123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773 |
- // SPDX-License-Identifier: GPL-2.0
- /*
- * security/tomoyo/network.c
- *
- * Copyright (C) 2005-2011 NTT DATA CORPORATION
- */
- #include "common.h"
- #include <linux/slab.h>
- /* Structure for holding inet domain socket's address. */
- struct tomoyo_inet_addr_info {
- __be16 port; /* In network byte order. */
- const __be32 *address; /* In network byte order. */
- bool is_ipv6;
- };
- /* Structure for holding unix domain socket's address. */
- struct tomoyo_unix_addr_info {
- u8 *addr; /* This may not be '\0' terminated string. */
- unsigned int addr_len;
- };
- /* Structure for holding socket address. */
- struct tomoyo_addr_info {
- u8 protocol;
- u8 operation;
- struct tomoyo_inet_addr_info inet;
- struct tomoyo_unix_addr_info unix0;
- };
- /* String table for socket's protocols. */
- const char * const tomoyo_proto_keyword[TOMOYO_SOCK_MAX] = {
- [SOCK_STREAM] = "stream",
- [SOCK_DGRAM] = "dgram",
- [SOCK_RAW] = "raw",
- [SOCK_SEQPACKET] = "seqpacket",
- [0] = " ", /* Dummy for avoiding NULL pointer dereference. */
- [4] = " ", /* Dummy for avoiding NULL pointer dereference. */
- };
- /**
- * tomoyo_parse_ipaddr_union - Parse an IP address.
- *
- * @param: Pointer to "struct tomoyo_acl_param".
- * @ptr: Pointer to "struct tomoyo_ipaddr_union".
- *
- * Returns true on success, false otherwise.
- */
- bool tomoyo_parse_ipaddr_union(struct tomoyo_acl_param *param,
- struct tomoyo_ipaddr_union *ptr)
- {
- u8 * const min = ptr->ip[0].in6_u.u6_addr8;
- u8 * const max = ptr->ip[1].in6_u.u6_addr8;
- char *address = tomoyo_read_token(param);
- const char *end;
- if (!strchr(address, ':') &&
- in4_pton(address, -1, min, '-', &end) > 0) {
- ptr->is_ipv6 = false;
- if (!*end)
- ptr->ip[1].s6_addr32[0] = ptr->ip[0].s6_addr32[0];
- else if (*end++ != '-' ||
- in4_pton(end, -1, max, '\0', &end) <= 0 || *end)
- return false;
- return true;
- }
- if (in6_pton(address, -1, min, '-', &end) > 0) {
- ptr->is_ipv6 = true;
- if (!*end)
- memmove(max, min, sizeof(u16) * 8);
- else if (*end++ != '-' ||
- in6_pton(end, -1, max, '\0', &end) <= 0 || *end)
- return false;
- return true;
- }
- return false;
- }
- /**
- * tomoyo_print_ipv4 - Print an IPv4 address.
- *
- * @buffer: Buffer to write to.
- * @buffer_len: Size of @buffer.
- * @min_ip: Pointer to __be32.
- * @max_ip: Pointer to __be32.
- *
- * Returns nothing.
- */
- static void tomoyo_print_ipv4(char *buffer, const unsigned int buffer_len,
- const __be32 *min_ip, const __be32 *max_ip)
- {
- snprintf(buffer, buffer_len, "%pI4%c%pI4", min_ip,
- *min_ip == *max_ip ? '\0' : '-', max_ip);
- }
- /**
- * tomoyo_print_ipv6 - Print an IPv6 address.
- *
- * @buffer: Buffer to write to.
- * @buffer_len: Size of @buffer.
- * @min_ip: Pointer to "struct in6_addr".
- * @max_ip: Pointer to "struct in6_addr".
- *
- * Returns nothing.
- */
- static void tomoyo_print_ipv6(char *buffer, const unsigned int buffer_len,
- const struct in6_addr *min_ip,
- const struct in6_addr *max_ip)
- {
- snprintf(buffer, buffer_len, "%pI6c%c%pI6c", min_ip,
- !memcmp(min_ip, max_ip, 16) ? '\0' : '-', max_ip);
- }
- /**
- * tomoyo_print_ip - Print an IP address.
- *
- * @buf: Buffer to write to.
- * @size: Size of @buf.
- * @ptr: Pointer to "struct ipaddr_union".
- *
- * Returns nothing.
- */
- void tomoyo_print_ip(char *buf, const unsigned int size,
- const struct tomoyo_ipaddr_union *ptr)
- {
- if (ptr->is_ipv6)
- tomoyo_print_ipv6(buf, size, &ptr->ip[0], &ptr->ip[1]);
- else
- tomoyo_print_ipv4(buf, size, &ptr->ip[0].s6_addr32[0],
- &ptr->ip[1].s6_addr32[0]);
- }
- /*
- * Mapping table from "enum tomoyo_network_acl_index" to
- * "enum tomoyo_mac_index" for inet domain socket.
- */
- static const u8 tomoyo_inet2mac
- [TOMOYO_SOCK_MAX][TOMOYO_MAX_NETWORK_OPERATION] = {
- [SOCK_STREAM] = {
- [TOMOYO_NETWORK_BIND] = TOMOYO_MAC_NETWORK_INET_STREAM_BIND,
- [TOMOYO_NETWORK_LISTEN] =
- TOMOYO_MAC_NETWORK_INET_STREAM_LISTEN,
- [TOMOYO_NETWORK_CONNECT] =
- TOMOYO_MAC_NETWORK_INET_STREAM_CONNECT,
- },
- [SOCK_DGRAM] = {
- [TOMOYO_NETWORK_BIND] = TOMOYO_MAC_NETWORK_INET_DGRAM_BIND,
- [TOMOYO_NETWORK_SEND] = TOMOYO_MAC_NETWORK_INET_DGRAM_SEND,
- },
- [SOCK_RAW] = {
- [TOMOYO_NETWORK_BIND] = TOMOYO_MAC_NETWORK_INET_RAW_BIND,
- [TOMOYO_NETWORK_SEND] = TOMOYO_MAC_NETWORK_INET_RAW_SEND,
- },
- };
- /*
- * Mapping table from "enum tomoyo_network_acl_index" to
- * "enum tomoyo_mac_index" for unix domain socket.
- */
- static const u8 tomoyo_unix2mac
- [TOMOYO_SOCK_MAX][TOMOYO_MAX_NETWORK_OPERATION] = {
- [SOCK_STREAM] = {
- [TOMOYO_NETWORK_BIND] = TOMOYO_MAC_NETWORK_UNIX_STREAM_BIND,
- [TOMOYO_NETWORK_LISTEN] =
- TOMOYO_MAC_NETWORK_UNIX_STREAM_LISTEN,
- [TOMOYO_NETWORK_CONNECT] =
- TOMOYO_MAC_NETWORK_UNIX_STREAM_CONNECT,
- },
- [SOCK_DGRAM] = {
- [TOMOYO_NETWORK_BIND] = TOMOYO_MAC_NETWORK_UNIX_DGRAM_BIND,
- [TOMOYO_NETWORK_SEND] = TOMOYO_MAC_NETWORK_UNIX_DGRAM_SEND,
- },
- [SOCK_SEQPACKET] = {
- [TOMOYO_NETWORK_BIND] =
- TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_BIND,
- [TOMOYO_NETWORK_LISTEN] =
- TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_LISTEN,
- [TOMOYO_NETWORK_CONNECT] =
- TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_CONNECT,
- },
- };
- /**
- * tomoyo_same_inet_acl - Check for duplicated "struct tomoyo_inet_acl" entry.
- *
- * @a: Pointer to "struct tomoyo_acl_info".
- * @b: Pointer to "struct tomoyo_acl_info".
- *
- * Returns true if @a == @b except permission bits, false otherwise.
- */
- static bool tomoyo_same_inet_acl(const struct tomoyo_acl_info *a,
- const struct tomoyo_acl_info *b)
- {
- const struct tomoyo_inet_acl *p1 = container_of(a, typeof(*p1), head);
- const struct tomoyo_inet_acl *p2 = container_of(b, typeof(*p2), head);
- return p1->protocol == p2->protocol &&
- tomoyo_same_ipaddr_union(&p1->address, &p2->address) &&
- tomoyo_same_number_union(&p1->port, &p2->port);
- }
- /**
- * tomoyo_same_unix_acl - Check for duplicated "struct tomoyo_unix_acl" entry.
- *
- * @a: Pointer to "struct tomoyo_acl_info".
- * @b: Pointer to "struct tomoyo_acl_info".
- *
- * Returns true if @a == @b except permission bits, false otherwise.
- */
- static bool tomoyo_same_unix_acl(const struct tomoyo_acl_info *a,
- const struct tomoyo_acl_info *b)
- {
- const struct tomoyo_unix_acl *p1 = container_of(a, typeof(*p1), head);
- const struct tomoyo_unix_acl *p2 = container_of(b, typeof(*p2), head);
- return p1->protocol == p2->protocol &&
- tomoyo_same_name_union(&p1->name, &p2->name);
- }
- /**
- * tomoyo_merge_inet_acl - Merge duplicated "struct tomoyo_inet_acl" entry.
- *
- * @a: Pointer to "struct tomoyo_acl_info".
- * @b: Pointer to "struct tomoyo_acl_info".
- * @is_delete: True for @a &= ~@b, false for @a |= @b.
- *
- * Returns true if @a is empty, false otherwise.
- */
- static bool tomoyo_merge_inet_acl(struct tomoyo_acl_info *a,
- struct tomoyo_acl_info *b,
- const bool is_delete)
- {
- u8 * const a_perm =
- &container_of(a, struct tomoyo_inet_acl, head)->perm;
- u8 perm = *a_perm;
- const u8 b_perm = container_of(b, struct tomoyo_inet_acl, head)->perm;
- if (is_delete)
- perm &= ~b_perm;
- else
- perm |= b_perm;
- *a_perm = perm;
- return !perm;
- }
- /**
- * tomoyo_merge_unix_acl - Merge duplicated "struct tomoyo_unix_acl" entry.
- *
- * @a: Pointer to "struct tomoyo_acl_info".
- * @b: Pointer to "struct tomoyo_acl_info".
- * @is_delete: True for @a &= ~@b, false for @a |= @b.
- *
- * Returns true if @a is empty, false otherwise.
- */
- static bool tomoyo_merge_unix_acl(struct tomoyo_acl_info *a,
- struct tomoyo_acl_info *b,
- const bool is_delete)
- {
- u8 * const a_perm =
- &container_of(a, struct tomoyo_unix_acl, head)->perm;
- u8 perm = *a_perm;
- const u8 b_perm = container_of(b, struct tomoyo_unix_acl, head)->perm;
- if (is_delete)
- perm &= ~b_perm;
- else
- perm |= b_perm;
- *a_perm = perm;
- return !perm;
- }
- /**
- * tomoyo_write_inet_network - Write "struct tomoyo_inet_acl" list.
- *
- * @param: Pointer to "struct tomoyo_acl_param".
- *
- * Returns 0 on success, negative value otherwise.
- *
- * Caller holds tomoyo_read_lock().
- */
- int tomoyo_write_inet_network(struct tomoyo_acl_param *param)
- {
- struct tomoyo_inet_acl e = { .head.type = TOMOYO_TYPE_INET_ACL };
- int error = -EINVAL;
- u8 type;
- const char *protocol = tomoyo_read_token(param);
- const char *operation = tomoyo_read_token(param);
- for (e.protocol = 0; e.protocol < TOMOYO_SOCK_MAX; e.protocol++)
- if (!strcmp(protocol, tomoyo_proto_keyword[e.protocol]))
- break;
- for (type = 0; type < TOMOYO_MAX_NETWORK_OPERATION; type++)
- if (tomoyo_permstr(operation, tomoyo_socket_keyword[type]))
- e.perm |= 1 << type;
- if (e.protocol == TOMOYO_SOCK_MAX || !e.perm)
- return -EINVAL;
- if (param->data[0] == '@') {
- param->data++;
- e.address.group =
- tomoyo_get_group(param, TOMOYO_ADDRESS_GROUP);
- if (!e.address.group)
- return -ENOMEM;
- } else {
- if (!tomoyo_parse_ipaddr_union(param, &e.address))
- goto out;
- }
- if (!tomoyo_parse_number_union(param, &e.port) ||
- e.port.values[1] > 65535)
- goto out;
- error = tomoyo_update_domain(&e.head, sizeof(e), param,
- tomoyo_same_inet_acl,
- tomoyo_merge_inet_acl);
- out:
- tomoyo_put_group(e.address.group);
- tomoyo_put_number_union(&e.port);
- return error;
- }
- /**
- * tomoyo_write_unix_network - Write "struct tomoyo_unix_acl" list.
- *
- * @param: Pointer to "struct tomoyo_acl_param".
- *
- * Returns 0 on success, negative value otherwise.
- */
- int tomoyo_write_unix_network(struct tomoyo_acl_param *param)
- {
- struct tomoyo_unix_acl e = { .head.type = TOMOYO_TYPE_UNIX_ACL };
- int error;
- u8 type;
- const char *protocol = tomoyo_read_token(param);
- const char *operation = tomoyo_read_token(param);
- for (e.protocol = 0; e.protocol < TOMOYO_SOCK_MAX; e.protocol++)
- if (!strcmp(protocol, tomoyo_proto_keyword[e.protocol]))
- break;
- for (type = 0; type < TOMOYO_MAX_NETWORK_OPERATION; type++)
- if (tomoyo_permstr(operation, tomoyo_socket_keyword[type]))
- e.perm |= 1 << type;
- if (e.protocol == TOMOYO_SOCK_MAX || !e.perm)
- return -EINVAL;
- if (!tomoyo_parse_name_union(param, &e.name))
- return -EINVAL;
- error = tomoyo_update_domain(&e.head, sizeof(e), param,
- tomoyo_same_unix_acl,
- tomoyo_merge_unix_acl);
- tomoyo_put_name_union(&e.name);
- return error;
- }
- /**
- * tomoyo_audit_net_log - Audit network log.
- *
- * @r: Pointer to "struct tomoyo_request_info".
- * @family: Name of socket family ("inet" or "unix").
- * @protocol: Name of protocol in @family.
- * @operation: Name of socket operation.
- * @address: Name of address.
- *
- * Returns 0 on success, negative value otherwise.
- */
- static int tomoyo_audit_net_log(struct tomoyo_request_info *r,
- const char *family, const u8 protocol,
- const u8 operation, const char *address)
- {
- return tomoyo_supervisor(r, "network %s %s %s %s\n", family,
- tomoyo_proto_keyword[protocol],
- tomoyo_socket_keyword[operation], address);
- }
- /**
- * tomoyo_audit_inet_log - Audit INET network log.
- *
- * @r: Pointer to "struct tomoyo_request_info".
- *
- * Returns 0 on success, negative value otherwise.
- */
- static int tomoyo_audit_inet_log(struct tomoyo_request_info *r)
- {
- char buf[128];
- int len;
- const __be32 *address = r->param.inet_network.address;
- if (r->param.inet_network.is_ipv6)
- tomoyo_print_ipv6(buf, sizeof(buf), (const struct in6_addr *)
- address, (const struct in6_addr *) address);
- else
- tomoyo_print_ipv4(buf, sizeof(buf), address, address);
- len = strlen(buf);
- snprintf(buf + len, sizeof(buf) - len, " %u",
- r->param.inet_network.port);
- return tomoyo_audit_net_log(r, "inet", r->param.inet_network.protocol,
- r->param.inet_network.operation, buf);
- }
- /**
- * tomoyo_audit_unix_log - Audit UNIX network log.
- *
- * @r: Pointer to "struct tomoyo_request_info".
- *
- * Returns 0 on success, negative value otherwise.
- */
- static int tomoyo_audit_unix_log(struct tomoyo_request_info *r)
- {
- return tomoyo_audit_net_log(r, "unix", r->param.unix_network.protocol,
- r->param.unix_network.operation,
- r->param.unix_network.address->name);
- }
- /**
- * tomoyo_check_inet_acl - Check permission for inet domain socket operation.
- *
- * @r: Pointer to "struct tomoyo_request_info".
- * @ptr: Pointer to "struct tomoyo_acl_info".
- *
- * Returns true if granted, false otherwise.
- */
- static bool tomoyo_check_inet_acl(struct tomoyo_request_info *r,
- const struct tomoyo_acl_info *ptr)
- {
- const struct tomoyo_inet_acl *acl =
- container_of(ptr, typeof(*acl), head);
- const u8 size = r->param.inet_network.is_ipv6 ? 16 : 4;
- if (!(acl->perm & (1 << r->param.inet_network.operation)) ||
- !tomoyo_compare_number_union(r->param.inet_network.port,
- &acl->port))
- return false;
- if (acl->address.group)
- return tomoyo_address_matches_group
- (r->param.inet_network.is_ipv6,
- r->param.inet_network.address, acl->address.group);
- return acl->address.is_ipv6 == r->param.inet_network.is_ipv6 &&
- memcmp(&acl->address.ip[0],
- r->param.inet_network.address, size) <= 0 &&
- memcmp(r->param.inet_network.address,
- &acl->address.ip[1], size) <= 0;
- }
- /**
- * tomoyo_check_unix_acl - Check permission for unix domain socket operation.
- *
- * @r: Pointer to "struct tomoyo_request_info".
- * @ptr: Pointer to "struct tomoyo_acl_info".
- *
- * Returns true if granted, false otherwise.
- */
- static bool tomoyo_check_unix_acl(struct tomoyo_request_info *r,
- const struct tomoyo_acl_info *ptr)
- {
- const struct tomoyo_unix_acl *acl =
- container_of(ptr, typeof(*acl), head);
- return (acl->perm & (1 << r->param.unix_network.operation)) &&
- tomoyo_compare_name_union(r->param.unix_network.address,
- &acl->name);
- }
- /**
- * tomoyo_inet_entry - Check permission for INET network operation.
- *
- * @address: Pointer to "struct tomoyo_addr_info".
- *
- * Returns 0 on success, negative value otherwise.
- */
- static int tomoyo_inet_entry(const struct tomoyo_addr_info *address)
- {
- const int idx = tomoyo_read_lock();
- struct tomoyo_request_info r;
- int error = 0;
- const u8 type = tomoyo_inet2mac[address->protocol][address->operation];
- if (type && tomoyo_init_request_info(&r, NULL, type)
- != TOMOYO_CONFIG_DISABLED) {
- r.param_type = TOMOYO_TYPE_INET_ACL;
- r.param.inet_network.protocol = address->protocol;
- r.param.inet_network.operation = address->operation;
- r.param.inet_network.is_ipv6 = address->inet.is_ipv6;
- r.param.inet_network.address = address->inet.address;
- r.param.inet_network.port = ntohs(address->inet.port);
- do {
- tomoyo_check_acl(&r, tomoyo_check_inet_acl);
- error = tomoyo_audit_inet_log(&r);
- } while (error == TOMOYO_RETRY_REQUEST);
- }
- tomoyo_read_unlock(idx);
- return error;
- }
- /**
- * tomoyo_check_inet_address - Check permission for inet domain socket's operation.
- *
- * @addr: Pointer to "struct sockaddr".
- * @addr_len: Size of @addr.
- * @port: Port number.
- * @address: Pointer to "struct tomoyo_addr_info".
- *
- * Returns 0 on success, negative value otherwise.
- */
- static int tomoyo_check_inet_address(const struct sockaddr *addr,
- const unsigned int addr_len,
- const u16 port,
- struct tomoyo_addr_info *address)
- {
- struct tomoyo_inet_addr_info *i = &address->inet;
- switch (addr->sa_family) {
- case AF_INET6:
- if (addr_len < SIN6_LEN_RFC2133)
- goto skip;
- i->is_ipv6 = true;
- i->address = (__be32 *)
- ((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr;
- i->port = ((struct sockaddr_in6 *) addr)->sin6_port;
- break;
- case AF_INET:
- if (addr_len < sizeof(struct sockaddr_in))
- goto skip;
- i->is_ipv6 = false;
- i->address = (__be32 *)
- &((struct sockaddr_in *) addr)->sin_addr;
- i->port = ((struct sockaddr_in *) addr)->sin_port;
- break;
- default:
- goto skip;
- }
- if (address->protocol == SOCK_RAW)
- i->port = htons(port);
- return tomoyo_inet_entry(address);
- skip:
- return 0;
- }
- /**
- * tomoyo_unix_entry - Check permission for UNIX network operation.
- *
- * @address: Pointer to "struct tomoyo_addr_info".
- *
- * Returns 0 on success, negative value otherwise.
- */
- static int tomoyo_unix_entry(const struct tomoyo_addr_info *address)
- {
- const int idx = tomoyo_read_lock();
- struct tomoyo_request_info r;
- int error = 0;
- const u8 type = tomoyo_unix2mac[address->protocol][address->operation];
- if (type && tomoyo_init_request_info(&r, NULL, type)
- != TOMOYO_CONFIG_DISABLED) {
- char *buf = address->unix0.addr;
- int len = address->unix0.addr_len - sizeof(sa_family_t);
- if (len <= 0) {
- buf = "anonymous";
- len = 9;
- } else if (buf[0]) {
- len = strnlen(buf, len);
- }
- buf = tomoyo_encode2(buf, len);
- if (buf) {
- struct tomoyo_path_info addr;
- addr.name = buf;
- tomoyo_fill_path_info(&addr);
- r.param_type = TOMOYO_TYPE_UNIX_ACL;
- r.param.unix_network.protocol = address->protocol;
- r.param.unix_network.operation = address->operation;
- r.param.unix_network.address = &addr;
- do {
- tomoyo_check_acl(&r, tomoyo_check_unix_acl);
- error = tomoyo_audit_unix_log(&r);
- } while (error == TOMOYO_RETRY_REQUEST);
- kfree(buf);
- } else
- error = -ENOMEM;
- }
- tomoyo_read_unlock(idx);
- return error;
- }
- /**
- * tomoyo_check_unix_address - Check permission for unix domain socket's operation.
- *
- * @addr: Pointer to "struct sockaddr".
- * @addr_len: Size of @addr.
- * @address: Pointer to "struct tomoyo_addr_info".
- *
- * Returns 0 on success, negative value otherwise.
- */
- static int tomoyo_check_unix_address(struct sockaddr *addr,
- const unsigned int addr_len,
- struct tomoyo_addr_info *address)
- {
- struct tomoyo_unix_addr_info *u = &address->unix0;
- if (addr->sa_family != AF_UNIX)
- return 0;
- u->addr = ((struct sockaddr_un *) addr)->sun_path;
- u->addr_len = addr_len;
- return tomoyo_unix_entry(address);
- }
- /**
- * tomoyo_kernel_service - Check whether I'm kernel service or not.
- *
- * Returns true if I'm kernel service, false otherwise.
- */
- static bool tomoyo_kernel_service(void)
- {
- /* Nothing to do if I am a kernel service. */
- return uaccess_kernel();
- }
- /**
- * tomoyo_sock_family - Get socket's family.
- *
- * @sk: Pointer to "struct sock".
- *
- * Returns one of PF_INET, PF_INET6, PF_UNIX or 0.
- */
- static u8 tomoyo_sock_family(struct sock *sk)
- {
- u8 family;
- if (tomoyo_kernel_service())
- return 0;
- family = sk->sk_family;
- switch (family) {
- case PF_INET:
- case PF_INET6:
- case PF_UNIX:
- return family;
- default:
- return 0;
- }
- }
- /**
- * tomoyo_socket_listen_permission - Check permission for listening a socket.
- *
- * @sock: Pointer to "struct socket".
- *
- * Returns 0 on success, negative value otherwise.
- */
- int tomoyo_socket_listen_permission(struct socket *sock)
- {
- struct tomoyo_addr_info address;
- const u8 family = tomoyo_sock_family(sock->sk);
- const unsigned int type = sock->type;
- struct sockaddr_storage addr;
- int addr_len;
- if (!family || (type != SOCK_STREAM && type != SOCK_SEQPACKET))
- return 0;
- {
- const int error = sock->ops->getname(sock, (struct sockaddr *)
- &addr, &addr_len, 0);
- if (error)
- return error;
- }
- address.protocol = type;
- address.operation = TOMOYO_NETWORK_LISTEN;
- if (family == PF_UNIX)
- return tomoyo_check_unix_address((struct sockaddr *) &addr,
- addr_len, &address);
- return tomoyo_check_inet_address((struct sockaddr *) &addr, addr_len,
- 0, &address);
- }
- /**
- * tomoyo_socket_connect_permission - Check permission for setting the remote address of a socket.
- *
- * @sock: Pointer to "struct socket".
- * @addr: Pointer to "struct sockaddr".
- * @addr_len: Size of @addr.
- *
- * Returns 0 on success, negative value otherwise.
- */
- int tomoyo_socket_connect_permission(struct socket *sock,
- struct sockaddr *addr, int addr_len)
- {
- struct tomoyo_addr_info address;
- const u8 family = tomoyo_sock_family(sock->sk);
- const unsigned int type = sock->type;
- if (!family)
- return 0;
- address.protocol = type;
- switch (type) {
- case SOCK_DGRAM:
- case SOCK_RAW:
- address.operation = TOMOYO_NETWORK_SEND;
- break;
- case SOCK_STREAM:
- case SOCK_SEQPACKET:
- address.operation = TOMOYO_NETWORK_CONNECT;
- break;
- default:
- return 0;
- }
- if (family == PF_UNIX)
- return tomoyo_check_unix_address(addr, addr_len, &address);
- return tomoyo_check_inet_address(addr, addr_len, sock->sk->sk_protocol,
- &address);
- }
- /**
- * tomoyo_socket_bind_permission - Check permission for setting the local address of a socket.
- *
- * @sock: Pointer to "struct socket".
- * @addr: Pointer to "struct sockaddr".
- * @addr_len: Size of @addr.
- *
- * Returns 0 on success, negative value otherwise.
- */
- int tomoyo_socket_bind_permission(struct socket *sock, struct sockaddr *addr,
- int addr_len)
- {
- struct tomoyo_addr_info address;
- const u8 family = tomoyo_sock_family(sock->sk);
- const unsigned int type = sock->type;
- if (!family)
- return 0;
- switch (type) {
- case SOCK_STREAM:
- case SOCK_DGRAM:
- case SOCK_RAW:
- case SOCK_SEQPACKET:
- address.protocol = type;
- address.operation = TOMOYO_NETWORK_BIND;
- break;
- default:
- return 0;
- }
- if (family == PF_UNIX)
- return tomoyo_check_unix_address(addr, addr_len, &address);
- return tomoyo_check_inet_address(addr, addr_len, sock->sk->sk_protocol,
- &address);
- }
- /**
- * tomoyo_socket_sendmsg_permission - Check permission for sending a datagram.
- *
- * @sock: Pointer to "struct socket".
- * @msg: Pointer to "struct msghdr".
- * @size: Unused.
- *
- * Returns 0 on success, negative value otherwise.
- */
- int tomoyo_socket_sendmsg_permission(struct socket *sock, struct msghdr *msg,
- int size)
- {
- struct tomoyo_addr_info address;
- const u8 family = tomoyo_sock_family(sock->sk);
- const unsigned int type = sock->type;
- if (!msg->msg_name || !family ||
- (type != SOCK_DGRAM && type != SOCK_RAW))
- return 0;
- address.protocol = type;
- address.operation = TOMOYO_NETWORK_SEND;
- if (family == PF_UNIX)
- return tomoyo_check_unix_address((struct sockaddr *)
- msg->msg_name,
- msg->msg_namelen, &address);
- return tomoyo_check_inet_address((struct sockaddr *) msg->msg_name,
- msg->msg_namelen,
- sock->sk->sk_protocol, &address);
- }
|