1 /* 2 * security/tomoyo/group.c 3 * 4 * Copyright (C) 2005-2011 NTT DATA CORPORATION 5 */ 6 7 #include <linux/slab.h> 8 #include <linux/rculist.h> 9 10 #include "common.h" 11 12 /** 13 * tomoyo_same_path_group - Check for duplicated "struct tomoyo_path_group" entry. 14 * 15 * @a: Pointer to "struct tomoyo_acl_head". 16 * @b: Pointer to "struct tomoyo_acl_head". 17 * 18 * Returns true if @a == @b, false otherwise. 19 */ 20 static bool tomoyo_same_path_group(const struct tomoyo_acl_head *a, 21 const struct tomoyo_acl_head *b) 22 { 23 return container_of(a, struct tomoyo_path_group, head)->member_name == 24 container_of(b, struct tomoyo_path_group, head)->member_name; 25 } 26 27 /** 28 * tomoyo_same_number_group - Check for duplicated "struct tomoyo_number_group" entry. 29 * 30 * @a: Pointer to "struct tomoyo_acl_head". 31 * @b: Pointer to "struct tomoyo_acl_head". 32 * 33 * Returns true if @a == @b, false otherwise. 34 */ 35 static bool tomoyo_same_number_group(const struct tomoyo_acl_head *a, 36 const struct tomoyo_acl_head *b) 37 { 38 return !memcmp(&container_of(a, struct tomoyo_number_group, head) 39 ->number, 40 &container_of(b, struct tomoyo_number_group, head) 41 ->number, 42 sizeof(container_of(a, struct tomoyo_number_group, head) 43 ->number)); 44 } 45 46 /** 47 * tomoyo_same_address_group - Check for duplicated "struct tomoyo_address_group" entry. 48 * 49 * @a: Pointer to "struct tomoyo_acl_head". 50 * @b: Pointer to "struct tomoyo_acl_head". 51 * 52 * Returns true if @a == @b, false otherwise. 53 */ 54 static bool tomoyo_same_address_group(const struct tomoyo_acl_head *a, 55 const struct tomoyo_acl_head *b) 56 { 57 const struct tomoyo_address_group *p1 = container_of(a, typeof(*p1), 58 head); 59 const struct tomoyo_address_group *p2 = container_of(b, typeof(*p2), 60 head); 61 62 return tomoyo_same_ipaddr_union(&p1->address, &p2->address); 63 } 64 65 /** 66 * tomoyo_write_group - Write "struct tomoyo_path_group"/"struct tomoyo_number_group"/"struct tomoyo_address_group" list. 67 * 68 * @param: Pointer to "struct tomoyo_acl_param". 69 * @type: Type of this group. 70 * 71 * Returns 0 on success, negative value otherwise. 72 */ 73 int tomoyo_write_group(struct tomoyo_acl_param *param, const u8 type) 74 { 75 struct tomoyo_group *group = tomoyo_get_group(param, type); 76 int error = -EINVAL; 77 if (!group) 78 return -ENOMEM; 79 param->list = &group->member_list; 80 if (type == TOMOYO_PATH_GROUP) { 81 struct tomoyo_path_group e = { }; 82 e.member_name = tomoyo_get_name(tomoyo_read_token(param)); 83 if (!e.member_name) { 84 error = -ENOMEM; 85 goto out; 86 } 87 error = tomoyo_update_policy(&e.head, sizeof(e), param, 88 tomoyo_same_path_group); 89 tomoyo_put_name(e.member_name); 90 } else if (type == TOMOYO_NUMBER_GROUP) { 91 struct tomoyo_number_group e = { }; 92 if (param->data[0] == '@' || 93 !tomoyo_parse_number_union(param, &e.number)) 94 goto out; 95 error = tomoyo_update_policy(&e.head, sizeof(e), param, 96 tomoyo_same_number_group); 97 /* 98 * tomoyo_put_number_union() is not needed because 99 * param->data[0] != '@'. 100 */ 101 } else { 102 struct tomoyo_address_group e = { }; 103 104 if (param->data[0] == '@' || 105 !tomoyo_parse_ipaddr_union(param, &e.address)) 106 goto out; 107 error = tomoyo_update_policy(&e.head, sizeof(e), param, 108 tomoyo_same_address_group); 109 } 110 out: 111 tomoyo_put_group(group); 112 return error; 113 } 114 115 /** 116 * tomoyo_path_matches_group - Check whether the given pathname matches members of the given pathname group. 117 * 118 * @pathname: The name of pathname. 119 * @group: Pointer to "struct tomoyo_path_group". 120 * 121 * Returns matched member's pathname if @pathname matches pathnames in @group, 122 * NULL otherwise. 123 * 124 * Caller holds tomoyo_read_lock(). 125 */ 126 const struct tomoyo_path_info * 127 tomoyo_path_matches_group(const struct tomoyo_path_info *pathname, 128 const struct tomoyo_group *group) 129 { 130 struct tomoyo_path_group *member; 131 list_for_each_entry_rcu(member, &group->member_list, head.list) { 132 if (member->head.is_deleted) 133 continue; 134 if (!tomoyo_path_matches_pattern(pathname, member->member_name)) 135 continue; 136 return member->member_name; 137 } 138 return NULL; 139 } 140 141 /** 142 * tomoyo_number_matches_group - Check whether the given number matches members of the given number group. 143 * 144 * @min: Min number. 145 * @max: Max number. 146 * @group: Pointer to "struct tomoyo_number_group". 147 * 148 * Returns true if @min and @max partially overlaps @group, false otherwise. 149 * 150 * Caller holds tomoyo_read_lock(). 151 */ 152 bool tomoyo_number_matches_group(const unsigned long min, 153 const unsigned long max, 154 const struct tomoyo_group *group) 155 { 156 struct tomoyo_number_group *member; 157 bool matched = false; 158 list_for_each_entry_rcu(member, &group->member_list, head.list) { 159 if (member->head.is_deleted) 160 continue; 161 if (min > member->number.values[1] || 162 max < member->number.values[0]) 163 continue; 164 matched = true; 165 break; 166 } 167 return matched; 168 } 169 170 /** 171 * tomoyo_address_matches_group - Check whether the given address matches members of the given address group. 172 * 173 * @is_ipv6: True if @address is an IPv6 address. 174 * @address: An IPv4 or IPv6 address. 175 * @group: Pointer to "struct tomoyo_address_group". 176 * 177 * Returns true if @address matches addresses in @group group, false otherwise. 178 * 179 * Caller holds tomoyo_read_lock(). 180 */ 181 bool tomoyo_address_matches_group(const bool is_ipv6, const __be32 *address, 182 const struct tomoyo_group *group) 183 { 184 struct tomoyo_address_group *member; 185 bool matched = false; 186 const u8 size = is_ipv6 ? 16 : 4; 187 188 list_for_each_entry_rcu(member, &group->member_list, head.list) { 189 if (member->head.is_deleted) 190 continue; 191 if (member->address.is_ipv6 != is_ipv6) 192 continue; 193 if (memcmp(&member->address.ip[0], address, size) > 0 || 194 memcmp(address, &member->address.ip[1], size) > 0) 195 continue; 196 matched = true; 197 break; 198 } 199 return matched; 200 } 201