1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 2059d84dbSTetsuo Handa /* 3059d84dbSTetsuo Handa * security/tomoyo/network.c 4059d84dbSTetsuo Handa * 5059d84dbSTetsuo Handa * Copyright (C) 2005-2011 NTT DATA CORPORATION 6059d84dbSTetsuo Handa */ 7059d84dbSTetsuo Handa 8059d84dbSTetsuo Handa #include "common.h" 9059d84dbSTetsuo Handa #include <linux/slab.h> 10059d84dbSTetsuo Handa 11059d84dbSTetsuo Handa /* Structure for holding inet domain socket's address. */ 12059d84dbSTetsuo Handa struct tomoyo_inet_addr_info { 13059d84dbSTetsuo Handa __be16 port; /* In network byte order. */ 14059d84dbSTetsuo Handa const __be32 *address; /* In network byte order. */ 15059d84dbSTetsuo Handa bool is_ipv6; 16059d84dbSTetsuo Handa }; 17059d84dbSTetsuo Handa 18059d84dbSTetsuo Handa /* Structure for holding unix domain socket's address. */ 19059d84dbSTetsuo Handa struct tomoyo_unix_addr_info { 20059d84dbSTetsuo Handa u8 *addr; /* This may not be '\0' terminated string. */ 21059d84dbSTetsuo Handa unsigned int addr_len; 22059d84dbSTetsuo Handa }; 23059d84dbSTetsuo Handa 24059d84dbSTetsuo Handa /* Structure for holding socket address. */ 25059d84dbSTetsuo Handa struct tomoyo_addr_info { 26059d84dbSTetsuo Handa u8 protocol; 27059d84dbSTetsuo Handa u8 operation; 28059d84dbSTetsuo Handa struct tomoyo_inet_addr_info inet; 29059d84dbSTetsuo Handa struct tomoyo_unix_addr_info unix0; 30059d84dbSTetsuo Handa }; 31059d84dbSTetsuo Handa 32059d84dbSTetsuo Handa /* String table for socket's protocols. */ 33059d84dbSTetsuo Handa const char * const tomoyo_proto_keyword[TOMOYO_SOCK_MAX] = { 34059d84dbSTetsuo Handa [SOCK_STREAM] = "stream", 35059d84dbSTetsuo Handa [SOCK_DGRAM] = "dgram", 36059d84dbSTetsuo Handa [SOCK_RAW] = "raw", 37059d84dbSTetsuo Handa [SOCK_SEQPACKET] = "seqpacket", 38059d84dbSTetsuo Handa [0] = " ", /* Dummy for avoiding NULL pointer dereference. */ 39059d84dbSTetsuo Handa [4] = " ", /* Dummy for avoiding NULL pointer dereference. */ 40059d84dbSTetsuo Handa }; 41059d84dbSTetsuo Handa 42059d84dbSTetsuo Handa /** 43059d84dbSTetsuo Handa * tomoyo_parse_ipaddr_union - Parse an IP address. 44059d84dbSTetsuo Handa * 45059d84dbSTetsuo Handa * @param: Pointer to "struct tomoyo_acl_param". 46059d84dbSTetsuo Handa * @ptr: Pointer to "struct tomoyo_ipaddr_union". 47059d84dbSTetsuo Handa * 48059d84dbSTetsuo Handa * Returns true on success, false otherwise. 49059d84dbSTetsuo Handa */ 50059d84dbSTetsuo Handa bool tomoyo_parse_ipaddr_union(struct tomoyo_acl_param *param, 51059d84dbSTetsuo Handa struct tomoyo_ipaddr_union *ptr) 52059d84dbSTetsuo Handa { 53059d84dbSTetsuo Handa u8 * const min = ptr->ip[0].in6_u.u6_addr8; 54059d84dbSTetsuo Handa u8 * const max = ptr->ip[1].in6_u.u6_addr8; 55059d84dbSTetsuo Handa char *address = tomoyo_read_token(param); 56059d84dbSTetsuo Handa const char *end; 57059d84dbSTetsuo Handa 58059d84dbSTetsuo Handa if (!strchr(address, ':') && 59059d84dbSTetsuo Handa in4_pton(address, -1, min, '-', &end) > 0) { 60059d84dbSTetsuo Handa ptr->is_ipv6 = false; 61059d84dbSTetsuo Handa if (!*end) 62059d84dbSTetsuo Handa ptr->ip[1].s6_addr32[0] = ptr->ip[0].s6_addr32[0]; 63059d84dbSTetsuo Handa else if (*end++ != '-' || 64059d84dbSTetsuo Handa in4_pton(end, -1, max, '\0', &end) <= 0 || *end) 65059d84dbSTetsuo Handa return false; 66059d84dbSTetsuo Handa return true; 67059d84dbSTetsuo Handa } 68059d84dbSTetsuo Handa if (in6_pton(address, -1, min, '-', &end) > 0) { 69059d84dbSTetsuo Handa ptr->is_ipv6 = true; 70059d84dbSTetsuo Handa if (!*end) 71059d84dbSTetsuo Handa memmove(max, min, sizeof(u16) * 8); 72059d84dbSTetsuo Handa else if (*end++ != '-' || 73059d84dbSTetsuo Handa in6_pton(end, -1, max, '\0', &end) <= 0 || *end) 74059d84dbSTetsuo Handa return false; 75059d84dbSTetsuo Handa return true; 76059d84dbSTetsuo Handa } 77059d84dbSTetsuo Handa return false; 78059d84dbSTetsuo Handa } 79059d84dbSTetsuo Handa 80059d84dbSTetsuo Handa /** 81059d84dbSTetsuo Handa * tomoyo_print_ipv4 - Print an IPv4 address. 82059d84dbSTetsuo Handa * 83059d84dbSTetsuo Handa * @buffer: Buffer to write to. 84059d84dbSTetsuo Handa * @buffer_len: Size of @buffer. 85059d84dbSTetsuo Handa * @min_ip: Pointer to __be32. 86059d84dbSTetsuo Handa * @max_ip: Pointer to __be32. 87059d84dbSTetsuo Handa * 88059d84dbSTetsuo Handa * Returns nothing. 89059d84dbSTetsuo Handa */ 90059d84dbSTetsuo Handa static void tomoyo_print_ipv4(char *buffer, const unsigned int buffer_len, 91059d84dbSTetsuo Handa const __be32 *min_ip, const __be32 *max_ip) 92059d84dbSTetsuo Handa { 93059d84dbSTetsuo Handa snprintf(buffer, buffer_len, "%pI4%c%pI4", min_ip, 94059d84dbSTetsuo Handa *min_ip == *max_ip ? '\0' : '-', max_ip); 95059d84dbSTetsuo Handa } 96059d84dbSTetsuo Handa 97059d84dbSTetsuo Handa /** 98059d84dbSTetsuo Handa * tomoyo_print_ipv6 - Print an IPv6 address. 99059d84dbSTetsuo Handa * 100059d84dbSTetsuo Handa * @buffer: Buffer to write to. 101059d84dbSTetsuo Handa * @buffer_len: Size of @buffer. 102059d84dbSTetsuo Handa * @min_ip: Pointer to "struct in6_addr". 103059d84dbSTetsuo Handa * @max_ip: Pointer to "struct in6_addr". 104059d84dbSTetsuo Handa * 105059d84dbSTetsuo Handa * Returns nothing. 106059d84dbSTetsuo Handa */ 107059d84dbSTetsuo Handa static void tomoyo_print_ipv6(char *buffer, const unsigned int buffer_len, 108059d84dbSTetsuo Handa const struct in6_addr *min_ip, 109059d84dbSTetsuo Handa const struct in6_addr *max_ip) 110059d84dbSTetsuo Handa { 111059d84dbSTetsuo Handa snprintf(buffer, buffer_len, "%pI6c%c%pI6c", min_ip, 112059d84dbSTetsuo Handa !memcmp(min_ip, max_ip, 16) ? '\0' : '-', max_ip); 113059d84dbSTetsuo Handa } 114059d84dbSTetsuo Handa 115059d84dbSTetsuo Handa /** 116059d84dbSTetsuo Handa * tomoyo_print_ip - Print an IP address. 117059d84dbSTetsuo Handa * 118059d84dbSTetsuo Handa * @buf: Buffer to write to. 119059d84dbSTetsuo Handa * @size: Size of @buf. 120059d84dbSTetsuo Handa * @ptr: Pointer to "struct ipaddr_union". 121059d84dbSTetsuo Handa * 122059d84dbSTetsuo Handa * Returns nothing. 123059d84dbSTetsuo Handa */ 124059d84dbSTetsuo Handa void tomoyo_print_ip(char *buf, const unsigned int size, 125059d84dbSTetsuo Handa const struct tomoyo_ipaddr_union *ptr) 126059d84dbSTetsuo Handa { 127059d84dbSTetsuo Handa if (ptr->is_ipv6) 128059d84dbSTetsuo Handa tomoyo_print_ipv6(buf, size, &ptr->ip[0], &ptr->ip[1]); 129059d84dbSTetsuo Handa else 130059d84dbSTetsuo Handa tomoyo_print_ipv4(buf, size, &ptr->ip[0].s6_addr32[0], 131059d84dbSTetsuo Handa &ptr->ip[1].s6_addr32[0]); 132059d84dbSTetsuo Handa } 133059d84dbSTetsuo Handa 134059d84dbSTetsuo Handa /* 135059d84dbSTetsuo Handa * Mapping table from "enum tomoyo_network_acl_index" to 136059d84dbSTetsuo Handa * "enum tomoyo_mac_index" for inet domain socket. 137059d84dbSTetsuo Handa */ 138059d84dbSTetsuo Handa static const u8 tomoyo_inet2mac 139059d84dbSTetsuo Handa [TOMOYO_SOCK_MAX][TOMOYO_MAX_NETWORK_OPERATION] = { 140059d84dbSTetsuo Handa [SOCK_STREAM] = { 141059d84dbSTetsuo Handa [TOMOYO_NETWORK_BIND] = TOMOYO_MAC_NETWORK_INET_STREAM_BIND, 142059d84dbSTetsuo Handa [TOMOYO_NETWORK_LISTEN] = 143059d84dbSTetsuo Handa TOMOYO_MAC_NETWORK_INET_STREAM_LISTEN, 144059d84dbSTetsuo Handa [TOMOYO_NETWORK_CONNECT] = 145059d84dbSTetsuo Handa TOMOYO_MAC_NETWORK_INET_STREAM_CONNECT, 146059d84dbSTetsuo Handa }, 147059d84dbSTetsuo Handa [SOCK_DGRAM] = { 148059d84dbSTetsuo Handa [TOMOYO_NETWORK_BIND] = TOMOYO_MAC_NETWORK_INET_DGRAM_BIND, 149059d84dbSTetsuo Handa [TOMOYO_NETWORK_SEND] = TOMOYO_MAC_NETWORK_INET_DGRAM_SEND, 150059d84dbSTetsuo Handa }, 151059d84dbSTetsuo Handa [SOCK_RAW] = { 152059d84dbSTetsuo Handa [TOMOYO_NETWORK_BIND] = TOMOYO_MAC_NETWORK_INET_RAW_BIND, 153059d84dbSTetsuo Handa [TOMOYO_NETWORK_SEND] = TOMOYO_MAC_NETWORK_INET_RAW_SEND, 154059d84dbSTetsuo Handa }, 155059d84dbSTetsuo Handa }; 156059d84dbSTetsuo Handa 157059d84dbSTetsuo Handa /* 158059d84dbSTetsuo Handa * Mapping table from "enum tomoyo_network_acl_index" to 159059d84dbSTetsuo Handa * "enum tomoyo_mac_index" for unix domain socket. 160059d84dbSTetsuo Handa */ 161059d84dbSTetsuo Handa static const u8 tomoyo_unix2mac 162059d84dbSTetsuo Handa [TOMOYO_SOCK_MAX][TOMOYO_MAX_NETWORK_OPERATION] = { 163059d84dbSTetsuo Handa [SOCK_STREAM] = { 164059d84dbSTetsuo Handa [TOMOYO_NETWORK_BIND] = TOMOYO_MAC_NETWORK_UNIX_STREAM_BIND, 165059d84dbSTetsuo Handa [TOMOYO_NETWORK_LISTEN] = 166059d84dbSTetsuo Handa TOMOYO_MAC_NETWORK_UNIX_STREAM_LISTEN, 167059d84dbSTetsuo Handa [TOMOYO_NETWORK_CONNECT] = 168059d84dbSTetsuo Handa TOMOYO_MAC_NETWORK_UNIX_STREAM_CONNECT, 169059d84dbSTetsuo Handa }, 170059d84dbSTetsuo Handa [SOCK_DGRAM] = { 171059d84dbSTetsuo Handa [TOMOYO_NETWORK_BIND] = TOMOYO_MAC_NETWORK_UNIX_DGRAM_BIND, 172059d84dbSTetsuo Handa [TOMOYO_NETWORK_SEND] = TOMOYO_MAC_NETWORK_UNIX_DGRAM_SEND, 173059d84dbSTetsuo Handa }, 174059d84dbSTetsuo Handa [SOCK_SEQPACKET] = { 175059d84dbSTetsuo Handa [TOMOYO_NETWORK_BIND] = 176059d84dbSTetsuo Handa TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_BIND, 177059d84dbSTetsuo Handa [TOMOYO_NETWORK_LISTEN] = 178059d84dbSTetsuo Handa TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_LISTEN, 179059d84dbSTetsuo Handa [TOMOYO_NETWORK_CONNECT] = 180059d84dbSTetsuo Handa TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_CONNECT, 181059d84dbSTetsuo Handa }, 182059d84dbSTetsuo Handa }; 183059d84dbSTetsuo Handa 184059d84dbSTetsuo Handa /** 185059d84dbSTetsuo Handa * tomoyo_same_inet_acl - Check for duplicated "struct tomoyo_inet_acl" entry. 186059d84dbSTetsuo Handa * 187059d84dbSTetsuo Handa * @a: Pointer to "struct tomoyo_acl_info". 188059d84dbSTetsuo Handa * @b: Pointer to "struct tomoyo_acl_info". 189059d84dbSTetsuo Handa * 190059d84dbSTetsuo Handa * Returns true if @a == @b except permission bits, false otherwise. 191059d84dbSTetsuo Handa */ 192059d84dbSTetsuo Handa static bool tomoyo_same_inet_acl(const struct tomoyo_acl_info *a, 193059d84dbSTetsuo Handa const struct tomoyo_acl_info *b) 194059d84dbSTetsuo Handa { 195059d84dbSTetsuo Handa const struct tomoyo_inet_acl *p1 = container_of(a, typeof(*p1), head); 196059d84dbSTetsuo Handa const struct tomoyo_inet_acl *p2 = container_of(b, typeof(*p2), head); 197059d84dbSTetsuo Handa 198059d84dbSTetsuo Handa return p1->protocol == p2->protocol && 199059d84dbSTetsuo Handa tomoyo_same_ipaddr_union(&p1->address, &p2->address) && 200059d84dbSTetsuo Handa tomoyo_same_number_union(&p1->port, &p2->port); 201059d84dbSTetsuo Handa } 202059d84dbSTetsuo Handa 203059d84dbSTetsuo Handa /** 204059d84dbSTetsuo Handa * tomoyo_same_unix_acl - Check for duplicated "struct tomoyo_unix_acl" entry. 205059d84dbSTetsuo Handa * 206059d84dbSTetsuo Handa * @a: Pointer to "struct tomoyo_acl_info". 207059d84dbSTetsuo Handa * @b: Pointer to "struct tomoyo_acl_info". 208059d84dbSTetsuo Handa * 209059d84dbSTetsuo Handa * Returns true if @a == @b except permission bits, false otherwise. 210059d84dbSTetsuo Handa */ 211059d84dbSTetsuo Handa static bool tomoyo_same_unix_acl(const struct tomoyo_acl_info *a, 212059d84dbSTetsuo Handa const struct tomoyo_acl_info *b) 213059d84dbSTetsuo Handa { 214059d84dbSTetsuo Handa const struct tomoyo_unix_acl *p1 = container_of(a, typeof(*p1), head); 215059d84dbSTetsuo Handa const struct tomoyo_unix_acl *p2 = container_of(b, typeof(*p2), head); 216059d84dbSTetsuo Handa 217059d84dbSTetsuo Handa return p1->protocol == p2->protocol && 218059d84dbSTetsuo Handa tomoyo_same_name_union(&p1->name, &p2->name); 219059d84dbSTetsuo Handa } 220059d84dbSTetsuo Handa 221059d84dbSTetsuo Handa /** 222059d84dbSTetsuo Handa * tomoyo_merge_inet_acl - Merge duplicated "struct tomoyo_inet_acl" entry. 223059d84dbSTetsuo Handa * 224059d84dbSTetsuo Handa * @a: Pointer to "struct tomoyo_acl_info". 225059d84dbSTetsuo Handa * @b: Pointer to "struct tomoyo_acl_info". 226059d84dbSTetsuo Handa * @is_delete: True for @a &= ~@b, false for @a |= @b. 227059d84dbSTetsuo Handa * 228059d84dbSTetsuo Handa * Returns true if @a is empty, false otherwise. 229059d84dbSTetsuo Handa */ 230059d84dbSTetsuo Handa static bool tomoyo_merge_inet_acl(struct tomoyo_acl_info *a, 231059d84dbSTetsuo Handa struct tomoyo_acl_info *b, 232059d84dbSTetsuo Handa const bool is_delete) 233059d84dbSTetsuo Handa { 234059d84dbSTetsuo Handa u8 * const a_perm = 235059d84dbSTetsuo Handa &container_of(a, struct tomoyo_inet_acl, head)->perm; 236059d84dbSTetsuo Handa u8 perm = *a_perm; 237059d84dbSTetsuo Handa const u8 b_perm = container_of(b, struct tomoyo_inet_acl, head)->perm; 238059d84dbSTetsuo Handa 239059d84dbSTetsuo Handa if (is_delete) 240059d84dbSTetsuo Handa perm &= ~b_perm; 241059d84dbSTetsuo Handa else 242059d84dbSTetsuo Handa perm |= b_perm; 243059d84dbSTetsuo Handa *a_perm = perm; 244059d84dbSTetsuo Handa return !perm; 245059d84dbSTetsuo Handa } 246059d84dbSTetsuo Handa 247059d84dbSTetsuo Handa /** 248059d84dbSTetsuo Handa * tomoyo_merge_unix_acl - Merge duplicated "struct tomoyo_unix_acl" entry. 249059d84dbSTetsuo Handa * 250059d84dbSTetsuo Handa * @a: Pointer to "struct tomoyo_acl_info". 251059d84dbSTetsuo Handa * @b: Pointer to "struct tomoyo_acl_info". 252059d84dbSTetsuo Handa * @is_delete: True for @a &= ~@b, false for @a |= @b. 253059d84dbSTetsuo Handa * 254059d84dbSTetsuo Handa * Returns true if @a is empty, false otherwise. 255059d84dbSTetsuo Handa */ 256059d84dbSTetsuo Handa static bool tomoyo_merge_unix_acl(struct tomoyo_acl_info *a, 257059d84dbSTetsuo Handa struct tomoyo_acl_info *b, 258059d84dbSTetsuo Handa const bool is_delete) 259059d84dbSTetsuo Handa { 260059d84dbSTetsuo Handa u8 * const a_perm = 261059d84dbSTetsuo Handa &container_of(a, struct tomoyo_unix_acl, head)->perm; 262059d84dbSTetsuo Handa u8 perm = *a_perm; 263059d84dbSTetsuo Handa const u8 b_perm = container_of(b, struct tomoyo_unix_acl, head)->perm; 264059d84dbSTetsuo Handa 265059d84dbSTetsuo Handa if (is_delete) 266059d84dbSTetsuo Handa perm &= ~b_perm; 267059d84dbSTetsuo Handa else 268059d84dbSTetsuo Handa perm |= b_perm; 269059d84dbSTetsuo Handa *a_perm = perm; 270059d84dbSTetsuo Handa return !perm; 271059d84dbSTetsuo Handa } 272059d84dbSTetsuo Handa 273059d84dbSTetsuo Handa /** 274059d84dbSTetsuo Handa * tomoyo_write_inet_network - Write "struct tomoyo_inet_acl" list. 275059d84dbSTetsuo Handa * 276059d84dbSTetsuo Handa * @param: Pointer to "struct tomoyo_acl_param". 277059d84dbSTetsuo Handa * 278059d84dbSTetsuo Handa * Returns 0 on success, negative value otherwise. 279059d84dbSTetsuo Handa * 280059d84dbSTetsuo Handa * Caller holds tomoyo_read_lock(). 281059d84dbSTetsuo Handa */ 282059d84dbSTetsuo Handa int tomoyo_write_inet_network(struct tomoyo_acl_param *param) 283059d84dbSTetsuo Handa { 284059d84dbSTetsuo Handa struct tomoyo_inet_acl e = { .head.type = TOMOYO_TYPE_INET_ACL }; 285059d84dbSTetsuo Handa int error = -EINVAL; 286059d84dbSTetsuo Handa u8 type; 287059d84dbSTetsuo Handa const char *protocol = tomoyo_read_token(param); 288059d84dbSTetsuo Handa const char *operation = tomoyo_read_token(param); 289059d84dbSTetsuo Handa 290059d84dbSTetsuo Handa for (e.protocol = 0; e.protocol < TOMOYO_SOCK_MAX; e.protocol++) 291059d84dbSTetsuo Handa if (!strcmp(protocol, tomoyo_proto_keyword[e.protocol])) 292059d84dbSTetsuo Handa break; 293059d84dbSTetsuo Handa for (type = 0; type < TOMOYO_MAX_NETWORK_OPERATION; type++) 294059d84dbSTetsuo Handa if (tomoyo_permstr(operation, tomoyo_socket_keyword[type])) 295059d84dbSTetsuo Handa e.perm |= 1 << type; 296059d84dbSTetsuo Handa if (e.protocol == TOMOYO_SOCK_MAX || !e.perm) 297059d84dbSTetsuo Handa return -EINVAL; 298059d84dbSTetsuo Handa if (param->data[0] == '@') { 299059d84dbSTetsuo Handa param->data++; 300059d84dbSTetsuo Handa e.address.group = 301059d84dbSTetsuo Handa tomoyo_get_group(param, TOMOYO_ADDRESS_GROUP); 302059d84dbSTetsuo Handa if (!e.address.group) 303059d84dbSTetsuo Handa return -ENOMEM; 304059d84dbSTetsuo Handa } else { 305059d84dbSTetsuo Handa if (!tomoyo_parse_ipaddr_union(param, &e.address)) 306059d84dbSTetsuo Handa goto out; 307059d84dbSTetsuo Handa } 308059d84dbSTetsuo Handa if (!tomoyo_parse_number_union(param, &e.port) || 309059d84dbSTetsuo Handa e.port.values[1] > 65535) 310059d84dbSTetsuo Handa goto out; 311059d84dbSTetsuo Handa error = tomoyo_update_domain(&e.head, sizeof(e), param, 312059d84dbSTetsuo Handa tomoyo_same_inet_acl, 313059d84dbSTetsuo Handa tomoyo_merge_inet_acl); 314059d84dbSTetsuo Handa out: 315059d84dbSTetsuo Handa tomoyo_put_group(e.address.group); 316059d84dbSTetsuo Handa tomoyo_put_number_union(&e.port); 317059d84dbSTetsuo Handa return error; 318059d84dbSTetsuo Handa } 319059d84dbSTetsuo Handa 320059d84dbSTetsuo Handa /** 321059d84dbSTetsuo Handa * tomoyo_write_unix_network - Write "struct tomoyo_unix_acl" list. 322059d84dbSTetsuo Handa * 323059d84dbSTetsuo Handa * @param: Pointer to "struct tomoyo_acl_param". 324059d84dbSTetsuo Handa * 325059d84dbSTetsuo Handa * Returns 0 on success, negative value otherwise. 326059d84dbSTetsuo Handa */ 327059d84dbSTetsuo Handa int tomoyo_write_unix_network(struct tomoyo_acl_param *param) 328059d84dbSTetsuo Handa { 329059d84dbSTetsuo Handa struct tomoyo_unix_acl e = { .head.type = TOMOYO_TYPE_UNIX_ACL }; 330059d84dbSTetsuo Handa int error; 331059d84dbSTetsuo Handa u8 type; 332059d84dbSTetsuo Handa const char *protocol = tomoyo_read_token(param); 333059d84dbSTetsuo Handa const char *operation = tomoyo_read_token(param); 334059d84dbSTetsuo Handa 335059d84dbSTetsuo Handa for (e.protocol = 0; e.protocol < TOMOYO_SOCK_MAX; e.protocol++) 336059d84dbSTetsuo Handa if (!strcmp(protocol, tomoyo_proto_keyword[e.protocol])) 337059d84dbSTetsuo Handa break; 338059d84dbSTetsuo Handa for (type = 0; type < TOMOYO_MAX_NETWORK_OPERATION; type++) 339059d84dbSTetsuo Handa if (tomoyo_permstr(operation, tomoyo_socket_keyword[type])) 340059d84dbSTetsuo Handa e.perm |= 1 << type; 341059d84dbSTetsuo Handa if (e.protocol == TOMOYO_SOCK_MAX || !e.perm) 342059d84dbSTetsuo Handa return -EINVAL; 343059d84dbSTetsuo Handa if (!tomoyo_parse_name_union(param, &e.name)) 344059d84dbSTetsuo Handa return -EINVAL; 345059d84dbSTetsuo Handa error = tomoyo_update_domain(&e.head, sizeof(e), param, 346059d84dbSTetsuo Handa tomoyo_same_unix_acl, 347059d84dbSTetsuo Handa tomoyo_merge_unix_acl); 348059d84dbSTetsuo Handa tomoyo_put_name_union(&e.name); 349059d84dbSTetsuo Handa return error; 350059d84dbSTetsuo Handa } 351059d84dbSTetsuo Handa 352059d84dbSTetsuo Handa /** 353059d84dbSTetsuo Handa * tomoyo_audit_net_log - Audit network log. 354059d84dbSTetsuo Handa * 355059d84dbSTetsuo Handa * @r: Pointer to "struct tomoyo_request_info". 356059d84dbSTetsuo Handa * @family: Name of socket family ("inet" or "unix"). 357059d84dbSTetsuo Handa * @protocol: Name of protocol in @family. 358059d84dbSTetsuo Handa * @operation: Name of socket operation. 359059d84dbSTetsuo Handa * @address: Name of address. 360059d84dbSTetsuo Handa * 361059d84dbSTetsuo Handa * Returns 0 on success, negative value otherwise. 362059d84dbSTetsuo Handa */ 363059d84dbSTetsuo Handa static int tomoyo_audit_net_log(struct tomoyo_request_info *r, 364059d84dbSTetsuo Handa const char *family, const u8 protocol, 365059d84dbSTetsuo Handa const u8 operation, const char *address) 366059d84dbSTetsuo Handa { 367059d84dbSTetsuo Handa return tomoyo_supervisor(r, "network %s %s %s %s\n", family, 368059d84dbSTetsuo Handa tomoyo_proto_keyword[protocol], 369059d84dbSTetsuo Handa tomoyo_socket_keyword[operation], address); 370059d84dbSTetsuo Handa } 371059d84dbSTetsuo Handa 372059d84dbSTetsuo Handa /** 373059d84dbSTetsuo Handa * tomoyo_audit_inet_log - Audit INET network log. 374059d84dbSTetsuo Handa * 375059d84dbSTetsuo Handa * @r: Pointer to "struct tomoyo_request_info". 376059d84dbSTetsuo Handa * 377059d84dbSTetsuo Handa * Returns 0 on success, negative value otherwise. 378059d84dbSTetsuo Handa */ 379059d84dbSTetsuo Handa static int tomoyo_audit_inet_log(struct tomoyo_request_info *r) 380059d84dbSTetsuo Handa { 381059d84dbSTetsuo Handa char buf[128]; 382059d84dbSTetsuo Handa int len; 383059d84dbSTetsuo Handa const __be32 *address = r->param.inet_network.address; 384059d84dbSTetsuo Handa 385059d84dbSTetsuo Handa if (r->param.inet_network.is_ipv6) 386059d84dbSTetsuo Handa tomoyo_print_ipv6(buf, sizeof(buf), (const struct in6_addr *) 387059d84dbSTetsuo Handa address, (const struct in6_addr *) address); 388059d84dbSTetsuo Handa else 389059d84dbSTetsuo Handa tomoyo_print_ipv4(buf, sizeof(buf), address, address); 390059d84dbSTetsuo Handa len = strlen(buf); 391059d84dbSTetsuo Handa snprintf(buf + len, sizeof(buf) - len, " %u", 392059d84dbSTetsuo Handa r->param.inet_network.port); 393059d84dbSTetsuo Handa return tomoyo_audit_net_log(r, "inet", r->param.inet_network.protocol, 394059d84dbSTetsuo Handa r->param.inet_network.operation, buf); 395059d84dbSTetsuo Handa } 396059d84dbSTetsuo Handa 397059d84dbSTetsuo Handa /** 398059d84dbSTetsuo Handa * tomoyo_audit_unix_log - Audit UNIX network log. 399059d84dbSTetsuo Handa * 400059d84dbSTetsuo Handa * @r: Pointer to "struct tomoyo_request_info". 401059d84dbSTetsuo Handa * 402059d84dbSTetsuo Handa * Returns 0 on success, negative value otherwise. 403059d84dbSTetsuo Handa */ 404059d84dbSTetsuo Handa static int tomoyo_audit_unix_log(struct tomoyo_request_info *r) 405059d84dbSTetsuo Handa { 406059d84dbSTetsuo Handa return tomoyo_audit_net_log(r, "unix", r->param.unix_network.protocol, 407059d84dbSTetsuo Handa r->param.unix_network.operation, 408059d84dbSTetsuo Handa r->param.unix_network.address->name); 409059d84dbSTetsuo Handa } 410059d84dbSTetsuo Handa 411059d84dbSTetsuo Handa /** 412059d84dbSTetsuo Handa * tomoyo_check_inet_acl - Check permission for inet domain socket operation. 413059d84dbSTetsuo Handa * 414059d84dbSTetsuo Handa * @r: Pointer to "struct tomoyo_request_info". 415059d84dbSTetsuo Handa * @ptr: Pointer to "struct tomoyo_acl_info". 416059d84dbSTetsuo Handa * 417059d84dbSTetsuo Handa * Returns true if granted, false otherwise. 418059d84dbSTetsuo Handa */ 419059d84dbSTetsuo Handa static bool tomoyo_check_inet_acl(struct tomoyo_request_info *r, 420059d84dbSTetsuo Handa const struct tomoyo_acl_info *ptr) 421059d84dbSTetsuo Handa { 422059d84dbSTetsuo Handa const struct tomoyo_inet_acl *acl = 423059d84dbSTetsuo Handa container_of(ptr, typeof(*acl), head); 424059d84dbSTetsuo Handa const u8 size = r->param.inet_network.is_ipv6 ? 16 : 4; 425059d84dbSTetsuo Handa 426059d84dbSTetsuo Handa if (!(acl->perm & (1 << r->param.inet_network.operation)) || 427059d84dbSTetsuo Handa !tomoyo_compare_number_union(r->param.inet_network.port, 428059d84dbSTetsuo Handa &acl->port)) 429059d84dbSTetsuo Handa return false; 430059d84dbSTetsuo Handa if (acl->address.group) 431059d84dbSTetsuo Handa return tomoyo_address_matches_group 432059d84dbSTetsuo Handa (r->param.inet_network.is_ipv6, 433059d84dbSTetsuo Handa r->param.inet_network.address, acl->address.group); 434059d84dbSTetsuo Handa return acl->address.is_ipv6 == r->param.inet_network.is_ipv6 && 435059d84dbSTetsuo Handa memcmp(&acl->address.ip[0], 436059d84dbSTetsuo Handa r->param.inet_network.address, size) <= 0 && 437059d84dbSTetsuo Handa memcmp(r->param.inet_network.address, 438059d84dbSTetsuo Handa &acl->address.ip[1], size) <= 0; 439059d84dbSTetsuo Handa } 440059d84dbSTetsuo Handa 441059d84dbSTetsuo Handa /** 442059d84dbSTetsuo Handa * tomoyo_check_unix_acl - Check permission for unix domain socket operation. 443059d84dbSTetsuo Handa * 444059d84dbSTetsuo Handa * @r: Pointer to "struct tomoyo_request_info". 445059d84dbSTetsuo Handa * @ptr: Pointer to "struct tomoyo_acl_info". 446059d84dbSTetsuo Handa * 447059d84dbSTetsuo Handa * Returns true if granted, false otherwise. 448059d84dbSTetsuo Handa */ 449059d84dbSTetsuo Handa static bool tomoyo_check_unix_acl(struct tomoyo_request_info *r, 450059d84dbSTetsuo Handa const struct tomoyo_acl_info *ptr) 451059d84dbSTetsuo Handa { 452059d84dbSTetsuo Handa const struct tomoyo_unix_acl *acl = 453059d84dbSTetsuo Handa container_of(ptr, typeof(*acl), head); 454059d84dbSTetsuo Handa 455059d84dbSTetsuo Handa return (acl->perm & (1 << r->param.unix_network.operation)) && 456059d84dbSTetsuo Handa tomoyo_compare_name_union(r->param.unix_network.address, 457059d84dbSTetsuo Handa &acl->name); 458059d84dbSTetsuo Handa } 459059d84dbSTetsuo Handa 460059d84dbSTetsuo Handa /** 461059d84dbSTetsuo Handa * tomoyo_inet_entry - Check permission for INET network operation. 462059d84dbSTetsuo Handa * 463059d84dbSTetsuo Handa * @address: Pointer to "struct tomoyo_addr_info". 464059d84dbSTetsuo Handa * 465059d84dbSTetsuo Handa * Returns 0 on success, negative value otherwise. 466059d84dbSTetsuo Handa */ 467059d84dbSTetsuo Handa static int tomoyo_inet_entry(const struct tomoyo_addr_info *address) 468059d84dbSTetsuo Handa { 469059d84dbSTetsuo Handa const int idx = tomoyo_read_lock(); 470059d84dbSTetsuo Handa struct tomoyo_request_info r; 471059d84dbSTetsuo Handa int error = 0; 472059d84dbSTetsuo Handa const u8 type = tomoyo_inet2mac[address->protocol][address->operation]; 473059d84dbSTetsuo Handa 474059d84dbSTetsuo Handa if (type && tomoyo_init_request_info(&r, NULL, type) 475059d84dbSTetsuo Handa != TOMOYO_CONFIG_DISABLED) { 476059d84dbSTetsuo Handa r.param_type = TOMOYO_TYPE_INET_ACL; 477059d84dbSTetsuo Handa r.param.inet_network.protocol = address->protocol; 478059d84dbSTetsuo Handa r.param.inet_network.operation = address->operation; 479059d84dbSTetsuo Handa r.param.inet_network.is_ipv6 = address->inet.is_ipv6; 480059d84dbSTetsuo Handa r.param.inet_network.address = address->inet.address; 481059d84dbSTetsuo Handa r.param.inet_network.port = ntohs(address->inet.port); 482059d84dbSTetsuo Handa do { 483059d84dbSTetsuo Handa tomoyo_check_acl(&r, tomoyo_check_inet_acl); 484059d84dbSTetsuo Handa error = tomoyo_audit_inet_log(&r); 485059d84dbSTetsuo Handa } while (error == TOMOYO_RETRY_REQUEST); 486059d84dbSTetsuo Handa } 487059d84dbSTetsuo Handa tomoyo_read_unlock(idx); 488059d84dbSTetsuo Handa return error; 489059d84dbSTetsuo Handa } 490059d84dbSTetsuo Handa 491059d84dbSTetsuo Handa /** 492059d84dbSTetsuo Handa * tomoyo_check_inet_address - Check permission for inet domain socket's operation. 493059d84dbSTetsuo Handa * 494059d84dbSTetsuo Handa * @addr: Pointer to "struct sockaddr". 495059d84dbSTetsuo Handa * @addr_len: Size of @addr. 496059d84dbSTetsuo Handa * @port: Port number. 497059d84dbSTetsuo Handa * @address: Pointer to "struct tomoyo_addr_info". 498059d84dbSTetsuo Handa * 499059d84dbSTetsuo Handa * Returns 0 on success, negative value otherwise. 500059d84dbSTetsuo Handa */ 501059d84dbSTetsuo Handa static int tomoyo_check_inet_address(const struct sockaddr *addr, 502059d84dbSTetsuo Handa const unsigned int addr_len, 503059d84dbSTetsuo Handa const u16 port, 504059d84dbSTetsuo Handa struct tomoyo_addr_info *address) 505059d84dbSTetsuo Handa { 506059d84dbSTetsuo Handa struct tomoyo_inet_addr_info *i = &address->inet; 507059d84dbSTetsuo Handa 508*e6193f78STetsuo Handa if (addr_len < offsetofend(struct sockaddr, sa_family)) 509*e6193f78STetsuo Handa return 0; 510059d84dbSTetsuo Handa switch (addr->sa_family) { 511059d84dbSTetsuo Handa case AF_INET6: 512059d84dbSTetsuo Handa if (addr_len < SIN6_LEN_RFC2133) 513059d84dbSTetsuo Handa goto skip; 514059d84dbSTetsuo Handa i->is_ipv6 = true; 515059d84dbSTetsuo Handa i->address = (__be32 *) 516059d84dbSTetsuo Handa ((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr; 517059d84dbSTetsuo Handa i->port = ((struct sockaddr_in6 *) addr)->sin6_port; 518059d84dbSTetsuo Handa break; 519059d84dbSTetsuo Handa case AF_INET: 520059d84dbSTetsuo Handa if (addr_len < sizeof(struct sockaddr_in)) 521059d84dbSTetsuo Handa goto skip; 522059d84dbSTetsuo Handa i->is_ipv6 = false; 523059d84dbSTetsuo Handa i->address = (__be32 *) 524059d84dbSTetsuo Handa &((struct sockaddr_in *) addr)->sin_addr; 525059d84dbSTetsuo Handa i->port = ((struct sockaddr_in *) addr)->sin_port; 526059d84dbSTetsuo Handa break; 527059d84dbSTetsuo Handa default: 528059d84dbSTetsuo Handa goto skip; 529059d84dbSTetsuo Handa } 530059d84dbSTetsuo Handa if (address->protocol == SOCK_RAW) 531059d84dbSTetsuo Handa i->port = htons(port); 532059d84dbSTetsuo Handa return tomoyo_inet_entry(address); 533059d84dbSTetsuo Handa skip: 534059d84dbSTetsuo Handa return 0; 535059d84dbSTetsuo Handa } 536059d84dbSTetsuo Handa 537059d84dbSTetsuo Handa /** 538059d84dbSTetsuo Handa * tomoyo_unix_entry - Check permission for UNIX network operation. 539059d84dbSTetsuo Handa * 540059d84dbSTetsuo Handa * @address: Pointer to "struct tomoyo_addr_info". 541059d84dbSTetsuo Handa * 542059d84dbSTetsuo Handa * Returns 0 on success, negative value otherwise. 543059d84dbSTetsuo Handa */ 544059d84dbSTetsuo Handa static int tomoyo_unix_entry(const struct tomoyo_addr_info *address) 545059d84dbSTetsuo Handa { 546059d84dbSTetsuo Handa const int idx = tomoyo_read_lock(); 547059d84dbSTetsuo Handa struct tomoyo_request_info r; 548059d84dbSTetsuo Handa int error = 0; 549059d84dbSTetsuo Handa const u8 type = tomoyo_unix2mac[address->protocol][address->operation]; 550059d84dbSTetsuo Handa 551059d84dbSTetsuo Handa if (type && tomoyo_init_request_info(&r, NULL, type) 552059d84dbSTetsuo Handa != TOMOYO_CONFIG_DISABLED) { 553059d84dbSTetsuo Handa char *buf = address->unix0.addr; 554059d84dbSTetsuo Handa int len = address->unix0.addr_len - sizeof(sa_family_t); 555059d84dbSTetsuo Handa 556059d84dbSTetsuo Handa if (len <= 0) { 557059d84dbSTetsuo Handa buf = "anonymous"; 558059d84dbSTetsuo Handa len = 9; 559059d84dbSTetsuo Handa } else if (buf[0]) { 560059d84dbSTetsuo Handa len = strnlen(buf, len); 561059d84dbSTetsuo Handa } 562059d84dbSTetsuo Handa buf = tomoyo_encode2(buf, len); 563059d84dbSTetsuo Handa if (buf) { 564059d84dbSTetsuo Handa struct tomoyo_path_info addr; 565059d84dbSTetsuo Handa 566059d84dbSTetsuo Handa addr.name = buf; 567059d84dbSTetsuo Handa tomoyo_fill_path_info(&addr); 568059d84dbSTetsuo Handa r.param_type = TOMOYO_TYPE_UNIX_ACL; 569059d84dbSTetsuo Handa r.param.unix_network.protocol = address->protocol; 570059d84dbSTetsuo Handa r.param.unix_network.operation = address->operation; 571059d84dbSTetsuo Handa r.param.unix_network.address = &addr; 572059d84dbSTetsuo Handa do { 573059d84dbSTetsuo Handa tomoyo_check_acl(&r, tomoyo_check_unix_acl); 574059d84dbSTetsuo Handa error = tomoyo_audit_unix_log(&r); 575059d84dbSTetsuo Handa } while (error == TOMOYO_RETRY_REQUEST); 576059d84dbSTetsuo Handa kfree(buf); 577059d84dbSTetsuo Handa } else 578059d84dbSTetsuo Handa error = -ENOMEM; 579059d84dbSTetsuo Handa } 580059d84dbSTetsuo Handa tomoyo_read_unlock(idx); 581059d84dbSTetsuo Handa return error; 582059d84dbSTetsuo Handa } 583059d84dbSTetsuo Handa 584059d84dbSTetsuo Handa /** 585059d84dbSTetsuo Handa * tomoyo_check_unix_address - Check permission for unix domain socket's operation. 586059d84dbSTetsuo Handa * 587059d84dbSTetsuo Handa * @addr: Pointer to "struct sockaddr". 588059d84dbSTetsuo Handa * @addr_len: Size of @addr. 589059d84dbSTetsuo Handa * @address: Pointer to "struct tomoyo_addr_info". 590059d84dbSTetsuo Handa * 591059d84dbSTetsuo Handa * Returns 0 on success, negative value otherwise. 592059d84dbSTetsuo Handa */ 593059d84dbSTetsuo Handa static int tomoyo_check_unix_address(struct sockaddr *addr, 594059d84dbSTetsuo Handa const unsigned int addr_len, 595059d84dbSTetsuo Handa struct tomoyo_addr_info *address) 596059d84dbSTetsuo Handa { 597059d84dbSTetsuo Handa struct tomoyo_unix_addr_info *u = &address->unix0; 598059d84dbSTetsuo Handa 599*e6193f78STetsuo Handa if (addr_len < offsetofend(struct sockaddr, sa_family)) 600*e6193f78STetsuo Handa return 0; 601059d84dbSTetsuo Handa if (addr->sa_family != AF_UNIX) 602059d84dbSTetsuo Handa return 0; 603059d84dbSTetsuo Handa u->addr = ((struct sockaddr_un *) addr)->sun_path; 604059d84dbSTetsuo Handa u->addr_len = addr_len; 605059d84dbSTetsuo Handa return tomoyo_unix_entry(address); 606059d84dbSTetsuo Handa } 607059d84dbSTetsuo Handa 608059d84dbSTetsuo Handa /** 609059d84dbSTetsuo Handa * tomoyo_kernel_service - Check whether I'm kernel service or not. 610059d84dbSTetsuo Handa * 611059d84dbSTetsuo Handa * Returns true if I'm kernel service, false otherwise. 612059d84dbSTetsuo Handa */ 613059d84dbSTetsuo Handa static bool tomoyo_kernel_service(void) 614059d84dbSTetsuo Handa { 615059d84dbSTetsuo Handa /* Nothing to do if I am a kernel service. */ 616db68ce10SAl Viro return uaccess_kernel(); 617059d84dbSTetsuo Handa } 618059d84dbSTetsuo Handa 619059d84dbSTetsuo Handa /** 620059d84dbSTetsuo Handa * tomoyo_sock_family - Get socket's family. 621059d84dbSTetsuo Handa * 622059d84dbSTetsuo Handa * @sk: Pointer to "struct sock". 623059d84dbSTetsuo Handa * 624059d84dbSTetsuo Handa * Returns one of PF_INET, PF_INET6, PF_UNIX or 0. 625059d84dbSTetsuo Handa */ 626059d84dbSTetsuo Handa static u8 tomoyo_sock_family(struct sock *sk) 627059d84dbSTetsuo Handa { 628059d84dbSTetsuo Handa u8 family; 629059d84dbSTetsuo Handa 630059d84dbSTetsuo Handa if (tomoyo_kernel_service()) 631059d84dbSTetsuo Handa return 0; 632059d84dbSTetsuo Handa family = sk->sk_family; 633059d84dbSTetsuo Handa switch (family) { 634059d84dbSTetsuo Handa case PF_INET: 635059d84dbSTetsuo Handa case PF_INET6: 636059d84dbSTetsuo Handa case PF_UNIX: 637059d84dbSTetsuo Handa return family; 638059d84dbSTetsuo Handa default: 639059d84dbSTetsuo Handa return 0; 640059d84dbSTetsuo Handa } 641059d84dbSTetsuo Handa } 642059d84dbSTetsuo Handa 643059d84dbSTetsuo Handa /** 644059d84dbSTetsuo Handa * tomoyo_socket_listen_permission - Check permission for listening a socket. 645059d84dbSTetsuo Handa * 646059d84dbSTetsuo Handa * @sock: Pointer to "struct socket". 647059d84dbSTetsuo Handa * 648059d84dbSTetsuo Handa * Returns 0 on success, negative value otherwise. 649059d84dbSTetsuo Handa */ 650059d84dbSTetsuo Handa int tomoyo_socket_listen_permission(struct socket *sock) 651059d84dbSTetsuo Handa { 652059d84dbSTetsuo Handa struct tomoyo_addr_info address; 653059d84dbSTetsuo Handa const u8 family = tomoyo_sock_family(sock->sk); 654059d84dbSTetsuo Handa const unsigned int type = sock->type; 655059d84dbSTetsuo Handa struct sockaddr_storage addr; 656059d84dbSTetsuo Handa int addr_len; 657059d84dbSTetsuo Handa 658059d84dbSTetsuo Handa if (!family || (type != SOCK_STREAM && type != SOCK_SEQPACKET)) 659059d84dbSTetsuo Handa return 0; 660059d84dbSTetsuo Handa { 661059d84dbSTetsuo Handa const int error = sock->ops->getname(sock, (struct sockaddr *) 6629b2c45d4SDenys Vlasenko &addr, 0); 663059d84dbSTetsuo Handa 6649b2c45d4SDenys Vlasenko if (error < 0) 665059d84dbSTetsuo Handa return error; 6669b2c45d4SDenys Vlasenko addr_len = error; 667059d84dbSTetsuo Handa } 668059d84dbSTetsuo Handa address.protocol = type; 669059d84dbSTetsuo Handa address.operation = TOMOYO_NETWORK_LISTEN; 670059d84dbSTetsuo Handa if (family == PF_UNIX) 671059d84dbSTetsuo Handa return tomoyo_check_unix_address((struct sockaddr *) &addr, 672059d84dbSTetsuo Handa addr_len, &address); 673059d84dbSTetsuo Handa return tomoyo_check_inet_address((struct sockaddr *) &addr, addr_len, 674059d84dbSTetsuo Handa 0, &address); 675059d84dbSTetsuo Handa } 676059d84dbSTetsuo Handa 677059d84dbSTetsuo Handa /** 678059d84dbSTetsuo Handa * tomoyo_socket_connect_permission - Check permission for setting the remote address of a socket. 679059d84dbSTetsuo Handa * 680059d84dbSTetsuo Handa * @sock: Pointer to "struct socket". 681059d84dbSTetsuo Handa * @addr: Pointer to "struct sockaddr". 682059d84dbSTetsuo Handa * @addr_len: Size of @addr. 683059d84dbSTetsuo Handa * 684059d84dbSTetsuo Handa * Returns 0 on success, negative value otherwise. 685059d84dbSTetsuo Handa */ 686059d84dbSTetsuo Handa int tomoyo_socket_connect_permission(struct socket *sock, 687059d84dbSTetsuo Handa struct sockaddr *addr, int addr_len) 688059d84dbSTetsuo Handa { 689059d84dbSTetsuo Handa struct tomoyo_addr_info address; 690059d84dbSTetsuo Handa const u8 family = tomoyo_sock_family(sock->sk); 691059d84dbSTetsuo Handa const unsigned int type = sock->type; 692059d84dbSTetsuo Handa 693059d84dbSTetsuo Handa if (!family) 694059d84dbSTetsuo Handa return 0; 695059d84dbSTetsuo Handa address.protocol = type; 696059d84dbSTetsuo Handa switch (type) { 697059d84dbSTetsuo Handa case SOCK_DGRAM: 698059d84dbSTetsuo Handa case SOCK_RAW: 699059d84dbSTetsuo Handa address.operation = TOMOYO_NETWORK_SEND; 700059d84dbSTetsuo Handa break; 701059d84dbSTetsuo Handa case SOCK_STREAM: 702059d84dbSTetsuo Handa case SOCK_SEQPACKET: 703059d84dbSTetsuo Handa address.operation = TOMOYO_NETWORK_CONNECT; 704059d84dbSTetsuo Handa break; 705059d84dbSTetsuo Handa default: 706059d84dbSTetsuo Handa return 0; 707059d84dbSTetsuo Handa } 708059d84dbSTetsuo Handa if (family == PF_UNIX) 709059d84dbSTetsuo Handa return tomoyo_check_unix_address(addr, addr_len, &address); 710059d84dbSTetsuo Handa return tomoyo_check_inet_address(addr, addr_len, sock->sk->sk_protocol, 711059d84dbSTetsuo Handa &address); 712059d84dbSTetsuo Handa } 713059d84dbSTetsuo Handa 714059d84dbSTetsuo Handa /** 715059d84dbSTetsuo Handa * tomoyo_socket_bind_permission - Check permission for setting the local address of a socket. 716059d84dbSTetsuo Handa * 717059d84dbSTetsuo Handa * @sock: Pointer to "struct socket". 718059d84dbSTetsuo Handa * @addr: Pointer to "struct sockaddr". 719059d84dbSTetsuo Handa * @addr_len: Size of @addr. 720059d84dbSTetsuo Handa * 721059d84dbSTetsuo Handa * Returns 0 on success, negative value otherwise. 722059d84dbSTetsuo Handa */ 723059d84dbSTetsuo Handa int tomoyo_socket_bind_permission(struct socket *sock, struct sockaddr *addr, 724059d84dbSTetsuo Handa int addr_len) 725059d84dbSTetsuo Handa { 726059d84dbSTetsuo Handa struct tomoyo_addr_info address; 727059d84dbSTetsuo Handa const u8 family = tomoyo_sock_family(sock->sk); 728059d84dbSTetsuo Handa const unsigned int type = sock->type; 729059d84dbSTetsuo Handa 730059d84dbSTetsuo Handa if (!family) 731059d84dbSTetsuo Handa return 0; 732059d84dbSTetsuo Handa switch (type) { 733059d84dbSTetsuo Handa case SOCK_STREAM: 734059d84dbSTetsuo Handa case SOCK_DGRAM: 735059d84dbSTetsuo Handa case SOCK_RAW: 736059d84dbSTetsuo Handa case SOCK_SEQPACKET: 737059d84dbSTetsuo Handa address.protocol = type; 738059d84dbSTetsuo Handa address.operation = TOMOYO_NETWORK_BIND; 739059d84dbSTetsuo Handa break; 740059d84dbSTetsuo Handa default: 741059d84dbSTetsuo Handa return 0; 742059d84dbSTetsuo Handa } 743059d84dbSTetsuo Handa if (family == PF_UNIX) 744059d84dbSTetsuo Handa return tomoyo_check_unix_address(addr, addr_len, &address); 745059d84dbSTetsuo Handa return tomoyo_check_inet_address(addr, addr_len, sock->sk->sk_protocol, 746059d84dbSTetsuo Handa &address); 747059d84dbSTetsuo Handa } 748059d84dbSTetsuo Handa 749059d84dbSTetsuo Handa /** 750059d84dbSTetsuo Handa * tomoyo_socket_sendmsg_permission - Check permission for sending a datagram. 751059d84dbSTetsuo Handa * 752059d84dbSTetsuo Handa * @sock: Pointer to "struct socket". 753059d84dbSTetsuo Handa * @msg: Pointer to "struct msghdr". 754059d84dbSTetsuo Handa * @size: Unused. 755059d84dbSTetsuo Handa * 756059d84dbSTetsuo Handa * Returns 0 on success, negative value otherwise. 757059d84dbSTetsuo Handa */ 758059d84dbSTetsuo Handa int tomoyo_socket_sendmsg_permission(struct socket *sock, struct msghdr *msg, 759059d84dbSTetsuo Handa int size) 760059d84dbSTetsuo Handa { 761059d84dbSTetsuo Handa struct tomoyo_addr_info address; 762059d84dbSTetsuo Handa const u8 family = tomoyo_sock_family(sock->sk); 763059d84dbSTetsuo Handa const unsigned int type = sock->type; 764059d84dbSTetsuo Handa 765059d84dbSTetsuo Handa if (!msg->msg_name || !family || 766059d84dbSTetsuo Handa (type != SOCK_DGRAM && type != SOCK_RAW)) 767059d84dbSTetsuo Handa return 0; 768059d84dbSTetsuo Handa address.protocol = type; 769059d84dbSTetsuo Handa address.operation = TOMOYO_NETWORK_SEND; 770059d84dbSTetsuo Handa if (family == PF_UNIX) 771059d84dbSTetsuo Handa return tomoyo_check_unix_address((struct sockaddr *) 772059d84dbSTetsuo Handa msg->msg_name, 773059d84dbSTetsuo Handa msg->msg_namelen, &address); 774059d84dbSTetsuo Handa return tomoyo_check_inet_address((struct sockaddr *) msg->msg_name, 775059d84dbSTetsuo Handa msg->msg_namelen, 776059d84dbSTetsuo Handa sock->sk->sk_protocol, &address); 777059d84dbSTetsuo Handa } 778