Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

TOMOYO: Add socket operation restriction support.

This patch adds support for permission checks for PF_INET/PF_INET6/PF_UNIX
socket's bind()/listen()/connect()/send() operations.

Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: James Morris <jmorris@namei.org>

authored by

Tetsuo Handa and committed by
James Morris
059d84db d58e0da8

+1215 -17
+2
security/tomoyo/Kconfig
··· 1 1 config SECURITY_TOMOYO 2 2 bool "TOMOYO Linux Support" 3 3 depends on SECURITY 4 + depends on NET 4 5 select SECURITYFS 5 6 select SECURITY_PATH 7 + select SECURITY_NETWORK 6 8 default n 7 9 help 8 10 This selects TOMOYO Linux, pathname-based access control.
+1 -1
security/tomoyo/Makefile
··· 1 - obj-y = audit.o common.o condition.o domain.o environ.o file.o gc.o group.o load_policy.o memory.o mount.o realpath.o securityfs_if.o tomoyo.o util.o 1 + obj-y = audit.o common.o condition.o domain.o environ.o file.o gc.o group.o load_policy.o memory.o mount.o network.o realpath.o securityfs_if.o tomoyo.o util.o 2 2 3 3 $(obj)/policy/profile.conf: 4 4 @mkdir -p $(obj)/policy/
+98 -6
security/tomoyo/common.c
··· 44 44 [TOMOYO_MAC_FILE_MOUNT] = "mount", 45 45 [TOMOYO_MAC_FILE_UMOUNT] = "unmount", 46 46 [TOMOYO_MAC_FILE_PIVOT_ROOT] = "pivot_root", 47 + /* CONFIG::network group */ 48 + [TOMOYO_MAC_NETWORK_INET_STREAM_BIND] = "inet_stream_bind", 49 + [TOMOYO_MAC_NETWORK_INET_STREAM_LISTEN] = "inet_stream_listen", 50 + [TOMOYO_MAC_NETWORK_INET_STREAM_CONNECT] = "inet_stream_connect", 51 + [TOMOYO_MAC_NETWORK_INET_DGRAM_BIND] = "inet_dgram_bind", 52 + [TOMOYO_MAC_NETWORK_INET_DGRAM_SEND] = "inet_dgram_send", 53 + [TOMOYO_MAC_NETWORK_INET_RAW_BIND] = "inet_raw_bind", 54 + [TOMOYO_MAC_NETWORK_INET_RAW_SEND] = "inet_raw_send", 55 + [TOMOYO_MAC_NETWORK_UNIX_STREAM_BIND] = "unix_stream_bind", 56 + [TOMOYO_MAC_NETWORK_UNIX_STREAM_LISTEN] = "unix_stream_listen", 57 + [TOMOYO_MAC_NETWORK_UNIX_STREAM_CONNECT] = "unix_stream_connect", 58 + [TOMOYO_MAC_NETWORK_UNIX_DGRAM_BIND] = "unix_dgram_bind", 59 + [TOMOYO_MAC_NETWORK_UNIX_DGRAM_SEND] = "unix_dgram_send", 60 + [TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_BIND] = "unix_seqpacket_bind", 61 + [TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_LISTEN] = "unix_seqpacket_listen", 62 + [TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_CONNECT] = "unix_seqpacket_connect", 47 63 /* CONFIG::misc group */ 48 64 [TOMOYO_MAC_ENVIRON] = "env", 49 65 /* CONFIG group */ 50 66 [TOMOYO_MAX_MAC_INDEX + TOMOYO_MAC_CATEGORY_FILE] = "file", 67 + [TOMOYO_MAX_MAC_INDEX + TOMOYO_MAC_CATEGORY_NETWORK] = "network", 51 68 [TOMOYO_MAX_MAC_INDEX + TOMOYO_MAC_CATEGORY_MISC] = "misc", 52 69 }; 53 70 ··· 152 135 [TOMOYO_TYPE_UMOUNT] = "unmount", 153 136 }; 154 137 138 + /* String table for socket's operation. */ 139 + const char * const tomoyo_socket_keyword[TOMOYO_MAX_NETWORK_OPERATION] = { 140 + [TOMOYO_NETWORK_BIND] = "bind", 141 + [TOMOYO_NETWORK_LISTEN] = "listen", 142 + [TOMOYO_NETWORK_CONNECT] = "connect", 143 + [TOMOYO_NETWORK_SEND] = "send", 144 + }; 145 + 155 146 /* String table for categories. */ 156 147 static const char * const tomoyo_category_keywords 157 148 [TOMOYO_MAX_MAC_CATEGORY_INDEX] = { 158 - [TOMOYO_MAC_CATEGORY_FILE] = "file", 159 - [TOMOYO_MAC_CATEGORY_MISC] = "misc", 149 + [TOMOYO_MAC_CATEGORY_FILE] = "file", 150 + [TOMOYO_MAC_CATEGORY_NETWORK] = "network", 151 + [TOMOYO_MAC_CATEGORY_MISC] = "misc", 160 152 }; 161 153 162 154 /* Permit policy management by non-root user? */ ··· 1068 1042 static const struct { 1069 1043 const char *keyword; 1070 1044 int (*write) (struct tomoyo_acl_param *); 1071 - } tomoyo_callback[2] = { 1045 + } tomoyo_callback[4] = { 1072 1046 { "file ", tomoyo_write_file }, 1047 + { "network inet ", tomoyo_write_inet_network }, 1048 + { "network unix ", tomoyo_write_unix_network }, 1073 1049 { "misc ", tomoyo_write_misc }, 1074 1050 }; 1075 1051 u8 i; ··· 1403 1375 tomoyo_print_number_union(head, &ptr->mode); 1404 1376 tomoyo_print_number_union(head, &ptr->major); 1405 1377 tomoyo_print_number_union(head, &ptr->minor); 1378 + } else if (acl_type == TOMOYO_TYPE_INET_ACL) { 1379 + struct tomoyo_inet_acl *ptr = 1380 + container_of(acl, typeof(*ptr), head); 1381 + const u8 perm = ptr->perm; 1382 + 1383 + for (bit = 0; bit < TOMOYO_MAX_NETWORK_OPERATION; bit++) { 1384 + if (!(perm & (1 << bit))) 1385 + continue; 1386 + if (first) { 1387 + tomoyo_set_group(head, "network inet "); 1388 + tomoyo_set_string(head, tomoyo_proto_keyword 1389 + [ptr->protocol]); 1390 + tomoyo_set_space(head); 1391 + first = false; 1392 + } else { 1393 + tomoyo_set_slash(head); 1394 + } 1395 + tomoyo_set_string(head, tomoyo_socket_keyword[bit]); 1396 + } 1397 + if (first) 1398 + return true; 1399 + tomoyo_set_space(head); 1400 + if (ptr->address.group) { 1401 + tomoyo_set_string(head, "@"); 1402 + tomoyo_set_string(head, ptr->address.group->group_name 1403 + ->name); 1404 + } else { 1405 + char buf[128]; 1406 + tomoyo_print_ip(buf, sizeof(buf), &ptr->address); 1407 + tomoyo_io_printf(head, "%s", buf); 1408 + } 1409 + tomoyo_print_number_union(head, &ptr->port); 1410 + } else if (acl_type == TOMOYO_TYPE_UNIX_ACL) { 1411 + struct tomoyo_unix_acl *ptr = 1412 + container_of(acl, typeof(*ptr), head); 1413 + const u8 perm = ptr->perm; 1414 + 1415 + for (bit = 0; bit < TOMOYO_MAX_NETWORK_OPERATION; bit++) { 1416 + if (!(perm & (1 << bit))) 1417 + continue; 1418 + if (first) { 1419 + tomoyo_set_group(head, "network unix "); 1420 + tomoyo_set_string(head, tomoyo_proto_keyword 1421 + [ptr->protocol]); 1422 + tomoyo_set_space(head); 1423 + first = false; 1424 + } else { 1425 + tomoyo_set_slash(head); 1426 + } 1427 + tomoyo_set_string(head, tomoyo_socket_keyword[bit]); 1428 + } 1429 + if (first) 1430 + return true; 1431 + tomoyo_print_name_union(head, &ptr->name); 1406 1432 } else if (acl_type == TOMOYO_TYPE_MOUNT_ACL) { 1407 1433 struct tomoyo_mount_acl *ptr = 1408 1434 container_of(acl, typeof(*ptr), head); ··· 1630 1548 1631 1549 /* String table for grouping keywords. */ 1632 1550 static const char *tomoyo_group_name[TOMOYO_MAX_GROUP] = { 1633 - [TOMOYO_PATH_GROUP] = "path_group ", 1634 - [TOMOYO_NUMBER_GROUP] = "number_group ", 1551 + [TOMOYO_PATH_GROUP] = "path_group ", 1552 + [TOMOYO_NUMBER_GROUP] = "number_group ", 1553 + [TOMOYO_ADDRESS_GROUP] = "address_group ", 1635 1554 }; 1636 1555 1637 1556 /** ··· 1674 1591 } 1675 1592 1676 1593 /** 1677 - * tomoyo_read_group - Read "struct tomoyo_path_group"/"struct tomoyo_number_group" list. 1594 + * tomoyo_read_group - Read "struct tomoyo_path_group"/"struct tomoyo_number_group"/"struct tomoyo_address_group" list. 1678 1595 * 1679 1596 * @head: Pointer to "struct tomoyo_io_buffer". 1680 1597 * @idx: Index number. ··· 1711 1628 (ptr, 1712 1629 struct tomoyo_number_group, 1713 1630 head)->number); 1631 + } else if (idx == TOMOYO_ADDRESS_GROUP) { 1632 + char buffer[128]; 1633 + 1634 + struct tomoyo_address_group *member = 1635 + container_of(ptr, typeof(*member), 1636 + head); 1637 + tomoyo_print_ip(buffer, sizeof(buffer), 1638 + &member->address); 1639 + tomoyo_io_printf(head, " %s", buffer); 1714 1640 } 1715 1641 tomoyo_set_lf(head); 1716 1642 }
+126 -1
security/tomoyo/common.h
··· 23 23 #include <linux/poll.h> 24 24 #include <linux/binfmts.h> 25 25 #include <linux/highmem.h> 26 + #include <linux/net.h> 27 + #include <linux/inet.h> 28 + #include <linux/in.h> 29 + #include <linux/in6.h> 30 + #include <linux/un.h> 31 + #include <net/sock.h> 32 + #include <net/af_unix.h> 33 + #include <net/ip.h> 34 + #include <net/ipv6.h> 35 + #include <net/udp.h> 26 36 27 37 /********** Constants definitions. **********/ 28 38 ··· 43 33 */ 44 34 #define TOMOYO_HASH_BITS 8 45 35 #define TOMOYO_MAX_HASH (1u<<TOMOYO_HASH_BITS) 36 + 37 + /* 38 + * TOMOYO checks only SOCK_STREAM, SOCK_DGRAM, SOCK_RAW, SOCK_SEQPACKET. 39 + * Therefore, we don't need SOCK_MAX. 40 + */ 41 + #define TOMOYO_SOCK_MAX 6 46 42 47 43 #define TOMOYO_EXEC_TMPSIZE 4096 48 44 ··· 152 136 /* Index numbers for entry type. */ 153 137 enum tomoyo_policy_id { 154 138 TOMOYO_ID_GROUP, 139 + TOMOYO_ID_ADDRESS_GROUP, 155 140 TOMOYO_ID_PATH_GROUP, 156 141 TOMOYO_ID_NUMBER_GROUP, 157 142 TOMOYO_ID_TRANSITION_CONTROL, ··· 183 166 enum tomoyo_group_id { 184 167 TOMOYO_PATH_GROUP, 185 168 TOMOYO_NUMBER_GROUP, 169 + TOMOYO_ADDRESS_GROUP, 186 170 TOMOYO_MAX_GROUP 187 171 }; 188 172 ··· 214 196 TOMOYO_TYPE_PATH_NUMBER_ACL, 215 197 TOMOYO_TYPE_MKDEV_ACL, 216 198 TOMOYO_TYPE_MOUNT_ACL, 199 + TOMOYO_TYPE_INET_ACL, 200 + TOMOYO_TYPE_UNIX_ACL, 217 201 TOMOYO_TYPE_ENV_ACL, 218 202 }; 219 203 ··· 247 227 TOMOYO_TYPE_MKBLOCK, 248 228 TOMOYO_TYPE_MKCHAR, 249 229 TOMOYO_MAX_MKDEV_OPERATION 230 + }; 231 + 232 + /* Index numbers for socket operations. */ 233 + enum tomoyo_network_acl_index { 234 + TOMOYO_NETWORK_BIND, /* bind() operation. */ 235 + TOMOYO_NETWORK_LISTEN, /* listen() operation. */ 236 + TOMOYO_NETWORK_CONNECT, /* connect() operation. */ 237 + TOMOYO_NETWORK_SEND, /* send() operation. */ 238 + TOMOYO_MAX_NETWORK_OPERATION 250 239 }; 251 240 252 241 /* Index numbers for access controls with two pathnames. */ ··· 330 301 TOMOYO_MAC_FILE_MOUNT, 331 302 TOMOYO_MAC_FILE_UMOUNT, 332 303 TOMOYO_MAC_FILE_PIVOT_ROOT, 304 + TOMOYO_MAC_NETWORK_INET_STREAM_BIND, 305 + TOMOYO_MAC_NETWORK_INET_STREAM_LISTEN, 306 + TOMOYO_MAC_NETWORK_INET_STREAM_CONNECT, 307 + TOMOYO_MAC_NETWORK_INET_DGRAM_BIND, 308 + TOMOYO_MAC_NETWORK_INET_DGRAM_SEND, 309 + TOMOYO_MAC_NETWORK_INET_RAW_BIND, 310 + TOMOYO_MAC_NETWORK_INET_RAW_SEND, 311 + TOMOYO_MAC_NETWORK_UNIX_STREAM_BIND, 312 + TOMOYO_MAC_NETWORK_UNIX_STREAM_LISTEN, 313 + TOMOYO_MAC_NETWORK_UNIX_STREAM_CONNECT, 314 + TOMOYO_MAC_NETWORK_UNIX_DGRAM_BIND, 315 + TOMOYO_MAC_NETWORK_UNIX_DGRAM_SEND, 316 + TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_BIND, 317 + TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_LISTEN, 318 + TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_CONNECT, 333 319 TOMOYO_MAC_ENVIRON, 334 320 TOMOYO_MAX_MAC_INDEX 335 321 }; ··· 352 308 /* Index numbers for category of functionality. */ 353 309 enum tomoyo_mac_category_index { 354 310 TOMOYO_MAC_CATEGORY_FILE, 311 + TOMOYO_MAC_CATEGORY_NETWORK, 355 312 TOMOYO_MAC_CATEGORY_MISC, 356 313 TOMOYO_MAX_MAC_CATEGORY_INDEX 357 314 }; ··· 448 403 const struct tomoyo_path_info *name; 449 404 } environ; 450 405 struct { 406 + const __be32 *address; 407 + u16 port; 408 + /* One of values smaller than TOMOYO_SOCK_MAX. */ 409 + u8 protocol; 410 + /* One of values in "enum tomoyo_network_acl_index". */ 411 + u8 operation; 412 + bool is_ipv6; 413 + } inet_network; 414 + struct { 415 + const struct tomoyo_path_info *address; 416 + /* One of values smaller than TOMOYO_SOCK_MAX. */ 417 + u8 protocol; 418 + /* One of values in "enum tomoyo_network_acl_index". */ 419 + u8 operation; 420 + } unix_network; 421 + struct { 451 422 const struct tomoyo_path_info *type; 452 423 const struct tomoyo_path_info *dir; 453 424 const struct tomoyo_path_info *dev; ··· 509 448 u8 value_type[2]; 510 449 }; 511 450 512 - /* Structure for "path_group"/"number_group" directive. */ 451 + /* Structure for holding an IP address. */ 452 + struct tomoyo_ipaddr_union { 453 + struct in6_addr ip[2]; /* Big endian. */ 454 + struct tomoyo_group *group; /* Pointer to address group. */ 455 + bool is_ipv6; /* Valid only if @group == NULL. */ 456 + }; 457 + 458 + /* Structure for "path_group"/"number_group"/"address_group" directive. */ 513 459 struct tomoyo_group { 514 460 struct tomoyo_shared_acl_head head; 515 461 const struct tomoyo_path_info *group_name; ··· 533 465 struct tomoyo_number_group { 534 466 struct tomoyo_acl_head head; 535 467 struct tomoyo_number_union number; 468 + }; 469 + 470 + /* Structure for "address_group" directive. */ 471 + struct tomoyo_address_group { 472 + struct tomoyo_acl_head head; 473 + /* Structure for holding an IP address. */ 474 + struct tomoyo_ipaddr_union address; 536 475 }; 537 476 538 477 /* Subset of "struct stat". Used by conditional ACL and audit logs. */ ··· 725 650 const struct tomoyo_path_info *env; /* environment variable */ 726 651 }; 727 652 653 + /* Structure for "network inet" directive. */ 654 + struct tomoyo_inet_acl { 655 + struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_INET_ACL */ 656 + u8 protocol; 657 + u8 perm; /* Bitmask of values in "enum tomoyo_network_acl_index" */ 658 + struct tomoyo_ipaddr_union address; 659 + struct tomoyo_number_union port; 660 + }; 661 + 662 + /* Structure for "network unix" directive. */ 663 + struct tomoyo_unix_acl { 664 + struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_UNIX_ACL */ 665 + u8 protocol; 666 + u8 perm; /* Bitmask of values in "enum tomoyo_network_acl_index" */ 667 + struct tomoyo_name_union name; 668 + }; 669 + 728 670 /* Structure for holding a line from /sys/kernel/security/tomoyo/ interface. */ 729 671 struct tomoyo_acl_param { 730 672 char *data; ··· 885 793 886 794 /********** Function prototypes. **********/ 887 795 796 + bool tomoyo_address_matches_group(const bool is_ipv6, const __be32 *address, 797 + const struct tomoyo_group *group); 888 798 bool tomoyo_compare_number_union(const unsigned long value, 889 799 const struct tomoyo_number_union *ptr); 890 800 bool tomoyo_condition(struct tomoyo_request_info *r, ··· 902 808 bool tomoyo_number_matches_group(const unsigned long min, 903 809 const unsigned long max, 904 810 const struct tomoyo_group *group); 811 + bool tomoyo_parse_ipaddr_union(struct tomoyo_acl_param *param, 812 + struct tomoyo_ipaddr_union *ptr); 905 813 bool tomoyo_parse_name_union(struct tomoyo_acl_param *param, 906 814 struct tomoyo_name_union *ptr); 907 815 bool tomoyo_parse_number_union(struct tomoyo_acl_param *param, ··· 913 817 bool tomoyo_permstr(const char *string, const char *keyword); 914 818 bool tomoyo_str_starts(char **src, const char *find); 915 819 char *tomoyo_encode(const char *str); 820 + char *tomoyo_encode2(const char *str, int str_len); 916 821 char *tomoyo_init_log(struct tomoyo_request_info *r, int len, const char *fmt, 917 822 va_list args); 918 823 char *tomoyo_read_token(struct tomoyo_acl_param *param); ··· 952 855 const struct tomoyo_path_info *filename); 953 856 int tomoyo_poll_control(struct file *file, poll_table *wait); 954 857 int tomoyo_poll_log(struct file *file, poll_table *wait); 858 + int tomoyo_socket_bind_permission(struct socket *sock, struct sockaddr *addr, 859 + int addr_len); 860 + int tomoyo_socket_connect_permission(struct socket *sock, 861 + struct sockaddr *addr, int addr_len); 862 + int tomoyo_socket_listen_permission(struct socket *sock); 863 + int tomoyo_socket_sendmsg_permission(struct socket *sock, struct msghdr *msg, 864 + int size); 955 865 int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...) 956 866 __printf(2, 3); 957 867 int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size, ··· 978 874 int tomoyo_write_file(struct tomoyo_acl_param *param); 979 875 int tomoyo_write_group(struct tomoyo_acl_param *param, const u8 type); 980 876 int tomoyo_write_misc(struct tomoyo_acl_param *param); 877 + int tomoyo_write_inet_network(struct tomoyo_acl_param *param); 981 878 int tomoyo_write_transition_control(struct tomoyo_acl_param *param, 982 879 const u8 type); 880 + int tomoyo_write_unix_network(struct tomoyo_acl_param *param); 983 881 ssize_t tomoyo_read_control(struct tomoyo_io_buffer *head, char __user *buffer, 984 882 const int buffer_len); 985 883 ssize_t tomoyo_write_control(struct tomoyo_io_buffer *head, ··· 1017 911 void tomoyo_memory_free(void *ptr); 1018 912 void tomoyo_normalize_line(unsigned char *buffer); 1019 913 void tomoyo_notify_gc(struct tomoyo_io_buffer *head, const bool is_register); 914 + void tomoyo_print_ip(char *buf, const unsigned int size, 915 + const struct tomoyo_ipaddr_union *ptr); 1020 916 void tomoyo_print_ulong(char *buffer, const int buffer_len, 1021 917 const unsigned long value, const u8 type); 1022 918 void tomoyo_put_name_union(struct tomoyo_name_union *ptr); ··· 1041 933 + TOMOYO_MAX_MAC_CATEGORY_INDEX]; 1042 934 extern const char * const tomoyo_mode[TOMOYO_CONFIG_MAX_MODE]; 1043 935 extern const char * const tomoyo_path_keyword[TOMOYO_MAX_PATH_OPERATION]; 936 + extern const char * const tomoyo_proto_keyword[TOMOYO_SOCK_MAX]; 937 + extern const char * const tomoyo_socket_keyword[TOMOYO_MAX_NETWORK_OPERATION]; 1044 938 extern const u8 tomoyo_index2category[TOMOYO_MAX_MAC_INDEX]; 1045 939 extern const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION]; 1046 940 extern const u8 tomoyo_pnnn2mac[TOMOYO_MAX_MKDEV_OPERATION]; ··· 1219 1109 return a->values[0] == b->values[0] && a->values[1] == b->values[1] && 1220 1110 a->group == b->group && a->value_type[0] == b->value_type[0] && 1221 1111 a->value_type[1] == b->value_type[1]; 1112 + } 1113 + 1114 + /** 1115 + * tomoyo_same_ipaddr_union - Check for duplicated "struct tomoyo_ipaddr_union" entry. 1116 + * 1117 + * @a: Pointer to "struct tomoyo_ipaddr_union". 1118 + * @b: Pointer to "struct tomoyo_ipaddr_union". 1119 + * 1120 + * Returns true if @a == @b, false otherwise. 1121 + */ 1122 + static inline bool tomoyo_same_ipaddr_union 1123 + (const struct tomoyo_ipaddr_union *a, const struct tomoyo_ipaddr_union *b) 1124 + { 1125 + return !memcmp(a->ip, b->ip, sizeof(a->ip)) && a->group == b->group && 1126 + a->is_ipv6 == b->is_ipv6; 1222 1127 } 1223 1128 1224 1129 /**
+39 -1
security/tomoyo/gc.c
··· 16 16 /* Size of an element. */ 17 17 static const u8 tomoyo_element_size[TOMOYO_MAX_POLICY] = { 18 18 [TOMOYO_ID_GROUP] = sizeof(struct tomoyo_group), 19 + [TOMOYO_ID_ADDRESS_GROUP] = sizeof(struct tomoyo_address_group), 19 20 [TOMOYO_ID_PATH_GROUP] = sizeof(struct tomoyo_path_group), 20 21 [TOMOYO_ID_NUMBER_GROUP] = sizeof(struct tomoyo_number_group), 21 22 [TOMOYO_ID_AGGREGATOR] = sizeof(struct tomoyo_aggregator), ··· 37 36 [TOMOYO_TYPE_PATH_NUMBER_ACL] = sizeof(struct tomoyo_path_number_acl), 38 37 [TOMOYO_TYPE_MKDEV_ACL] = sizeof(struct tomoyo_mkdev_acl), 39 38 [TOMOYO_TYPE_MOUNT_ACL] = sizeof(struct tomoyo_mount_acl), 39 + [TOMOYO_TYPE_INET_ACL] = sizeof(struct tomoyo_inet_acl), 40 + [TOMOYO_TYPE_UNIX_ACL] = sizeof(struct tomoyo_unix_acl), 40 41 [TOMOYO_TYPE_ENV_ACL] = sizeof(struct tomoyo_env_acl), 41 42 }; 42 43 ··· 305 302 tomoyo_put_name(entry->env); 306 303 } 307 304 break; 305 + case TOMOYO_TYPE_INET_ACL: 306 + { 307 + struct tomoyo_inet_acl *entry = 308 + container_of(acl, typeof(*entry), head); 309 + 310 + tomoyo_put_group(entry->address.group); 311 + tomoyo_put_number_union(&entry->port); 312 + } 313 + break; 314 + case TOMOYO_TYPE_UNIX_ACL: 315 + { 316 + struct tomoyo_unix_acl *entry = 317 + container_of(acl, typeof(*entry), head); 318 + 319 + tomoyo_put_name_union(&entry->name); 320 + } 321 + break; 308 322 } 309 323 } 310 324 ··· 451 431 } 452 432 453 433 /** 434 + * tomoyo_del_address_group - Delete members in "struct tomoyo_address_group". 435 + * 436 + * @element: Pointer to "struct list_head". 437 + * 438 + * Returns nothing. 439 + */ 440 + static inline void tomoyo_del_address_group(struct list_head *element) 441 + { 442 + /* Nothing to do. */ 443 + } 444 + 445 + /** 454 446 * tomoyo_del_number_group - Delete members in "struct tomoyo_number_group". 455 447 * 456 448 * @element: Pointer to "struct list_head". ··· 559 527 case 0: 560 528 id = TOMOYO_ID_PATH_GROUP; 561 529 break; 562 - default: 530 + case 1: 563 531 id = TOMOYO_ID_NUMBER_GROUP; 532 + break; 533 + default: 534 + id = TOMOYO_ID_ADDRESS_GROUP; 564 535 break; 565 536 } 566 537 list_for_each_entry(group, list, head.list) { ··· 668 633 break; 669 634 case TOMOYO_ID_PATH_GROUP: 670 635 tomoyo_del_path_group(element); 636 + break; 637 + case TOMOYO_ID_ADDRESS_GROUP: 638 + tomoyo_del_address_group(element); 671 639 break; 672 640 case TOMOYO_ID_GROUP: 673 641 tomoyo_del_group(element);
+60 -1
security/tomoyo/group.c
··· 42 42 } 43 43 44 44 /** 45 - * tomoyo_write_group - Write "struct tomoyo_path_group"/"struct tomoyo_number_group" list. 45 + * tomoyo_same_address_group - Check for duplicated "struct tomoyo_address_group" entry. 46 + * 47 + * @a: Pointer to "struct tomoyo_acl_head". 48 + * @b: Pointer to "struct tomoyo_acl_head". 49 + * 50 + * Returns true if @a == @b, false otherwise. 51 + */ 52 + static bool tomoyo_same_address_group(const struct tomoyo_acl_head *a, 53 + const struct tomoyo_acl_head *b) 54 + { 55 + const struct tomoyo_address_group *p1 = container_of(a, typeof(*p1), 56 + head); 57 + const struct tomoyo_address_group *p2 = container_of(b, typeof(*p2), 58 + head); 59 + 60 + return tomoyo_same_ipaddr_union(&p1->address, &p2->address); 61 + } 62 + 63 + /** 64 + * tomoyo_write_group - Write "struct tomoyo_path_group"/"struct tomoyo_number_group"/"struct tomoyo_address_group" list. 46 65 * 47 66 * @param: Pointer to "struct tomoyo_acl_param". 48 67 * @type: Type of this group. ··· 96 77 * tomoyo_put_number_union() is not needed because 97 78 * param->data[0] != '@'. 98 79 */ 80 + } else { 81 + struct tomoyo_address_group e = { }; 82 + 83 + if (param->data[0] == '@' || 84 + !tomoyo_parse_ipaddr_union(param, &e.address)) 85 + goto out; 86 + error = tomoyo_update_policy(&e.head, sizeof(e), param, 87 + tomoyo_same_address_group); 99 88 } 100 89 out: 101 90 tomoyo_put_group(group); ··· 158 131 continue; 159 132 if (min > member->number.values[1] || 160 133 max < member->number.values[0]) 134 + continue; 135 + matched = true; 136 + break; 137 + } 138 + return matched; 139 + } 140 + 141 + /** 142 + * tomoyo_address_matches_group - Check whether the given address matches members of the given address group. 143 + * 144 + * @is_ipv6: True if @address is an IPv6 address. 145 + * @address: An IPv4 or IPv6 address. 146 + * @group: Pointer to "struct tomoyo_address_group". 147 + * 148 + * Returns true if @address matches addresses in @group group, false otherwise. 149 + * 150 + * Caller holds tomoyo_read_lock(). 151 + */ 152 + bool tomoyo_address_matches_group(const bool is_ipv6, const __be32 *address, 153 + const struct tomoyo_group *group) 154 + { 155 + struct tomoyo_address_group *member; 156 + bool matched = false; 157 + const u8 size = is_ipv6 ? 16 : 4; 158 + 159 + list_for_each_entry_rcu(member, &group->member_list, head.list) { 160 + if (member->head.is_deleted) 161 + continue; 162 + if (member->address.is_ipv6 != is_ipv6) 163 + continue; 164 + if (memcmp(&member->address.ip[0], address, size) > 0 || 165 + memcmp(address, &member->address.ip[1], size) > 0) 161 166 continue; 162 167 matched = true; 163 168 break;
+771
security/tomoyo/network.c
··· 1 + /* 2 + * security/tomoyo/network.c 3 + * 4 + * Copyright (C) 2005-2011 NTT DATA CORPORATION 5 + */ 6 + 7 + #include "common.h" 8 + #include <linux/slab.h> 9 + 10 + /* Structure for holding inet domain socket's address. */ 11 + struct tomoyo_inet_addr_info { 12 + __be16 port; /* In network byte order. */ 13 + const __be32 *address; /* In network byte order. */ 14 + bool is_ipv6; 15 + }; 16 + 17 + /* Structure for holding unix domain socket's address. */ 18 + struct tomoyo_unix_addr_info { 19 + u8 *addr; /* This may not be '\0' terminated string. */ 20 + unsigned int addr_len; 21 + }; 22 + 23 + /* Structure for holding socket address. */ 24 + struct tomoyo_addr_info { 25 + u8 protocol; 26 + u8 operation; 27 + struct tomoyo_inet_addr_info inet; 28 + struct tomoyo_unix_addr_info unix0; 29 + }; 30 + 31 + /* String table for socket's protocols. */ 32 + const char * const tomoyo_proto_keyword[TOMOYO_SOCK_MAX] = { 33 + [SOCK_STREAM] = "stream", 34 + [SOCK_DGRAM] = "dgram", 35 + [SOCK_RAW] = "raw", 36 + [SOCK_SEQPACKET] = "seqpacket", 37 + [0] = " ", /* Dummy for avoiding NULL pointer dereference. */ 38 + [4] = " ", /* Dummy for avoiding NULL pointer dereference. */ 39 + }; 40 + 41 + /** 42 + * tomoyo_parse_ipaddr_union - Parse an IP address. 43 + * 44 + * @param: Pointer to "struct tomoyo_acl_param". 45 + * @ptr: Pointer to "struct tomoyo_ipaddr_union". 46 + * 47 + * Returns true on success, false otherwise. 48 + */ 49 + bool tomoyo_parse_ipaddr_union(struct tomoyo_acl_param *param, 50 + struct tomoyo_ipaddr_union *ptr) 51 + { 52 + u8 * const min = ptr->ip[0].in6_u.u6_addr8; 53 + u8 * const max = ptr->ip[1].in6_u.u6_addr8; 54 + char *address = tomoyo_read_token(param); 55 + const char *end; 56 + 57 + if (!strchr(address, ':') && 58 + in4_pton(address, -1, min, '-', &end) > 0) { 59 + ptr->is_ipv6 = false; 60 + if (!*end) 61 + ptr->ip[1].s6_addr32[0] = ptr->ip[0].s6_addr32[0]; 62 + else if (*end++ != '-' || 63 + in4_pton(end, -1, max, '\0', &end) <= 0 || *end) 64 + return false; 65 + return true; 66 + } 67 + if (in6_pton(address, -1, min, '-', &end) > 0) { 68 + ptr->is_ipv6 = true; 69 + if (!*end) 70 + memmove(max, min, sizeof(u16) * 8); 71 + else if (*end++ != '-' || 72 + in6_pton(end, -1, max, '\0', &end) <= 0 || *end) 73 + return false; 74 + return true; 75 + } 76 + return false; 77 + } 78 + 79 + /** 80 + * tomoyo_print_ipv4 - Print an IPv4 address. 81 + * 82 + * @buffer: Buffer to write to. 83 + * @buffer_len: Size of @buffer. 84 + * @min_ip: Pointer to __be32. 85 + * @max_ip: Pointer to __be32. 86 + * 87 + * Returns nothing. 88 + */ 89 + static void tomoyo_print_ipv4(char *buffer, const unsigned int buffer_len, 90 + const __be32 *min_ip, const __be32 *max_ip) 91 + { 92 + snprintf(buffer, buffer_len, "%pI4%c%pI4", min_ip, 93 + *min_ip == *max_ip ? '\0' : '-', max_ip); 94 + } 95 + 96 + /** 97 + * tomoyo_print_ipv6 - Print an IPv6 address. 98 + * 99 + * @buffer: Buffer to write to. 100 + * @buffer_len: Size of @buffer. 101 + * @min_ip: Pointer to "struct in6_addr". 102 + * @max_ip: Pointer to "struct in6_addr". 103 + * 104 + * Returns nothing. 105 + */ 106 + static void tomoyo_print_ipv6(char *buffer, const unsigned int buffer_len, 107 + const struct in6_addr *min_ip, 108 + const struct in6_addr *max_ip) 109 + { 110 + snprintf(buffer, buffer_len, "%pI6c%c%pI6c", min_ip, 111 + !memcmp(min_ip, max_ip, 16) ? '\0' : '-', max_ip); 112 + } 113 + 114 + /** 115 + * tomoyo_print_ip - Print an IP address. 116 + * 117 + * @buf: Buffer to write to. 118 + * @size: Size of @buf. 119 + * @ptr: Pointer to "struct ipaddr_union". 120 + * 121 + * Returns nothing. 122 + */ 123 + void tomoyo_print_ip(char *buf, const unsigned int size, 124 + const struct tomoyo_ipaddr_union *ptr) 125 + { 126 + if (ptr->is_ipv6) 127 + tomoyo_print_ipv6(buf, size, &ptr->ip[0], &ptr->ip[1]); 128 + else 129 + tomoyo_print_ipv4(buf, size, &ptr->ip[0].s6_addr32[0], 130 + &ptr->ip[1].s6_addr32[0]); 131 + } 132 + 133 + /* 134 + * Mapping table from "enum tomoyo_network_acl_index" to 135 + * "enum tomoyo_mac_index" for inet domain socket. 136 + */ 137 + static const u8 tomoyo_inet2mac 138 + [TOMOYO_SOCK_MAX][TOMOYO_MAX_NETWORK_OPERATION] = { 139 + [SOCK_STREAM] = { 140 + [TOMOYO_NETWORK_BIND] = TOMOYO_MAC_NETWORK_INET_STREAM_BIND, 141 + [TOMOYO_NETWORK_LISTEN] = 142 + TOMOYO_MAC_NETWORK_INET_STREAM_LISTEN, 143 + [TOMOYO_NETWORK_CONNECT] = 144 + TOMOYO_MAC_NETWORK_INET_STREAM_CONNECT, 145 + }, 146 + [SOCK_DGRAM] = { 147 + [TOMOYO_NETWORK_BIND] = TOMOYO_MAC_NETWORK_INET_DGRAM_BIND, 148 + [TOMOYO_NETWORK_SEND] = TOMOYO_MAC_NETWORK_INET_DGRAM_SEND, 149 + }, 150 + [SOCK_RAW] = { 151 + [TOMOYO_NETWORK_BIND] = TOMOYO_MAC_NETWORK_INET_RAW_BIND, 152 + [TOMOYO_NETWORK_SEND] = TOMOYO_MAC_NETWORK_INET_RAW_SEND, 153 + }, 154 + }; 155 + 156 + /* 157 + * Mapping table from "enum tomoyo_network_acl_index" to 158 + * "enum tomoyo_mac_index" for unix domain socket. 159 + */ 160 + static const u8 tomoyo_unix2mac 161 + [TOMOYO_SOCK_MAX][TOMOYO_MAX_NETWORK_OPERATION] = { 162 + [SOCK_STREAM] = { 163 + [TOMOYO_NETWORK_BIND] = TOMOYO_MAC_NETWORK_UNIX_STREAM_BIND, 164 + [TOMOYO_NETWORK_LISTEN] = 165 + TOMOYO_MAC_NETWORK_UNIX_STREAM_LISTEN, 166 + [TOMOYO_NETWORK_CONNECT] = 167 + TOMOYO_MAC_NETWORK_UNIX_STREAM_CONNECT, 168 + }, 169 + [SOCK_DGRAM] = { 170 + [TOMOYO_NETWORK_BIND] = TOMOYO_MAC_NETWORK_UNIX_DGRAM_BIND, 171 + [TOMOYO_NETWORK_SEND] = TOMOYO_MAC_NETWORK_UNIX_DGRAM_SEND, 172 + }, 173 + [SOCK_SEQPACKET] = { 174 + [TOMOYO_NETWORK_BIND] = 175 + TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_BIND, 176 + [TOMOYO_NETWORK_LISTEN] = 177 + TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_LISTEN, 178 + [TOMOYO_NETWORK_CONNECT] = 179 + TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_CONNECT, 180 + }, 181 + }; 182 + 183 + /** 184 + * tomoyo_same_inet_acl - Check for duplicated "struct tomoyo_inet_acl" entry. 185 + * 186 + * @a: Pointer to "struct tomoyo_acl_info". 187 + * @b: Pointer to "struct tomoyo_acl_info". 188 + * 189 + * Returns true if @a == @b except permission bits, false otherwise. 190 + */ 191 + static bool tomoyo_same_inet_acl(const struct tomoyo_acl_info *a, 192 + const struct tomoyo_acl_info *b) 193 + { 194 + const struct tomoyo_inet_acl *p1 = container_of(a, typeof(*p1), head); 195 + const struct tomoyo_inet_acl *p2 = container_of(b, typeof(*p2), head); 196 + 197 + return p1->protocol == p2->protocol && 198 + tomoyo_same_ipaddr_union(&p1->address, &p2->address) && 199 + tomoyo_same_number_union(&p1->port, &p2->port); 200 + } 201 + 202 + /** 203 + * tomoyo_same_unix_acl - Check for duplicated "struct tomoyo_unix_acl" entry. 204 + * 205 + * @a: Pointer to "struct tomoyo_acl_info". 206 + * @b: Pointer to "struct tomoyo_acl_info". 207 + * 208 + * Returns true if @a == @b except permission bits, false otherwise. 209 + */ 210 + static bool tomoyo_same_unix_acl(const struct tomoyo_acl_info *a, 211 + const struct tomoyo_acl_info *b) 212 + { 213 + const struct tomoyo_unix_acl *p1 = container_of(a, typeof(*p1), head); 214 + const struct tomoyo_unix_acl *p2 = container_of(b, typeof(*p2), head); 215 + 216 + return p1->protocol == p2->protocol && 217 + tomoyo_same_name_union(&p1->name, &p2->name); 218 + } 219 + 220 + /** 221 + * tomoyo_merge_inet_acl - Merge duplicated "struct tomoyo_inet_acl" entry. 222 + * 223 + * @a: Pointer to "struct tomoyo_acl_info". 224 + * @b: Pointer to "struct tomoyo_acl_info". 225 + * @is_delete: True for @a &= ~@b, false for @a |= @b. 226 + * 227 + * Returns true if @a is empty, false otherwise. 228 + */ 229 + static bool tomoyo_merge_inet_acl(struct tomoyo_acl_info *a, 230 + struct tomoyo_acl_info *b, 231 + const bool is_delete) 232 + { 233 + u8 * const a_perm = 234 + &container_of(a, struct tomoyo_inet_acl, head)->perm; 235 + u8 perm = *a_perm; 236 + const u8 b_perm = container_of(b, struct tomoyo_inet_acl, head)->perm; 237 + 238 + if (is_delete) 239 + perm &= ~b_perm; 240 + else 241 + perm |= b_perm; 242 + *a_perm = perm; 243 + return !perm; 244 + } 245 + 246 + /** 247 + * tomoyo_merge_unix_acl - Merge duplicated "struct tomoyo_unix_acl" entry. 248 + * 249 + * @a: Pointer to "struct tomoyo_acl_info". 250 + * @b: Pointer to "struct tomoyo_acl_info". 251 + * @is_delete: True for @a &= ~@b, false for @a |= @b. 252 + * 253 + * Returns true if @a is empty, false otherwise. 254 + */ 255 + static bool tomoyo_merge_unix_acl(struct tomoyo_acl_info *a, 256 + struct tomoyo_acl_info *b, 257 + const bool is_delete) 258 + { 259 + u8 * const a_perm = 260 + &container_of(a, struct tomoyo_unix_acl, head)->perm; 261 + u8 perm = *a_perm; 262 + const u8 b_perm = container_of(b, struct tomoyo_unix_acl, head)->perm; 263 + 264 + if (is_delete) 265 + perm &= ~b_perm; 266 + else 267 + perm |= b_perm; 268 + *a_perm = perm; 269 + return !perm; 270 + } 271 + 272 + /** 273 + * tomoyo_write_inet_network - Write "struct tomoyo_inet_acl" list. 274 + * 275 + * @param: Pointer to "struct tomoyo_acl_param". 276 + * 277 + * Returns 0 on success, negative value otherwise. 278 + * 279 + * Caller holds tomoyo_read_lock(). 280 + */ 281 + int tomoyo_write_inet_network(struct tomoyo_acl_param *param) 282 + { 283 + struct tomoyo_inet_acl e = { .head.type = TOMOYO_TYPE_INET_ACL }; 284 + int error = -EINVAL; 285 + u8 type; 286 + const char *protocol = tomoyo_read_token(param); 287 + const char *operation = tomoyo_read_token(param); 288 + 289 + for (e.protocol = 0; e.protocol < TOMOYO_SOCK_MAX; e.protocol++) 290 + if (!strcmp(protocol, tomoyo_proto_keyword[e.protocol])) 291 + break; 292 + for (type = 0; type < TOMOYO_MAX_NETWORK_OPERATION; type++) 293 + if (tomoyo_permstr(operation, tomoyo_socket_keyword[type])) 294 + e.perm |= 1 << type; 295 + if (e.protocol == TOMOYO_SOCK_MAX || !e.perm) 296 + return -EINVAL; 297 + if (param->data[0] == '@') { 298 + param->data++; 299 + e.address.group = 300 + tomoyo_get_group(param, TOMOYO_ADDRESS_GROUP); 301 + if (!e.address.group) 302 + return -ENOMEM; 303 + } else { 304 + if (!tomoyo_parse_ipaddr_union(param, &e.address)) 305 + goto out; 306 + } 307 + if (!tomoyo_parse_number_union(param, &e.port) || 308 + e.port.values[1] > 65535) 309 + goto out; 310 + error = tomoyo_update_domain(&e.head, sizeof(e), param, 311 + tomoyo_same_inet_acl, 312 + tomoyo_merge_inet_acl); 313 + out: 314 + tomoyo_put_group(e.address.group); 315 + tomoyo_put_number_union(&e.port); 316 + return error; 317 + } 318 + 319 + /** 320 + * tomoyo_write_unix_network - Write "struct tomoyo_unix_acl" list. 321 + * 322 + * @param: Pointer to "struct tomoyo_acl_param". 323 + * 324 + * Returns 0 on success, negative value otherwise. 325 + */ 326 + int tomoyo_write_unix_network(struct tomoyo_acl_param *param) 327 + { 328 + struct tomoyo_unix_acl e = { .head.type = TOMOYO_TYPE_UNIX_ACL }; 329 + int error; 330 + u8 type; 331 + const char *protocol = tomoyo_read_token(param); 332 + const char *operation = tomoyo_read_token(param); 333 + 334 + for (e.protocol = 0; e.protocol < TOMOYO_SOCK_MAX; e.protocol++) 335 + if (!strcmp(protocol, tomoyo_proto_keyword[e.protocol])) 336 + break; 337 + for (type = 0; type < TOMOYO_MAX_NETWORK_OPERATION; type++) 338 + if (tomoyo_permstr(operation, tomoyo_socket_keyword[type])) 339 + e.perm |= 1 << type; 340 + if (e.protocol == TOMOYO_SOCK_MAX || !e.perm) 341 + return -EINVAL; 342 + if (!tomoyo_parse_name_union(param, &e.name)) 343 + return -EINVAL; 344 + error = tomoyo_update_domain(&e.head, sizeof(e), param, 345 + tomoyo_same_unix_acl, 346 + tomoyo_merge_unix_acl); 347 + tomoyo_put_name_union(&e.name); 348 + return error; 349 + } 350 + 351 + /** 352 + * tomoyo_audit_net_log - Audit network log. 353 + * 354 + * @r: Pointer to "struct tomoyo_request_info". 355 + * @family: Name of socket family ("inet" or "unix"). 356 + * @protocol: Name of protocol in @family. 357 + * @operation: Name of socket operation. 358 + * @address: Name of address. 359 + * 360 + * Returns 0 on success, negative value otherwise. 361 + */ 362 + static int tomoyo_audit_net_log(struct tomoyo_request_info *r, 363 + const char *family, const u8 protocol, 364 + const u8 operation, const char *address) 365 + { 366 + return tomoyo_supervisor(r, "network %s %s %s %s\n", family, 367 + tomoyo_proto_keyword[protocol], 368 + tomoyo_socket_keyword[operation], address); 369 + } 370 + 371 + /** 372 + * tomoyo_audit_inet_log - Audit INET network log. 373 + * 374 + * @r: Pointer to "struct tomoyo_request_info". 375 + * 376 + * Returns 0 on success, negative value otherwise. 377 + */ 378 + static int tomoyo_audit_inet_log(struct tomoyo_request_info *r) 379 + { 380 + char buf[128]; 381 + int len; 382 + const __be32 *address = r->param.inet_network.address; 383 + 384 + if (r->param.inet_network.is_ipv6) 385 + tomoyo_print_ipv6(buf, sizeof(buf), (const struct in6_addr *) 386 + address, (const struct in6_addr *) address); 387 + else 388 + tomoyo_print_ipv4(buf, sizeof(buf), address, address); 389 + len = strlen(buf); 390 + snprintf(buf + len, sizeof(buf) - len, " %u", 391 + r->param.inet_network.port); 392 + return tomoyo_audit_net_log(r, "inet", r->param.inet_network.protocol, 393 + r->param.inet_network.operation, buf); 394 + } 395 + 396 + /** 397 + * tomoyo_audit_unix_log - Audit UNIX network log. 398 + * 399 + * @r: Pointer to "struct tomoyo_request_info". 400 + * 401 + * Returns 0 on success, negative value otherwise. 402 + */ 403 + static int tomoyo_audit_unix_log(struct tomoyo_request_info *r) 404 + { 405 + return tomoyo_audit_net_log(r, "unix", r->param.unix_network.protocol, 406 + r->param.unix_network.operation, 407 + r->param.unix_network.address->name); 408 + } 409 + 410 + /** 411 + * tomoyo_check_inet_acl - Check permission for inet domain socket operation. 412 + * 413 + * @r: Pointer to "struct tomoyo_request_info". 414 + * @ptr: Pointer to "struct tomoyo_acl_info". 415 + * 416 + * Returns true if granted, false otherwise. 417 + */ 418 + static bool tomoyo_check_inet_acl(struct tomoyo_request_info *r, 419 + const struct tomoyo_acl_info *ptr) 420 + { 421 + const struct tomoyo_inet_acl *acl = 422 + container_of(ptr, typeof(*acl), head); 423 + const u8 size = r->param.inet_network.is_ipv6 ? 16 : 4; 424 + 425 + if (!(acl->perm & (1 << r->param.inet_network.operation)) || 426 + !tomoyo_compare_number_union(r->param.inet_network.port, 427 + &acl->port)) 428 + return false; 429 + if (acl->address.group) 430 + return tomoyo_address_matches_group 431 + (r->param.inet_network.is_ipv6, 432 + r->param.inet_network.address, acl->address.group); 433 + return acl->address.is_ipv6 == r->param.inet_network.is_ipv6 && 434 + memcmp(&acl->address.ip[0], 435 + r->param.inet_network.address, size) <= 0 && 436 + memcmp(r->param.inet_network.address, 437 + &acl->address.ip[1], size) <= 0; 438 + } 439 + 440 + /** 441 + * tomoyo_check_unix_acl - Check permission for unix domain socket operation. 442 + * 443 + * @r: Pointer to "struct tomoyo_request_info". 444 + * @ptr: Pointer to "struct tomoyo_acl_info". 445 + * 446 + * Returns true if granted, false otherwise. 447 + */ 448 + static bool tomoyo_check_unix_acl(struct tomoyo_request_info *r, 449 + const struct tomoyo_acl_info *ptr) 450 + { 451 + const struct tomoyo_unix_acl *acl = 452 + container_of(ptr, typeof(*acl), head); 453 + 454 + return (acl->perm & (1 << r->param.unix_network.operation)) && 455 + tomoyo_compare_name_union(r->param.unix_network.address, 456 + &acl->name); 457 + } 458 + 459 + /** 460 + * tomoyo_inet_entry - Check permission for INET network operation. 461 + * 462 + * @address: Pointer to "struct tomoyo_addr_info". 463 + * 464 + * Returns 0 on success, negative value otherwise. 465 + */ 466 + static int tomoyo_inet_entry(const struct tomoyo_addr_info *address) 467 + { 468 + const int idx = tomoyo_read_lock(); 469 + struct tomoyo_request_info r; 470 + int error = 0; 471 + const u8 type = tomoyo_inet2mac[address->protocol][address->operation]; 472 + 473 + if (type && tomoyo_init_request_info(&r, NULL, type) 474 + != TOMOYO_CONFIG_DISABLED) { 475 + r.param_type = TOMOYO_TYPE_INET_ACL; 476 + r.param.inet_network.protocol = address->protocol; 477 + r.param.inet_network.operation = address->operation; 478 + r.param.inet_network.is_ipv6 = address->inet.is_ipv6; 479 + r.param.inet_network.address = address->inet.address; 480 + r.param.inet_network.port = ntohs(address->inet.port); 481 + do { 482 + tomoyo_check_acl(&r, tomoyo_check_inet_acl); 483 + error = tomoyo_audit_inet_log(&r); 484 + } while (error == TOMOYO_RETRY_REQUEST); 485 + } 486 + tomoyo_read_unlock(idx); 487 + return error; 488 + } 489 + 490 + /** 491 + * tomoyo_check_inet_address - Check permission for inet domain socket's operation. 492 + * 493 + * @addr: Pointer to "struct sockaddr". 494 + * @addr_len: Size of @addr. 495 + * @port: Port number. 496 + * @address: Pointer to "struct tomoyo_addr_info". 497 + * 498 + * Returns 0 on success, negative value otherwise. 499 + */ 500 + static int tomoyo_check_inet_address(const struct sockaddr *addr, 501 + const unsigned int addr_len, 502 + const u16 port, 503 + struct tomoyo_addr_info *address) 504 + { 505 + struct tomoyo_inet_addr_info *i = &address->inet; 506 + 507 + switch (addr->sa_family) { 508 + case AF_INET6: 509 + if (addr_len < SIN6_LEN_RFC2133) 510 + goto skip; 511 + i->is_ipv6 = true; 512 + i->address = (__be32 *) 513 + ((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr; 514 + i->port = ((struct sockaddr_in6 *) addr)->sin6_port; 515 + break; 516 + case AF_INET: 517 + if (addr_len < sizeof(struct sockaddr_in)) 518 + goto skip; 519 + i->is_ipv6 = false; 520 + i->address = (__be32 *) 521 + &((struct sockaddr_in *) addr)->sin_addr; 522 + i->port = ((struct sockaddr_in *) addr)->sin_port; 523 + break; 524 + default: 525 + goto skip; 526 + } 527 + if (address->protocol == SOCK_RAW) 528 + i->port = htons(port); 529 + return tomoyo_inet_entry(address); 530 + skip: 531 + return 0; 532 + } 533 + 534 + /** 535 + * tomoyo_unix_entry - Check permission for UNIX network operation. 536 + * 537 + * @address: Pointer to "struct tomoyo_addr_info". 538 + * 539 + * Returns 0 on success, negative value otherwise. 540 + */ 541 + static int tomoyo_unix_entry(const struct tomoyo_addr_info *address) 542 + { 543 + const int idx = tomoyo_read_lock(); 544 + struct tomoyo_request_info r; 545 + int error = 0; 546 + const u8 type = tomoyo_unix2mac[address->protocol][address->operation]; 547 + 548 + if (type && tomoyo_init_request_info(&r, NULL, type) 549 + != TOMOYO_CONFIG_DISABLED) { 550 + char *buf = address->unix0.addr; 551 + int len = address->unix0.addr_len - sizeof(sa_family_t); 552 + 553 + if (len <= 0) { 554 + buf = "anonymous"; 555 + len = 9; 556 + } else if (buf[0]) { 557 + len = strnlen(buf, len); 558 + } 559 + buf = tomoyo_encode2(buf, len); 560 + if (buf) { 561 + struct tomoyo_path_info addr; 562 + 563 + addr.name = buf; 564 + tomoyo_fill_path_info(&addr); 565 + r.param_type = TOMOYO_TYPE_UNIX_ACL; 566 + r.param.unix_network.protocol = address->protocol; 567 + r.param.unix_network.operation = address->operation; 568 + r.param.unix_network.address = &addr; 569 + do { 570 + tomoyo_check_acl(&r, tomoyo_check_unix_acl); 571 + error = tomoyo_audit_unix_log(&r); 572 + } while (error == TOMOYO_RETRY_REQUEST); 573 + kfree(buf); 574 + } else 575 + error = -ENOMEM; 576 + } 577 + tomoyo_read_unlock(idx); 578 + return error; 579 + } 580 + 581 + /** 582 + * tomoyo_check_unix_address - Check permission for unix domain socket's operation. 583 + * 584 + * @addr: Pointer to "struct sockaddr". 585 + * @addr_len: Size of @addr. 586 + * @address: Pointer to "struct tomoyo_addr_info". 587 + * 588 + * Returns 0 on success, negative value otherwise. 589 + */ 590 + static int tomoyo_check_unix_address(struct sockaddr *addr, 591 + const unsigned int addr_len, 592 + struct tomoyo_addr_info *address) 593 + { 594 + struct tomoyo_unix_addr_info *u = &address->unix0; 595 + 596 + if (addr->sa_family != AF_UNIX) 597 + return 0; 598 + u->addr = ((struct sockaddr_un *) addr)->sun_path; 599 + u->addr_len = addr_len; 600 + return tomoyo_unix_entry(address); 601 + } 602 + 603 + /** 604 + * tomoyo_kernel_service - Check whether I'm kernel service or not. 605 + * 606 + * Returns true if I'm kernel service, false otherwise. 607 + */ 608 + static bool tomoyo_kernel_service(void) 609 + { 610 + /* Nothing to do if I am a kernel service. */ 611 + return segment_eq(get_fs(), KERNEL_DS); 612 + } 613 + 614 + /** 615 + * tomoyo_sock_family - Get socket's family. 616 + * 617 + * @sk: Pointer to "struct sock". 618 + * 619 + * Returns one of PF_INET, PF_INET6, PF_UNIX or 0. 620 + */ 621 + static u8 tomoyo_sock_family(struct sock *sk) 622 + { 623 + u8 family; 624 + 625 + if (tomoyo_kernel_service()) 626 + return 0; 627 + family = sk->sk_family; 628 + switch (family) { 629 + case PF_INET: 630 + case PF_INET6: 631 + case PF_UNIX: 632 + return family; 633 + default: 634 + return 0; 635 + } 636 + } 637 + 638 + /** 639 + * tomoyo_socket_listen_permission - Check permission for listening a socket. 640 + * 641 + * @sock: Pointer to "struct socket". 642 + * 643 + * Returns 0 on success, negative value otherwise. 644 + */ 645 + int tomoyo_socket_listen_permission(struct socket *sock) 646 + { 647 + struct tomoyo_addr_info address; 648 + const u8 family = tomoyo_sock_family(sock->sk); 649 + const unsigned int type = sock->type; 650 + struct sockaddr_storage addr; 651 + int addr_len; 652 + 653 + if (!family || (type != SOCK_STREAM && type != SOCK_SEQPACKET)) 654 + return 0; 655 + { 656 + const int error = sock->ops->getname(sock, (struct sockaddr *) 657 + &addr, &addr_len, 0); 658 + 659 + if (error) 660 + return error; 661 + } 662 + address.protocol = type; 663 + address.operation = TOMOYO_NETWORK_LISTEN; 664 + if (family == PF_UNIX) 665 + return tomoyo_check_unix_address((struct sockaddr *) &addr, 666 + addr_len, &address); 667 + return tomoyo_check_inet_address((struct sockaddr *) &addr, addr_len, 668 + 0, &address); 669 + } 670 + 671 + /** 672 + * tomoyo_socket_connect_permission - Check permission for setting the remote address of a socket. 673 + * 674 + * @sock: Pointer to "struct socket". 675 + * @addr: Pointer to "struct sockaddr". 676 + * @addr_len: Size of @addr. 677 + * 678 + * Returns 0 on success, negative value otherwise. 679 + */ 680 + int tomoyo_socket_connect_permission(struct socket *sock, 681 + struct sockaddr *addr, int addr_len) 682 + { 683 + struct tomoyo_addr_info address; 684 + const u8 family = tomoyo_sock_family(sock->sk); 685 + const unsigned int type = sock->type; 686 + 687 + if (!family) 688 + return 0; 689 + address.protocol = type; 690 + switch (type) { 691 + case SOCK_DGRAM: 692 + case SOCK_RAW: 693 + address.operation = TOMOYO_NETWORK_SEND; 694 + break; 695 + case SOCK_STREAM: 696 + case SOCK_SEQPACKET: 697 + address.operation = TOMOYO_NETWORK_CONNECT; 698 + break; 699 + default: 700 + return 0; 701 + } 702 + if (family == PF_UNIX) 703 + return tomoyo_check_unix_address(addr, addr_len, &address); 704 + return tomoyo_check_inet_address(addr, addr_len, sock->sk->sk_protocol, 705 + &address); 706 + } 707 + 708 + /** 709 + * tomoyo_socket_bind_permission - Check permission for setting the local address of a socket. 710 + * 711 + * @sock: Pointer to "struct socket". 712 + * @addr: Pointer to "struct sockaddr". 713 + * @addr_len: Size of @addr. 714 + * 715 + * Returns 0 on success, negative value otherwise. 716 + */ 717 + int tomoyo_socket_bind_permission(struct socket *sock, struct sockaddr *addr, 718 + int addr_len) 719 + { 720 + struct tomoyo_addr_info address; 721 + const u8 family = tomoyo_sock_family(sock->sk); 722 + const unsigned int type = sock->type; 723 + 724 + if (!family) 725 + return 0; 726 + switch (type) { 727 + case SOCK_STREAM: 728 + case SOCK_DGRAM: 729 + case SOCK_RAW: 730 + case SOCK_SEQPACKET: 731 + address.protocol = type; 732 + address.operation = TOMOYO_NETWORK_BIND; 733 + break; 734 + default: 735 + return 0; 736 + } 737 + if (family == PF_UNIX) 738 + return tomoyo_check_unix_address(addr, addr_len, &address); 739 + return tomoyo_check_inet_address(addr, addr_len, sock->sk->sk_protocol, 740 + &address); 741 + } 742 + 743 + /** 744 + * tomoyo_socket_sendmsg_permission - Check permission for sending a datagram. 745 + * 746 + * @sock: Pointer to "struct socket". 747 + * @msg: Pointer to "struct msghdr". 748 + * @size: Unused. 749 + * 750 + * Returns 0 on success, negative value otherwise. 751 + */ 752 + int tomoyo_socket_sendmsg_permission(struct socket *sock, struct msghdr *msg, 753 + int size) 754 + { 755 + struct tomoyo_addr_info address; 756 + const u8 family = tomoyo_sock_family(sock->sk); 757 + const unsigned int type = sock->type; 758 + 759 + if (!msg->msg_name || !family || 760 + (type != SOCK_DGRAM && type != SOCK_RAW)) 761 + return 0; 762 + address.protocol = type; 763 + address.operation = TOMOYO_NETWORK_SEND; 764 + if (family == PF_UNIX) 765 + return tomoyo_check_unix_address((struct sockaddr *) 766 + msg->msg_name, 767 + msg->msg_namelen, &address); 768 + return tomoyo_check_inet_address((struct sockaddr *) msg->msg_name, 769 + msg->msg_namelen, 770 + sock->sk->sk_protocol, &address); 771 + }
+25 -7
security/tomoyo/realpath.c
··· 15 15 #include "../../fs/internal.h" 16 16 17 17 /** 18 - * tomoyo_encode: Convert binary string to ascii string. 18 + * tomoyo_encode2 - Encode binary string to ascii string. 19 19 * 20 - * @str: String in binary format. 20 + * @str: String in binary format. 21 + * @str_len: Size of @str in byte. 21 22 * 22 23 * Returns pointer to @str in ascii format on success, NULL otherwise. 23 24 * 24 25 * This function uses kzalloc(), so caller must kfree() if this function 25 26 * didn't return NULL. 26 27 */ 27 - char *tomoyo_encode(const char *str) 28 + char *tomoyo_encode2(const char *str, int str_len) 28 29 { 30 + int i; 29 31 int len = 0; 30 32 const char *p = str; 31 33 char *cp; ··· 35 33 36 34 if (!p) 37 35 return NULL; 38 - while (*p) { 39 - const unsigned char c = *p++; 36 + for (i = 0; i < str_len; i++) { 37 + const unsigned char c = p[i]; 38 + 40 39 if (c == '\\') 41 40 len += 2; 42 41 else if (c > ' ' && c < 127) ··· 52 49 return NULL; 53 50 cp0 = cp; 54 51 p = str; 55 - while (*p) { 56 - const unsigned char c = *p++; 52 + for (i = 0; i < str_len; i++) { 53 + const unsigned char c = p[i]; 57 54 58 55 if (c == '\\') { 59 56 *cp++ = '\\'; ··· 68 65 } 69 66 } 70 67 return cp0; 68 + } 69 + 70 + /** 71 + * tomoyo_encode - Encode binary string to ascii string. 72 + * 73 + * @str: String in binary format. 74 + * 75 + * Returns pointer to @str in ascii format on success, NULL otherwise. 76 + * 77 + * This function uses kzalloc(), so caller must kfree() if this function 78 + * didn't return NULL. 79 + */ 80 + char *tomoyo_encode(const char *str) 81 + { 82 + return str ? tomoyo_encode2(str, strlen(str)) : NULL; 71 83 } 72 84 73 85 /**
+62
security/tomoyo/tomoyo.c
··· 442 442 return tomoyo_path2_perm(TOMOYO_TYPE_PIVOT_ROOT, new_path, old_path); 443 443 } 444 444 445 + /** 446 + * tomoyo_socket_listen - Check permission for listen(). 447 + * 448 + * @sock: Pointer to "struct socket". 449 + * @backlog: Backlog parameter. 450 + * 451 + * Returns 0 on success, negative value otherwise. 452 + */ 453 + static int tomoyo_socket_listen(struct socket *sock, int backlog) 454 + { 455 + return tomoyo_socket_listen_permission(sock); 456 + } 457 + 458 + /** 459 + * tomoyo_socket_connect - Check permission for connect(). 460 + * 461 + * @sock: Pointer to "struct socket". 462 + * @addr: Pointer to "struct sockaddr". 463 + * @addr_len: Size of @addr. 464 + * 465 + * Returns 0 on success, negative value otherwise. 466 + */ 467 + static int tomoyo_socket_connect(struct socket *sock, struct sockaddr *addr, 468 + int addr_len) 469 + { 470 + return tomoyo_socket_connect_permission(sock, addr, addr_len); 471 + } 472 + 473 + /** 474 + * tomoyo_socket_bind - Check permission for bind(). 475 + * 476 + * @sock: Pointer to "struct socket". 477 + * @addr: Pointer to "struct sockaddr". 478 + * @addr_len: Size of @addr. 479 + * 480 + * Returns 0 on success, negative value otherwise. 481 + */ 482 + static int tomoyo_socket_bind(struct socket *sock, struct sockaddr *addr, 483 + int addr_len) 484 + { 485 + return tomoyo_socket_bind_permission(sock, addr, addr_len); 486 + } 487 + 488 + /** 489 + * tomoyo_socket_sendmsg - Check permission for sendmsg(). 490 + * 491 + * @sock: Pointer to "struct socket". 492 + * @msg: Pointer to "struct msghdr". 493 + * @size: Size of message. 494 + * 495 + * Returns 0 on success, negative value otherwise. 496 + */ 497 + static int tomoyo_socket_sendmsg(struct socket *sock, struct msghdr *msg, 498 + int size) 499 + { 500 + return tomoyo_socket_sendmsg_permission(sock, msg, size); 501 + } 502 + 445 503 /* 446 504 * tomoyo_security_ops is a "struct security_operations" which is used for 447 505 * registering TOMOYO. ··· 530 472 .sb_mount = tomoyo_sb_mount, 531 473 .sb_umount = tomoyo_sb_umount, 532 474 .sb_pivotroot = tomoyo_sb_pivotroot, 475 + .socket_bind = tomoyo_socket_bind, 476 + .socket_connect = tomoyo_socket_connect, 477 + .socket_listen = tomoyo_socket_listen, 478 + .socket_sendmsg = tomoyo_socket_sendmsg, 533 479 }; 534 480 535 481 /* Lock for GC. */
+31
security/tomoyo/util.c
··· 42 42 [TOMOYO_MAC_FILE_MOUNT] = TOMOYO_MAC_CATEGORY_FILE, 43 43 [TOMOYO_MAC_FILE_UMOUNT] = TOMOYO_MAC_CATEGORY_FILE, 44 44 [TOMOYO_MAC_FILE_PIVOT_ROOT] = TOMOYO_MAC_CATEGORY_FILE, 45 + /* CONFIG::network group */ 46 + [TOMOYO_MAC_NETWORK_INET_STREAM_BIND] = 47 + TOMOYO_MAC_CATEGORY_NETWORK, 48 + [TOMOYO_MAC_NETWORK_INET_STREAM_LISTEN] = 49 + TOMOYO_MAC_CATEGORY_NETWORK, 50 + [TOMOYO_MAC_NETWORK_INET_STREAM_CONNECT] = 51 + TOMOYO_MAC_CATEGORY_NETWORK, 52 + [TOMOYO_MAC_NETWORK_INET_DGRAM_BIND] = 53 + TOMOYO_MAC_CATEGORY_NETWORK, 54 + [TOMOYO_MAC_NETWORK_INET_DGRAM_SEND] = 55 + TOMOYO_MAC_CATEGORY_NETWORK, 56 + [TOMOYO_MAC_NETWORK_INET_RAW_BIND] = 57 + TOMOYO_MAC_CATEGORY_NETWORK, 58 + [TOMOYO_MAC_NETWORK_INET_RAW_SEND] = 59 + TOMOYO_MAC_CATEGORY_NETWORK, 60 + [TOMOYO_MAC_NETWORK_UNIX_STREAM_BIND] = 61 + TOMOYO_MAC_CATEGORY_NETWORK, 62 + [TOMOYO_MAC_NETWORK_UNIX_STREAM_LISTEN] = 63 + TOMOYO_MAC_CATEGORY_NETWORK, 64 + [TOMOYO_MAC_NETWORK_UNIX_STREAM_CONNECT] = 65 + TOMOYO_MAC_CATEGORY_NETWORK, 66 + [TOMOYO_MAC_NETWORK_UNIX_DGRAM_BIND] = 67 + TOMOYO_MAC_CATEGORY_NETWORK, 68 + [TOMOYO_MAC_NETWORK_UNIX_DGRAM_SEND] = 69 + TOMOYO_MAC_CATEGORY_NETWORK, 70 + [TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_BIND] = 71 + TOMOYO_MAC_CATEGORY_NETWORK, 72 + [TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_LISTEN] = 73 + TOMOYO_MAC_CATEGORY_NETWORK, 74 + [TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_CONNECT] = 75 + TOMOYO_MAC_CATEGORY_NETWORK, 45 76 /* CONFIG::misc group */ 46 77 [TOMOYO_MAC_ENVIRON] = TOMOYO_MAC_CATEGORY_MISC, 47 78 };