cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

network.c (22015B)


      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 = READ_ONCE(*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	WRITE_ONCE(*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 = READ_ONCE(*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	WRITE_ONCE(*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	if (addr_len < offsetofend(struct sockaddr, sa_family))
    509		return 0;
    510	switch (addr->sa_family) {
    511	case AF_INET6:
    512		if (addr_len < SIN6_LEN_RFC2133)
    513			goto skip;
    514		i->is_ipv6 = true;
    515		i->address = (__be32 *)
    516			((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr;
    517		i->port = ((struct sockaddr_in6 *) addr)->sin6_port;
    518		break;
    519	case AF_INET:
    520		if (addr_len < sizeof(struct sockaddr_in))
    521			goto skip;
    522		i->is_ipv6 = false;
    523		i->address = (__be32 *)
    524			&((struct sockaddr_in *) addr)->sin_addr;
    525		i->port = ((struct sockaddr_in *) addr)->sin_port;
    526		break;
    527	default:
    528		goto skip;
    529	}
    530	if (address->protocol == SOCK_RAW)
    531		i->port = htons(port);
    532	return tomoyo_inet_entry(address);
    533skip:
    534	return 0;
    535}
    536
    537/**
    538 * tomoyo_unix_entry - Check permission for UNIX network operation.
    539 *
    540 * @address: Pointer to "struct tomoyo_addr_info".
    541 *
    542 * Returns 0 on success, negative value otherwise.
    543 */
    544static int tomoyo_unix_entry(const struct tomoyo_addr_info *address)
    545{
    546	const int idx = tomoyo_read_lock();
    547	struct tomoyo_request_info r;
    548	int error = 0;
    549	const u8 type = tomoyo_unix2mac[address->protocol][address->operation];
    550
    551	if (type && tomoyo_init_request_info(&r, NULL, type)
    552	    != TOMOYO_CONFIG_DISABLED) {
    553		char *buf = address->unix0.addr;
    554		int len = address->unix0.addr_len - sizeof(sa_family_t);
    555
    556		if (len <= 0) {
    557			buf = "anonymous";
    558			len = 9;
    559		} else if (buf[0]) {
    560			len = strnlen(buf, len);
    561		}
    562		buf = tomoyo_encode2(buf, len);
    563		if (buf) {
    564			struct tomoyo_path_info addr;
    565
    566			addr.name = buf;
    567			tomoyo_fill_path_info(&addr);
    568			r.param_type = TOMOYO_TYPE_UNIX_ACL;
    569			r.param.unix_network.protocol = address->protocol;
    570			r.param.unix_network.operation = address->operation;
    571			r.param.unix_network.address = &addr;
    572			do {
    573				tomoyo_check_acl(&r, tomoyo_check_unix_acl);
    574				error = tomoyo_audit_unix_log(&r);
    575			} while (error == TOMOYO_RETRY_REQUEST);
    576			kfree(buf);
    577		} else
    578			error = -ENOMEM;
    579	}
    580	tomoyo_read_unlock(idx);
    581	return error;
    582}
    583
    584/**
    585 * tomoyo_check_unix_address - Check permission for unix domain socket's operation.
    586 *
    587 * @addr:     Pointer to "struct sockaddr".
    588 * @addr_len: Size of @addr.
    589 * @address:  Pointer to "struct tomoyo_addr_info".
    590 *
    591 * Returns 0 on success, negative value otherwise.
    592 */
    593static int tomoyo_check_unix_address(struct sockaddr *addr,
    594				     const unsigned int addr_len,
    595				     struct tomoyo_addr_info *address)
    596{
    597	struct tomoyo_unix_addr_info *u = &address->unix0;
    598
    599	if (addr_len < offsetofend(struct sockaddr, sa_family))
    600		return 0;
    601	if (addr->sa_family != AF_UNIX)
    602		return 0;
    603	u->addr = ((struct sockaddr_un *) addr)->sun_path;
    604	u->addr_len = addr_len;
    605	return tomoyo_unix_entry(address);
    606}
    607
    608/**
    609 * tomoyo_kernel_service - Check whether I'm kernel service or not.
    610 *
    611 * Returns true if I'm kernel service, false otherwise.
    612 */
    613static bool tomoyo_kernel_service(void)
    614{
    615	/* Nothing to do if I am a kernel service. */
    616	return current->flags & PF_KTHREAD;
    617}
    618
    619/**
    620 * tomoyo_sock_family - Get socket's family.
    621 *
    622 * @sk: Pointer to "struct sock".
    623 *
    624 * Returns one of PF_INET, PF_INET6, PF_UNIX or 0.
    625 */
    626static u8 tomoyo_sock_family(struct sock *sk)
    627{
    628	u8 family;
    629
    630	if (tomoyo_kernel_service())
    631		return 0;
    632	family = sk->sk_family;
    633	switch (family) {
    634	case PF_INET:
    635	case PF_INET6:
    636	case PF_UNIX:
    637		return family;
    638	default:
    639		return 0;
    640	}
    641}
    642
    643/**
    644 * tomoyo_socket_listen_permission - Check permission for listening a socket.
    645 *
    646 * @sock: Pointer to "struct socket".
    647 *
    648 * Returns 0 on success, negative value otherwise.
    649 */
    650int tomoyo_socket_listen_permission(struct socket *sock)
    651{
    652	struct tomoyo_addr_info address;
    653	const u8 family = tomoyo_sock_family(sock->sk);
    654	const unsigned int type = sock->type;
    655	struct sockaddr_storage addr;
    656	int addr_len;
    657
    658	if (!family || (type != SOCK_STREAM && type != SOCK_SEQPACKET))
    659		return 0;
    660	{
    661		const int error = sock->ops->getname(sock, (struct sockaddr *)
    662						     &addr, 0);
    663
    664		if (error < 0)
    665			return error;
    666		addr_len = error;
    667	}
    668	address.protocol = type;
    669	address.operation = TOMOYO_NETWORK_LISTEN;
    670	if (family == PF_UNIX)
    671		return tomoyo_check_unix_address((struct sockaddr *) &addr,
    672						 addr_len, &address);
    673	return tomoyo_check_inet_address((struct sockaddr *) &addr, addr_len,
    674					 0, &address);
    675}
    676
    677/**
    678 * tomoyo_socket_connect_permission - Check permission for setting the remote address of a socket.
    679 *
    680 * @sock:     Pointer to "struct socket".
    681 * @addr:     Pointer to "struct sockaddr".
    682 * @addr_len: Size of @addr.
    683 *
    684 * Returns 0 on success, negative value otherwise.
    685 */
    686int tomoyo_socket_connect_permission(struct socket *sock,
    687				     struct sockaddr *addr, int addr_len)
    688{
    689	struct tomoyo_addr_info address;
    690	const u8 family = tomoyo_sock_family(sock->sk);
    691	const unsigned int type = sock->type;
    692
    693	if (!family)
    694		return 0;
    695	address.protocol = type;
    696	switch (type) {
    697	case SOCK_DGRAM:
    698	case SOCK_RAW:
    699		address.operation = TOMOYO_NETWORK_SEND;
    700		break;
    701	case SOCK_STREAM:
    702	case SOCK_SEQPACKET:
    703		address.operation = TOMOYO_NETWORK_CONNECT;
    704		break;
    705	default:
    706		return 0;
    707	}
    708	if (family == PF_UNIX)
    709		return tomoyo_check_unix_address(addr, addr_len, &address);
    710	return tomoyo_check_inet_address(addr, addr_len, sock->sk->sk_protocol,
    711					 &address);
    712}
    713
    714/**
    715 * tomoyo_socket_bind_permission - Check permission for setting the local address of a socket.
    716 *
    717 * @sock:     Pointer to "struct socket".
    718 * @addr:     Pointer to "struct sockaddr".
    719 * @addr_len: Size of @addr.
    720 *
    721 * Returns 0 on success, negative value otherwise.
    722 */
    723int tomoyo_socket_bind_permission(struct socket *sock, struct sockaddr *addr,
    724				  int addr_len)
    725{
    726	struct tomoyo_addr_info address;
    727	const u8 family = tomoyo_sock_family(sock->sk);
    728	const unsigned int type = sock->type;
    729
    730	if (!family)
    731		return 0;
    732	switch (type) {
    733	case SOCK_STREAM:
    734	case SOCK_DGRAM:
    735	case SOCK_RAW:
    736	case SOCK_SEQPACKET:
    737		address.protocol = type;
    738		address.operation = TOMOYO_NETWORK_BIND;
    739		break;
    740	default:
    741		return 0;
    742	}
    743	if (family == PF_UNIX)
    744		return tomoyo_check_unix_address(addr, addr_len, &address);
    745	return tomoyo_check_inet_address(addr, addr_len, sock->sk->sk_protocol,
    746					 &address);
    747}
    748
    749/**
    750 * tomoyo_socket_sendmsg_permission - Check permission for sending a datagram.
    751 *
    752 * @sock: Pointer to "struct socket".
    753 * @msg:  Pointer to "struct msghdr".
    754 * @size: Unused.
    755 *
    756 * Returns 0 on success, negative value otherwise.
    757 */
    758int tomoyo_socket_sendmsg_permission(struct socket *sock, struct msghdr *msg,
    759				     int size)
    760{
    761	struct tomoyo_addr_info address;
    762	const u8 family = tomoyo_sock_family(sock->sk);
    763	const unsigned int type = sock->type;
    764
    765	if (!msg->msg_name || !family ||
    766	    (type != SOCK_DGRAM && type != SOCK_RAW))
    767		return 0;
    768	address.protocol = type;
    769	address.operation = TOMOYO_NETWORK_SEND;
    770	if (family == PF_UNIX)
    771		return tomoyo_check_unix_address((struct sockaddr *)
    772						 msg->msg_name,
    773						 msg->msg_namelen, &address);
    774	return tomoyo_check_inet_address((struct sockaddr *) msg->msg_name,
    775					 msg->msg_namelen,
    776					 sock->sk->sk_protocol, &address);
    777}