0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/slab.h>
0009 #include <linux/rculist.h>
0010
0011 #include "common.h"
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021 static bool tomoyo_same_path_group(const struct tomoyo_acl_head *a,
0022 const struct tomoyo_acl_head *b)
0023 {
0024 return container_of(a, struct tomoyo_path_group, head)->member_name ==
0025 container_of(b, struct tomoyo_path_group, head)->member_name;
0026 }
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036 static bool tomoyo_same_number_group(const struct tomoyo_acl_head *a,
0037 const struct tomoyo_acl_head *b)
0038 {
0039 return !memcmp(&container_of(a, struct tomoyo_number_group, head)
0040 ->number,
0041 &container_of(b, struct tomoyo_number_group, head)
0042 ->number,
0043 sizeof(container_of(a, struct tomoyo_number_group, head)
0044 ->number));
0045 }
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055 static bool tomoyo_same_address_group(const struct tomoyo_acl_head *a,
0056 const struct tomoyo_acl_head *b)
0057 {
0058 const struct tomoyo_address_group *p1 = container_of(a, typeof(*p1),
0059 head);
0060 const struct tomoyo_address_group *p2 = container_of(b, typeof(*p2),
0061 head);
0062
0063 return tomoyo_same_ipaddr_union(&p1->address, &p2->address);
0064 }
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074 int tomoyo_write_group(struct tomoyo_acl_param *param, const u8 type)
0075 {
0076 struct tomoyo_group *group = tomoyo_get_group(param, type);
0077 int error = -EINVAL;
0078
0079 if (!group)
0080 return -ENOMEM;
0081 param->list = &group->member_list;
0082 if (type == TOMOYO_PATH_GROUP) {
0083 struct tomoyo_path_group e = { };
0084
0085 e.member_name = tomoyo_get_name(tomoyo_read_token(param));
0086 if (!e.member_name) {
0087 error = -ENOMEM;
0088 goto out;
0089 }
0090 error = tomoyo_update_policy(&e.head, sizeof(e), param,
0091 tomoyo_same_path_group);
0092 tomoyo_put_name(e.member_name);
0093 } else if (type == TOMOYO_NUMBER_GROUP) {
0094 struct tomoyo_number_group e = { };
0095
0096 if (param->data[0] == '@' ||
0097 !tomoyo_parse_number_union(param, &e.number))
0098 goto out;
0099 error = tomoyo_update_policy(&e.head, sizeof(e), param,
0100 tomoyo_same_number_group);
0101
0102
0103
0104
0105 } else {
0106 struct tomoyo_address_group e = { };
0107
0108 if (param->data[0] == '@' ||
0109 !tomoyo_parse_ipaddr_union(param, &e.address))
0110 goto out;
0111 error = tomoyo_update_policy(&e.head, sizeof(e), param,
0112 tomoyo_same_address_group);
0113 }
0114 out:
0115 tomoyo_put_group(group);
0116 return error;
0117 }
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130 const struct tomoyo_path_info *
0131 tomoyo_path_matches_group(const struct tomoyo_path_info *pathname,
0132 const struct tomoyo_group *group)
0133 {
0134 struct tomoyo_path_group *member;
0135
0136 list_for_each_entry_rcu(member, &group->member_list, head.list,
0137 srcu_read_lock_held(&tomoyo_ss)) {
0138 if (member->head.is_deleted)
0139 continue;
0140 if (!tomoyo_path_matches_pattern(pathname, member->member_name))
0141 continue;
0142 return member->member_name;
0143 }
0144 return NULL;
0145 }
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158 bool tomoyo_number_matches_group(const unsigned long min,
0159 const unsigned long max,
0160 const struct tomoyo_group *group)
0161 {
0162 struct tomoyo_number_group *member;
0163 bool matched = false;
0164
0165 list_for_each_entry_rcu(member, &group->member_list, head.list,
0166 srcu_read_lock_held(&tomoyo_ss)) {
0167 if (member->head.is_deleted)
0168 continue;
0169 if (min > member->number.values[1] ||
0170 max < member->number.values[0])
0171 continue;
0172 matched = true;
0173 break;
0174 }
0175 return matched;
0176 }
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189 bool tomoyo_address_matches_group(const bool is_ipv6, const __be32 *address,
0190 const struct tomoyo_group *group)
0191 {
0192 struct tomoyo_address_group *member;
0193 bool matched = false;
0194 const u8 size = is_ipv6 ? 16 : 4;
0195
0196 list_for_each_entry_rcu(member, &group->member_list, head.list,
0197 srcu_read_lock_held(&tomoyo_ss)) {
0198 if (member->head.is_deleted)
0199 continue;
0200 if (member->address.is_ipv6 != is_ipv6)
0201 continue;
0202 if (memcmp(&member->address.ip[0], address, size) > 0 ||
0203 memcmp(address, &member->address.ip[1], size) > 0)
0204 continue;
0205 matched = true;
0206 break;
0207 }
0208 return matched;
0209 }