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