linux/security/tomoyo/network.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * security/tomoyo/network.c
   4 *
   5 * Copyright (C) 2005-2011  NTT DATA CORPORATION
   6 */
   7
   8#include "common.h"
   9#include <linux/slab.h>
  10
  11/* Structure for holding inet domain socket's address. */
  12struct tomoyo_inet_addr_info {
  13        __be16 port;           /* In network byte order. */
  14        const __be32 *address; /* In network byte order. */
  15        bool is_ipv6;
  16};
  17
  18/* Structure for holding unix domain socket's address. */
  19struct tomoyo_unix_addr_info {
  20        u8 *addr; /* This may not be '\0' terminated string. */
  21        unsigned int addr_len;
  22};
  23
  24/* Structure for holding socket address. */
  25struct tomoyo_addr_info {
  26        u8 protocol;
  27        u8 operation;
  28        struct tomoyo_inet_addr_info inet;
  29        struct tomoyo_unix_addr_info unix0;
  30};
  31
  32/* String table for socket's protocols. */
  33const char * const tomoyo_proto_keyword[TOMOYO_SOCK_MAX] = {
  34        [SOCK_STREAM]    = "stream",
  35        [SOCK_DGRAM]     = "dgram",
  36        [SOCK_RAW]       = "raw",
  37        [SOCK_SEQPACKET] = "seqpacket",
  38        [0] = " ", /* Dummy for avoiding NULL pointer dereference. */
  39        [4] = " ", /* Dummy for avoiding NULL pointer dereference. */
  40};
  41
  42/**
  43 * tomoyo_parse_ipaddr_union - Parse an IP address.
  44 *
  45 * @param: Pointer to "struct tomoyo_acl_param".
  46 * @ptr:   Pointer to "struct tomoyo_ipaddr_union".
  47 *
  48 * Returns true on success, false otherwise.
  49 */
  50bool tomoyo_parse_ipaddr_union(struct tomoyo_acl_param *param,
  51                               struct tomoyo_ipaddr_union *ptr)
  52{
  53        u8 * const min = ptr->ip[0].in6_u.u6_addr8;
  54        u8 * const max = ptr->ip[1].in6_u.u6_addr8;
  55        char *address = tomoyo_read_token(param);
  56        const char *end;
  57
  58        if (!strchr(address, ':') &&
  59            in4_pton(address, -1, min, '-', &end) > 0) {
  60                ptr->is_ipv6 = false;
  61                if (!*end)
  62                        ptr->ip[1].s6_addr32[0] = ptr->ip[0].s6_addr32[0];
  63                else if (*end++ != '-' ||
  64                         in4_pton(end, -1, max, '\0', &end) <= 0 || *end)
  65                        return false;
  66                return true;
  67        }
  68        if (in6_pton(address, -1, min, '-', &end) > 0) {
  69                ptr->is_ipv6 = true;
  70                if (!*end)
  71                        memmove(max, min, sizeof(u16) * 8);
  72                else if (*end++ != '-' ||
  73                         in6_pton(end, -1, max, '\0', &end) <= 0 || *end)
  74                        return false;
  75                return true;
  76        }
  77        return false;
  78}
  79
  80/**
  81 * tomoyo_print_ipv4 - Print an IPv4 address.
  82 *
  83 * @buffer:     Buffer to write to.
  84 * @buffer_len: Size of @buffer.
  85 * @min_ip:     Pointer to __be32.
  86 * @max_ip:     Pointer to __be32.
  87 *
  88 * Returns nothing.
  89 */
  90static void tomoyo_print_ipv4(char *buffer, const unsigned int buffer_len,
  91                              const __be32 *min_ip, const __be32 *max_ip)
  92{
  93        snprintf(buffer, buffer_len, "%pI4%c%pI4", min_ip,
  94                 *min_ip == *max_ip ? '\0' : '-', max_ip);
  95}
  96
  97/**
  98 * tomoyo_print_ipv6 - Print an IPv6 address.
  99 *
 100 * @buffer:     Buffer to write to.
 101 * @buffer_len: Size of @buffer.
 102 * @min_ip:     Pointer to "struct in6_addr".
 103 * @max_ip:     Pointer to "struct in6_addr".
 104 *
 105 * Returns nothing.
 106 */
 107static void tomoyo_print_ipv6(char *buffer, const unsigned int buffer_len,
 108                              const struct in6_addr *min_ip,
 109                              const struct in6_addr *max_ip)
 110{
 111        snprintf(buffer, buffer_len, "%pI6c%c%pI6c", min_ip,
 112                 !memcmp(min_ip, max_ip, 16) ? '\0' : '-', max_ip);
 113}
 114
 115/**
 116 * tomoyo_print_ip - Print an IP address.
 117 *
 118 * @buf:  Buffer to write to.
 119 * @size: Size of @buf.
 120 * @ptr:  Pointer to "struct ipaddr_union".
 121 *
 122 * Returns nothing.
 123 */
 124void tomoyo_print_ip(char *buf, const unsigned int size,
 125                     const struct tomoyo_ipaddr_union *ptr)
 126{
 127        if (ptr->is_ipv6)
 128                tomoyo_print_ipv6(buf, size, &ptr->ip[0], &ptr->ip[1]);
 129        else
 130                tomoyo_print_ipv4(buf, size, &ptr->ip[0].s6_addr32[0],
 131                                  &ptr->ip[1].s6_addr32[0]);
 132}
 133
 134/*
 135 * Mapping table from "enum tomoyo_network_acl_index" to
 136 * "enum tomoyo_mac_index" for inet domain socket.
 137 */
 138static const u8 tomoyo_inet2mac
 139[TOMOYO_SOCK_MAX][TOMOYO_MAX_NETWORK_OPERATION] = {
 140        [SOCK_STREAM] = {
 141                [TOMOYO_NETWORK_BIND]    = TOMOYO_MAC_NETWORK_INET_STREAM_BIND,
 142                [TOMOYO_NETWORK_LISTEN]  =
 143                TOMOYO_MAC_NETWORK_INET_STREAM_LISTEN,
 144                [TOMOYO_NETWORK_CONNECT] =
 145                TOMOYO_MAC_NETWORK_INET_STREAM_CONNECT,
 146        },
 147        [SOCK_DGRAM] = {
 148                [TOMOYO_NETWORK_BIND]    = TOMOYO_MAC_NETWORK_INET_DGRAM_BIND,
 149                [TOMOYO_NETWORK_SEND]    = TOMOYO_MAC_NETWORK_INET_DGRAM_SEND,
 150        },
 151        [SOCK_RAW]    = {
 152                [TOMOYO_NETWORK_BIND]    = TOMOYO_MAC_NETWORK_INET_RAW_BIND,
 153                [TOMOYO_NETWORK_SEND]    = TOMOYO_MAC_NETWORK_INET_RAW_SEND,
 154        },
 155};
 156
 157/*
 158 * Mapping table from "enum tomoyo_network_acl_index" to
 159 * "enum tomoyo_mac_index" for unix domain socket.
 160 */
 161static const u8 tomoyo_unix2mac
 162[TOMOYO_SOCK_MAX][TOMOYO_MAX_NETWORK_OPERATION] = {
 163        [SOCK_STREAM] = {
 164                [TOMOYO_NETWORK_BIND]    = TOMOYO_MAC_NETWORK_UNIX_STREAM_BIND,
 165                [TOMOYO_NETWORK_LISTEN]  =
 166                TOMOYO_MAC_NETWORK_UNIX_STREAM_LISTEN,
 167                [TOMOYO_NETWORK_CONNECT] =
 168                TOMOYO_MAC_NETWORK_UNIX_STREAM_CONNECT,
 169        },
 170        [SOCK_DGRAM] = {
 171                [TOMOYO_NETWORK_BIND]    = TOMOYO_MAC_NETWORK_UNIX_DGRAM_BIND,
 172                [TOMOYO_NETWORK_SEND]    = TOMOYO_MAC_NETWORK_UNIX_DGRAM_SEND,
 173        },
 174        [SOCK_SEQPACKET] = {
 175                [TOMOYO_NETWORK_BIND]    =
 176                TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_BIND,
 177                [TOMOYO_NETWORK_LISTEN]  =
 178                TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_LISTEN,
 179                [TOMOYO_NETWORK_CONNECT] =
 180                TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_CONNECT,
 181        },
 182};
 183
 184/**
 185 * tomoyo_same_inet_acl - Check for duplicated "struct tomoyo_inet_acl" entry.
 186 *
 187 * @a: Pointer to "struct tomoyo_acl_info".
 188 * @b: Pointer to "struct tomoyo_acl_info".
 189 *
 190 * Returns true if @a == @b except permission bits, false otherwise.
 191 */
 192static bool tomoyo_same_inet_acl(const struct tomoyo_acl_info *a,
 193                                 const struct tomoyo_acl_info *b)
 194{
 195        const struct tomoyo_inet_acl *p1 = container_of(a, typeof(*p1), head);
 196        const struct tomoyo_inet_acl *p2 = container_of(b, typeof(*p2), head);
 197
 198        return p1->protocol == p2->protocol &&
 199                tomoyo_same_ipaddr_union(&p1->address, &p2->address) &&
 200                tomoyo_same_number_union(&p1->port, &p2->port);
 201}
 202
 203/**
 204 * tomoyo_same_unix_acl - Check for duplicated "struct tomoyo_unix_acl" entry.
 205 *
 206 * @a: Pointer to "struct tomoyo_acl_info".
 207 * @b: Pointer to "struct tomoyo_acl_info".
 208 *
 209 * Returns true if @a == @b except permission bits, false otherwise.
 210 */
 211static bool tomoyo_same_unix_acl(const struct tomoyo_acl_info *a,
 212                                 const struct tomoyo_acl_info *b)
 213{
 214        const struct tomoyo_unix_acl *p1 = container_of(a, typeof(*p1), head);
 215        const struct tomoyo_unix_acl *p2 = container_of(b, typeof(*p2), head);
 216
 217        return p1->protocol == p2->protocol &&
 218                tomoyo_same_name_union(&p1->name, &p2->name);
 219}
 220
 221/**
 222 * tomoyo_merge_inet_acl - Merge duplicated "struct tomoyo_inet_acl" entry.
 223 *
 224 * @a:         Pointer to "struct tomoyo_acl_info".
 225 * @b:         Pointer to "struct tomoyo_acl_info".
 226 * @is_delete: True for @a &= ~@b, false for @a |= @b.
 227 *
 228 * Returns true if @a is empty, false otherwise.
 229 */
 230static bool tomoyo_merge_inet_acl(struct tomoyo_acl_info *a,
 231                                  struct tomoyo_acl_info *b,
 232                                  const bool is_delete)
 233{
 234        u8 * const a_perm =
 235                &container_of(a, struct tomoyo_inet_acl, head)->perm;
 236        u8 perm = *a_perm;
 237        const u8 b_perm = container_of(b, struct tomoyo_inet_acl, head)->perm;
 238
 239        if (is_delete)
 240                perm &= ~b_perm;
 241        else
 242                perm |= b_perm;
 243        *a_perm = perm;
 244        return !perm;
 245}
 246
 247/**
 248 * tomoyo_merge_unix_acl - Merge duplicated "struct tomoyo_unix_acl" entry.
 249 *
 250 * @a:         Pointer to "struct tomoyo_acl_info".
 251 * @b:         Pointer to "struct tomoyo_acl_info".
 252 * @is_delete: True for @a &= ~@b, false for @a |= @b.
 253 *
 254 * Returns true if @a is empty, false otherwise.
 255 */
 256static bool tomoyo_merge_unix_acl(struct tomoyo_acl_info *a,
 257                                  struct tomoyo_acl_info *b,
 258                                  const bool is_delete)
 259{
 260        u8 * const a_perm =
 261                &container_of(a, struct tomoyo_unix_acl, head)->perm;
 262        u8 perm = *a_perm;
 263        const u8 b_perm = container_of(b, struct tomoyo_unix_acl, head)->perm;
 264
 265        if (is_delete)
 266                perm &= ~b_perm;
 267        else
 268                perm |= b_perm;
 269        *a_perm = perm;
 270        return !perm;
 271}
 272
 273/**
 274 * tomoyo_write_inet_network - Write "struct tomoyo_inet_acl" list.
 275 *
 276 * @param: Pointer to "struct tomoyo_acl_param".
 277 *
 278 * Returns 0 on success, negative value otherwise.
 279 *
 280 * Caller holds tomoyo_read_lock().
 281 */
 282int tomoyo_write_inet_network(struct tomoyo_acl_param *param)
 283{
 284        struct tomoyo_inet_acl e = { .head.type = TOMOYO_TYPE_INET_ACL };
 285        int error = -EINVAL;
 286        u8 type;
 287        const char *protocol = tomoyo_read_token(param);
 288        const char *operation = tomoyo_read_token(param);
 289
 290        for (e.protocol = 0; e.protocol < TOMOYO_SOCK_MAX; e.protocol++)
 291                if (!strcmp(protocol, tomoyo_proto_keyword[e.protocol]))
 292                        break;
 293        for (type = 0; type < TOMOYO_MAX_NETWORK_OPERATION; type++)
 294                if (tomoyo_permstr(operation, tomoyo_socket_keyword[type]))
 295                        e.perm |= 1 << type;
 296        if (e.protocol == TOMOYO_SOCK_MAX || !e.perm)
 297                return -EINVAL;
 298        if (param->data[0] == '@') {
 299                param->data++;
 300                e.address.group =
 301                        tomoyo_get_group(param, TOMOYO_ADDRESS_GROUP);
 302                if (!e.address.group)
 303                        return -ENOMEM;
 304        } else {
 305                if (!tomoyo_parse_ipaddr_union(param, &e.address))
 306                        goto out;
 307        }
 308        if (!tomoyo_parse_number_union(param, &e.port) ||
 309            e.port.values[1] > 65535)
 310                goto out;
 311        error = tomoyo_update_domain(&e.head, sizeof(e), param,
 312                                     tomoyo_same_inet_acl,
 313                                     tomoyo_merge_inet_acl);
 314out:
 315        tomoyo_put_group(e.address.group);
 316        tomoyo_put_number_union(&e.port);
 317        return error;
 318}
 319
 320/**
 321 * tomoyo_write_unix_network - Write "struct tomoyo_unix_acl" list.
 322 *
 323 * @param: Pointer to "struct tomoyo_acl_param".
 324 *
 325 * Returns 0 on success, negative value otherwise.
 326 */
 327int tomoyo_write_unix_network(struct tomoyo_acl_param *param)
 328{
 329        struct tomoyo_unix_acl e = { .head.type = TOMOYO_TYPE_UNIX_ACL };
 330        int error;
 331        u8 type;
 332        const char *protocol = tomoyo_read_token(param);
 333        const char *operation = tomoyo_read_token(param);
 334
 335        for (e.protocol = 0; e.protocol < TOMOYO_SOCK_MAX; e.protocol++)
 336                if (!strcmp(protocol, tomoyo_proto_keyword[e.protocol]))
 337                        break;
 338        for (type = 0; type < TOMOYO_MAX_NETWORK_OPERATION; type++)
 339                if (tomoyo_permstr(operation, tomoyo_socket_keyword[type]))
 340                        e.perm |= 1 << type;
 341        if (e.protocol == TOMOYO_SOCK_MAX || !e.perm)
 342                return -EINVAL;
 343        if (!tomoyo_parse_name_union(param, &e.name))
 344                return -EINVAL;
 345        error = tomoyo_update_domain(&e.head, sizeof(e), param,
 346                                     tomoyo_same_unix_acl,
 347                                     tomoyo_merge_unix_acl);
 348        tomoyo_put_name_union(&e.name);
 349        return error;
 350}
 351
 352/**
 353 * tomoyo_audit_net_log - Audit network log.
 354 *
 355 * @r:         Pointer to "struct tomoyo_request_info".
 356 * @family:    Name of socket family ("inet" or "unix").
 357 * @protocol:  Name of protocol in @family.
 358 * @operation: Name of socket operation.
 359 * @address:   Name of address.
 360 *
 361 * Returns 0 on success, negative value otherwise.
 362 */
 363static int tomoyo_audit_net_log(struct tomoyo_request_info *r,
 364                                const char *family, const u8 protocol,
 365                                const u8 operation, const char *address)
 366{
 367        return tomoyo_supervisor(r, "network %s %s %s %s\n", family,
 368                                 tomoyo_proto_keyword[protocol],
 369                                 tomoyo_socket_keyword[operation], address);
 370}
 371
 372/**
 373 * tomoyo_audit_inet_log - Audit INET network log.
 374 *
 375 * @r: Pointer to "struct tomoyo_request_info".
 376 *
 377 * Returns 0 on success, negative value otherwise.
 378 */
 379static int tomoyo_audit_inet_log(struct tomoyo_request_info *r)
 380{
 381        char buf[128];
 382        int len;
 383        const __be32 *address = r->param.inet_network.address;
 384
 385        if (r->param.inet_network.is_ipv6)
 386                tomoyo_print_ipv6(buf, sizeof(buf), (const struct in6_addr *)
 387                                  address, (const struct in6_addr *) address);
 388        else
 389                tomoyo_print_ipv4(buf, sizeof(buf), address, address);
 390        len = strlen(buf);
 391        snprintf(buf + len, sizeof(buf) - len, " %u",
 392                 r->param.inet_network.port);
 393        return tomoyo_audit_net_log(r, "inet", r->param.inet_network.protocol,
 394                                    r->param.inet_network.operation, buf);
 395}
 396
 397/**
 398 * tomoyo_audit_unix_log - Audit UNIX network log.
 399 *
 400 * @r: Pointer to "struct tomoyo_request_info".
 401 *
 402 * Returns 0 on success, negative value otherwise.
 403 */
 404static int tomoyo_audit_unix_log(struct tomoyo_request_info *r)
 405{
 406        return tomoyo_audit_net_log(r, "unix", r->param.unix_network.protocol,
 407                                    r->param.unix_network.operation,
 408                                    r->param.unix_network.address->name);
 409}
 410
 411/**
 412 * tomoyo_check_inet_acl - Check permission for inet domain socket operation.
 413 *
 414 * @r:   Pointer to "struct tomoyo_request_info".
 415 * @ptr: Pointer to "struct tomoyo_acl_info".
 416 *
 417 * Returns true if granted, false otherwise.
 418 */
 419static bool tomoyo_check_inet_acl(struct tomoyo_request_info *r,
 420                                  const struct tomoyo_acl_info *ptr)
 421{
 422        const struct tomoyo_inet_acl *acl =
 423                container_of(ptr, typeof(*acl), head);
 424        const u8 size = r->param.inet_network.is_ipv6 ? 16 : 4;
 425
 426        if (!(acl->perm & (1 << r->param.inet_network.operation)) ||
 427            !tomoyo_compare_number_union(r->param.inet_network.port,
 428                                         &acl->port))
 429                return false;
 430        if (acl->address.group)
 431                return tomoyo_address_matches_group
 432                        (r->param.inet_network.is_ipv6,
 433                         r->param.inet_network.address, acl->address.group);
 434        return acl->address.is_ipv6 == r->param.inet_network.is_ipv6 &&
 435                memcmp(&acl->address.ip[0],
 436                       r->param.inet_network.address, size) <= 0 &&
 437                memcmp(r->param.inet_network.address,
 438                       &acl->address.ip[1], size) <= 0;
 439}
 440
 441/**
 442 * tomoyo_check_unix_acl - Check permission for unix domain socket operation.
 443 *
 444 * @r:   Pointer to "struct tomoyo_request_info".
 445 * @ptr: Pointer to "struct tomoyo_acl_info".
 446 *
 447 * Returns true if granted, false otherwise.
 448 */
 449static bool tomoyo_check_unix_acl(struct tomoyo_request_info *r,
 450                                  const struct tomoyo_acl_info *ptr)
 451{
 452        const struct tomoyo_unix_acl *acl =
 453                container_of(ptr, typeof(*acl), head);
 454
 455        return (acl->perm & (1 << r->param.unix_network.operation)) &&
 456                tomoyo_compare_name_union(r->param.unix_network.address,
 457                                          &acl->name);
 458}
 459
 460/**
 461 * tomoyo_inet_entry - Check permission for INET network operation.
 462 *
 463 * @address: Pointer to "struct tomoyo_addr_info".
 464 *
 465 * Returns 0 on success, negative value otherwise.
 466 */
 467static int tomoyo_inet_entry(const struct tomoyo_addr_info *address)
 468{
 469        const int idx = tomoyo_read_lock();
 470        struct tomoyo_request_info r;
 471        int error = 0;
 472        const u8 type = tomoyo_inet2mac[address->protocol][address->operation];
 473
 474        if (type && tomoyo_init_request_info(&r, NULL, type)
 475            != TOMOYO_CONFIG_DISABLED) {
 476                r.param_type = TOMOYO_TYPE_INET_ACL;
 477                r.param.inet_network.protocol = address->protocol;
 478                r.param.inet_network.operation = address->operation;
 479                r.param.inet_network.is_ipv6 = address->inet.is_ipv6;
 480                r.param.inet_network.address = address->inet.address;
 481                r.param.inet_network.port = ntohs(address->inet.port);
 482                do {
 483                        tomoyo_check_acl(&r, tomoyo_check_inet_acl);
 484                        error = tomoyo_audit_inet_log(&r);
 485                } while (error == TOMOYO_RETRY_REQUEST);
 486        }
 487        tomoyo_read_unlock(idx);
 488        return error;
 489}
 490
 491/**
 492 * tomoyo_check_inet_address - Check permission for inet domain socket's operation.
 493 *
 494 * @addr:     Pointer to "struct sockaddr".
 495 * @addr_len: Size of @addr.
 496 * @port:     Port number.
 497 * @address:  Pointer to "struct tomoyo_addr_info".
 498 *
 499 * Returns 0 on success, negative value otherwise.
 500 */
 501static int tomoyo_check_inet_address(const struct sockaddr *addr,
 502                                     const unsigned int addr_len,
 503                                     const u16 port,
 504                                     struct tomoyo_addr_info *address)
 505{
 506        struct tomoyo_inet_addr_info *i = &address->inet;
 507
 508        switch (addr->sa_family) {
 509        case AF_INET6:
 510                if (addr_len < SIN6_LEN_RFC2133)
 511                        goto skip;
 512                i->is_ipv6 = true;
 513                i->address = (__be32 *)
 514                        ((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr;
 515                i->port = ((struct sockaddr_in6 *) addr)->sin6_port;
 516                break;
 517        case AF_INET:
 518                if (addr_len < sizeof(struct sockaddr_in))
 519                        goto skip;
 520                i->is_ipv6 = false;
 521                i->address = (__be32 *)
 522                        &((struct sockaddr_in *) addr)->sin_addr;
 523                i->port = ((struct sockaddr_in *) addr)->sin_port;
 524                break;
 525        default:
 526                goto skip;
 527        }
 528        if (address->protocol == SOCK_RAW)
 529                i->port = htons(port);
 530        return tomoyo_inet_entry(address);
 531skip:
 532        return 0;
 533}
 534
 535/**
 536 * tomoyo_unix_entry - Check permission for UNIX network operation.
 537 *
 538 * @address: Pointer to "struct tomoyo_addr_info".
 539 *
 540 * Returns 0 on success, negative value otherwise.
 541 */
 542static int tomoyo_unix_entry(const struct tomoyo_addr_info *address)
 543{
 544        const int idx = tomoyo_read_lock();
 545        struct tomoyo_request_info r;
 546        int error = 0;
 547        const u8 type = tomoyo_unix2mac[address->protocol][address->operation];
 548
 549        if (type && tomoyo_init_request_info(&r, NULL, type)
 550            != TOMOYO_CONFIG_DISABLED) {
 551                char *buf = address->unix0.addr;
 552                int len = address->unix0.addr_len - sizeof(sa_family_t);
 553
 554                if (len <= 0) {
 555                        buf = "anonymous";
 556                        len = 9;
 557                } else if (buf[0]) {
 558                        len = strnlen(buf, len);
 559                }
 560                buf = tomoyo_encode2(buf, len);
 561                if (buf) {
 562                        struct tomoyo_path_info addr;
 563
 564                        addr.name = buf;
 565                        tomoyo_fill_path_info(&addr);
 566                        r.param_type = TOMOYO_TYPE_UNIX_ACL;
 567                        r.param.unix_network.protocol = address->protocol;
 568                        r.param.unix_network.operation = address->operation;
 569                        r.param.unix_network.address = &addr;
 570                        do {
 571                                tomoyo_check_acl(&r, tomoyo_check_unix_acl);
 572                                error = tomoyo_audit_unix_log(&r);
 573                        } while (error == TOMOYO_RETRY_REQUEST);
 574                        kfree(buf);
 575                } else
 576                        error = -ENOMEM;
 577        }
 578        tomoyo_read_unlock(idx);
 579        return error;
 580}
 581
 582/**
 583 * tomoyo_check_unix_address - Check permission for unix domain socket's operation.
 584 *
 585 * @addr:     Pointer to "struct sockaddr".
 586 * @addr_len: Size of @addr.
 587 * @address:  Pointer to "struct tomoyo_addr_info".
 588 *
 589 * Returns 0 on success, negative value otherwise.
 590 */
 591static int tomoyo_check_unix_address(struct sockaddr *addr,
 592                                     const unsigned int addr_len,
 593                                     struct tomoyo_addr_info *address)
 594{
 595        struct tomoyo_unix_addr_info *u = &address->unix0;
 596
 597        if (addr->sa_family != AF_UNIX)
 598                return 0;
 599        u->addr = ((struct sockaddr_un *) addr)->sun_path;
 600        u->addr_len = addr_len;
 601        return tomoyo_unix_entry(address);
 602}
 603
 604/**
 605 * tomoyo_kernel_service - Check whether I'm kernel service or not.
 606 *
 607 * Returns true if I'm kernel service, false otherwise.
 608 */
 609static bool tomoyo_kernel_service(void)
 610{
 611        /* Nothing to do if I am a kernel service. */
 612        return uaccess_kernel();
 613}
 614
 615/**
 616 * tomoyo_sock_family - Get socket's family.
 617 *
 618 * @sk: Pointer to "struct sock".
 619 *
 620 * Returns one of PF_INET, PF_INET6, PF_UNIX or 0.
 621 */
 622static u8 tomoyo_sock_family(struct sock *sk)
 623{
 624        u8 family;
 625
 626        if (tomoyo_kernel_service())
 627                return 0;
 628        family = sk->sk_family;
 629        switch (family) {
 630        case PF_INET:
 631        case PF_INET6:
 632        case PF_UNIX:
 633                return family;
 634        default:
 635                return 0;
 636        }
 637}
 638
 639/**
 640 * tomoyo_socket_listen_permission - Check permission for listening a socket.
 641 *
 642 * @sock: Pointer to "struct socket".
 643 *
 644 * Returns 0 on success, negative value otherwise.
 645 */
 646int tomoyo_socket_listen_permission(struct socket *sock)
 647{
 648        struct tomoyo_addr_info address;
 649        const u8 family = tomoyo_sock_family(sock->sk);
 650        const unsigned int type = sock->type;
 651        struct sockaddr_storage addr;
 652        int addr_len;
 653
 654        if (!family || (type != SOCK_STREAM && type != SOCK_SEQPACKET))
 655                return 0;
 656        {
 657                const int error = sock->ops->getname(sock, (struct sockaddr *)
 658                                                     &addr, 0);
 659
 660                if (error < 0)
 661                        return error;
 662                addr_len = error;
 663        }
 664        address.protocol = type;
 665        address.operation = TOMOYO_NETWORK_LISTEN;
 666        if (family == PF_UNIX)
 667                return tomoyo_check_unix_address((struct sockaddr *) &addr,
 668                                                 addr_len, &address);
 669        return tomoyo_check_inet_address((struct sockaddr *) &addr, addr_len,
 670                                         0, &address);
 671}
 672
 673/**
 674 * tomoyo_socket_connect_permission - Check permission for setting the remote address of a socket.
 675 *
 676 * @sock:     Pointer to "struct socket".
 677 * @addr:     Pointer to "struct sockaddr".
 678 * @addr_len: Size of @addr.
 679 *
 680 * Returns 0 on success, negative value otherwise.
 681 */
 682int tomoyo_socket_connect_permission(struct socket *sock,
 683                                     struct sockaddr *addr, int addr_len)
 684{
 685        struct tomoyo_addr_info address;
 686        const u8 family = tomoyo_sock_family(sock->sk);
 687        const unsigned int type = sock->type;
 688
 689        if (!family)
 690                return 0;
 691        address.protocol = type;
 692        switch (type) {
 693        case SOCK_DGRAM:
 694        case SOCK_RAW:
 695                address.operation = TOMOYO_NETWORK_SEND;
 696                break;
 697        case SOCK_STREAM:
 698        case SOCK_SEQPACKET:
 699                address.operation = TOMOYO_NETWORK_CONNECT;
 700                break;
 701        default:
 702                return 0;
 703        }
 704        if (family == PF_UNIX)
 705                return tomoyo_check_unix_address(addr, addr_len, &address);
 706        return tomoyo_check_inet_address(addr, addr_len, sock->sk->sk_protocol,
 707                                         &address);
 708}
 709
 710/**
 711 * tomoyo_socket_bind_permission - Check permission for setting the local address of a socket.
 712 *
 713 * @sock:     Pointer to "struct socket".
 714 * @addr:     Pointer to "struct sockaddr".
 715 * @addr_len: Size of @addr.
 716 *
 717 * Returns 0 on success, negative value otherwise.
 718 */
 719int tomoyo_socket_bind_permission(struct socket *sock, struct sockaddr *addr,
 720                                  int addr_len)
 721{
 722        struct tomoyo_addr_info address;
 723        const u8 family = tomoyo_sock_family(sock->sk);
 724        const unsigned int type = sock->type;
 725
 726        if (!family)
 727                return 0;
 728        switch (type) {
 729        case SOCK_STREAM:
 730        case SOCK_DGRAM:
 731        case SOCK_RAW:
 732        case SOCK_SEQPACKET:
 733                address.protocol = type;
 734                address.operation = TOMOYO_NETWORK_BIND;
 735                break;
 736        default:
 737                return 0;
 738        }
 739        if (family == PF_UNIX)
 740                return tomoyo_check_unix_address(addr, addr_len, &address);
 741        return tomoyo_check_inet_address(addr, addr_len, sock->sk->sk_protocol,
 742                                         &address);
 743}
 744
 745/**
 746 * tomoyo_socket_sendmsg_permission - Check permission for sending a datagram.
 747 *
 748 * @sock: Pointer to "struct socket".
 749 * @msg:  Pointer to "struct msghdr".
 750 * @size: Unused.
 751 *
 752 * Returns 0 on success, negative value otherwise.
 753 */
 754int tomoyo_socket_sendmsg_permission(struct socket *sock, struct msghdr *msg,
 755                                     int size)
 756{
 757        struct tomoyo_addr_info address;
 758        const u8 family = tomoyo_sock_family(sock->sk);
 759        const unsigned int type = sock->type;
 760
 761        if (!msg->msg_name || !family ||
 762            (type != SOCK_DGRAM && type != SOCK_RAW))
 763                return 0;
 764        address.protocol = type;
 765        address.operation = TOMOYO_NETWORK_SEND;
 766        if (family == PF_UNIX)
 767                return tomoyo_check_unix_address((struct sockaddr *)
 768                                                 msg->msg_name,
 769                                                 msg->msg_namelen, &address);
 770        return tomoyo_check_inet_address((struct sockaddr *) msg->msg_name,
 771                                         msg->msg_namelen,
 772                                         sock->sk->sk_protocol, &address);
 773}
 774