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