1
2
3
4
5
6
7#include <linux/slab.h>
8#include "common.h"
9
10static bool tomoyo_same_path_group(const struct tomoyo_acl_head *a,
11 const struct tomoyo_acl_head *b)
12{
13 return container_of(a, struct tomoyo_path_group, head)->member_name ==
14 container_of(b, struct tomoyo_path_group, head)->member_name;
15}
16
17static bool tomoyo_same_number_group(const struct tomoyo_acl_head *a,
18 const struct tomoyo_acl_head *b)
19{
20 return !memcmp(&container_of(a, struct tomoyo_number_group, head)
21 ->number,
22 &container_of(b, struct tomoyo_number_group, head)
23 ->number,
24 sizeof(container_of(a, struct tomoyo_number_group, head)
25 ->number));
26}
27
28
29
30
31
32
33
34
35
36
37int tomoyo_write_group(char *data, const bool is_delete, const u8 type)
38{
39 struct tomoyo_group *group;
40 struct list_head *member;
41 char *w[2];
42 int error = -EINVAL;
43 if (!tomoyo_tokenize(data, w, sizeof(w)) || !w[1][0])
44 return -EINVAL;
45 group = tomoyo_get_group(w[0], type);
46 if (!group)
47 return -ENOMEM;
48 member = &group->member_list;
49 if (type == TOMOYO_PATH_GROUP) {
50 struct tomoyo_path_group e = { };
51 e.member_name = tomoyo_get_name(w[1]);
52 if (!e.member_name) {
53 error = -ENOMEM;
54 goto out;
55 }
56 error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
57 member, tomoyo_same_path_group);
58 tomoyo_put_name(e.member_name);
59 } else if (type == TOMOYO_NUMBER_GROUP) {
60 struct tomoyo_number_group e = { };
61 if (w[1][0] == '@'
62 || !tomoyo_parse_number_union(w[1], &e.number)
63 || e.number.values[0] > e.number.values[1])
64 goto out;
65 error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
66 member, tomoyo_same_number_group);
67
68
69
70
71 }
72 out:
73 tomoyo_put_group(group);
74 return error;
75}
76
77
78
79
80
81
82
83
84
85
86
87
88const struct tomoyo_path_info *
89tomoyo_path_matches_group(const struct tomoyo_path_info *pathname,
90 const struct tomoyo_group *group)
91{
92 struct tomoyo_path_group *member;
93 list_for_each_entry_rcu(member, &group->member_list, head.list) {
94 if (member->head.is_deleted)
95 continue;
96 if (!tomoyo_path_matches_pattern(pathname, member->member_name))
97 continue;
98 return member->member_name;
99 }
100 return NULL;
101}
102
103
104
105
106
107
108
109
110
111
112
113
114bool tomoyo_number_matches_group(const unsigned long min,
115 const unsigned long max,
116 const struct tomoyo_group *group)
117{
118 struct tomoyo_number_group *member;
119 bool matched = false;
120 list_for_each_entry_rcu(member, &group->member_list, head.list) {
121 if (member->head.is_deleted)
122 continue;
123 if (min > member->number.values[1] ||
124 max < member->number.values[0])
125 continue;
126 matched = true;
127 break;
128 }
129 return matched;
130}
131