aboutsummaryrefslogtreecommitdiffstats
path: root/security/tomoyo/domain.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/tomoyo/domain.c')
-rw-r--r--security/tomoyo/domain.c146
1 files changed, 61 insertions, 85 deletions
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c
index 43977083254b..d818717954f8 100644
--- a/security/tomoyo/domain.c
+++ b/security/tomoyo/domain.c
@@ -20,8 +20,7 @@ struct tomoyo_domain_info tomoyo_kernel_domain;
20 * 20 *
21 * @new_entry: Pointer to "struct tomoyo_acl_info". 21 * @new_entry: Pointer to "struct tomoyo_acl_info".
22 * @size: Size of @new_entry in bytes. 22 * @size: Size of @new_entry in bytes.
23 * @is_delete: True if it is a delete request. 23 * @param: Pointer to "struct tomoyo_acl_param".
24 * @list: Pointer to "struct list_head".
25 * @check_duplicate: Callback function to find duplicated entry. 24 * @check_duplicate: Callback function to find duplicated entry.
26 * 25 *
27 * Returns 0 on success, negative value otherwise. 26 * Returns 0 on success, negative value otherwise.
@@ -29,25 +28,26 @@ struct tomoyo_domain_info tomoyo_kernel_domain;
29 * Caller holds tomoyo_read_lock(). 28 * Caller holds tomoyo_read_lock().
30 */ 29 */
31int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size, 30int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size,
32 bool is_delete, struct list_head *list, 31 struct tomoyo_acl_param *param,
33 bool (*check_duplicate) (const struct tomoyo_acl_head 32 bool (*check_duplicate) (const struct tomoyo_acl_head
34 *, 33 *,
35 const struct tomoyo_acl_head 34 const struct tomoyo_acl_head
36 *)) 35 *))
37{ 36{
38 int error = is_delete ? -ENOENT : -ENOMEM; 37 int error = param->is_delete ? -ENOENT : -ENOMEM;
39 struct tomoyo_acl_head *entry; 38 struct tomoyo_acl_head *entry;
39 struct list_head *list = param->list;
40 40
41 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 41 if (mutex_lock_interruptible(&tomoyo_policy_lock))
42 return -ENOMEM; 42 return -ENOMEM;
43 list_for_each_entry_rcu(entry, list, list) { 43 list_for_each_entry_rcu(entry, list, list) {
44 if (!check_duplicate(entry, new_entry)) 44 if (!check_duplicate(entry, new_entry))
45 continue; 45 continue;
46 entry->is_deleted = is_delete; 46 entry->is_deleted = param->is_delete;
47 error = 0; 47 error = 0;
48 break; 48 break;
49 } 49 }
50 if (error && !is_delete) { 50 if (error && !param->is_delete) {
51 entry = tomoyo_commit_ok(new_entry, size); 51 entry = tomoyo_commit_ok(new_entry, size);
52 if (entry) { 52 if (entry) {
53 list_add_tail_rcu(&entry->list, list); 53 list_add_tail_rcu(&entry->list, list);
@@ -77,8 +77,7 @@ static inline bool tomoyo_same_acl_head(const struct tomoyo_acl_info *a,
77 * 77 *
78 * @new_entry: Pointer to "struct tomoyo_acl_info". 78 * @new_entry: Pointer to "struct tomoyo_acl_info".
79 * @size: Size of @new_entry in bytes. 79 * @size: Size of @new_entry in bytes.
80 * @is_delete: True if it is a delete request. 80 * @param: Pointer to "struct tomoyo_acl_param".
81 * @domain: Pointer to "struct tomoyo_domain_info".
82 * @check_duplicate: Callback function to find duplicated entry. 81 * @check_duplicate: Callback function to find duplicated entry.
83 * @merge_duplicate: Callback function to merge duplicated entry. 82 * @merge_duplicate: Callback function to merge duplicated entry.
84 * 83 *
@@ -87,7 +86,7 @@ static inline bool tomoyo_same_acl_head(const struct tomoyo_acl_info *a,
87 * Caller holds tomoyo_read_lock(). 86 * Caller holds tomoyo_read_lock().
88 */ 87 */
89int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size, 88int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size,
90 bool is_delete, struct tomoyo_domain_info *domain, 89 struct tomoyo_acl_param *param,
91 bool (*check_duplicate) (const struct tomoyo_acl_info 90 bool (*check_duplicate) (const struct tomoyo_acl_info
92 *, 91 *,
93 const struct tomoyo_acl_info 92 const struct tomoyo_acl_info
@@ -96,12 +95,14 @@ int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size,
96 struct tomoyo_acl_info *, 95 struct tomoyo_acl_info *,
97 const bool)) 96 const bool))
98{ 97{
98 const bool is_delete = param->is_delete;
99 int error = is_delete ? -ENOENT : -ENOMEM; 99 int error = is_delete ? -ENOENT : -ENOMEM;
100 struct tomoyo_acl_info *entry; 100 struct tomoyo_acl_info *entry;
101 struct list_head * const list = param->list;
101 102
102 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 103 if (mutex_lock_interruptible(&tomoyo_policy_lock))
103 return error; 104 return error;
104 list_for_each_entry_rcu(entry, &domain->acl_info_list, list) { 105 list_for_each_entry_rcu(entry, list, list) {
105 if (!tomoyo_same_acl_head(entry, new_entry) || 106 if (!tomoyo_same_acl_head(entry, new_entry) ||
106 !check_duplicate(entry, new_entry)) 107 !check_duplicate(entry, new_entry))
107 continue; 108 continue;
@@ -116,7 +117,7 @@ int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size,
116 if (error && !is_delete) { 117 if (error && !is_delete) {
117 entry = tomoyo_commit_ok(new_entry, size); 118 entry = tomoyo_commit_ok(new_entry, size);
118 if (entry) { 119 if (entry) {
119 list_add_tail_rcu(&entry->list, &domain->acl_info_list); 120 list_add_tail_rcu(&entry->list, list);
120 error = 0; 121 error = 0;
121 } 122 }
122 } 123 }
@@ -163,6 +164,14 @@ static const char *tomoyo_last_word(const char *name)
163 return name; 164 return name;
164} 165}
165 166
167/**
168 * tomoyo_same_transition_control - Check for duplicated "struct tomoyo_transition_control" entry.
169 *
170 * @a: Pointer to "struct tomoyo_acl_head".
171 * @b: Pointer to "struct tomoyo_acl_head".
172 *
173 * Returns true if @a == @b, false otherwise.
174 */
166static bool tomoyo_same_transition_control(const struct tomoyo_acl_head *a, 175static bool tomoyo_same_transition_control(const struct tomoyo_acl_head *a,
167 const struct tomoyo_acl_head *b) 176 const struct tomoyo_acl_head *b)
168{ 177{
@@ -178,22 +187,28 @@ static bool tomoyo_same_transition_control(const struct tomoyo_acl_head *a,
178} 187}
179 188
180/** 189/**
181 * tomoyo_update_transition_control_entry - Update "struct tomoyo_transition_control" list. 190 * tomoyo_write_transition_control - Write "struct tomoyo_transition_control" list.
182 * 191 *
183 * @domainname: The name of domain. Maybe NULL. 192 * @param: Pointer to "struct tomoyo_acl_param".
184 * @program: The name of program. Maybe NULL. 193 * @type: Type of this entry.
185 * @type: Type of transition.
186 * @is_delete: True if it is a delete request.
187 * 194 *
188 * Returns 0 on success, negative value otherwise. 195 * Returns 0 on success, negative value otherwise.
189 */ 196 */
190static int tomoyo_update_transition_control_entry(const char *domainname, 197int tomoyo_write_transition_control(struct tomoyo_acl_param *param,
191 const char *program, 198 const u8 type)
192 const u8 type,
193 const bool is_delete)
194{ 199{
195 struct tomoyo_transition_control e = { .type = type }; 200 struct tomoyo_transition_control e = { .type = type };
196 int error = is_delete ? -ENOENT : -ENOMEM; 201 int error = param->is_delete ? -ENOENT : -ENOMEM;
202 char *program = param->data;
203 char *domainname = strstr(program, " from ");
204 if (domainname) {
205 *domainname = '\0';
206 domainname += 6;
207 } else if (type == TOMOYO_TRANSITION_CONTROL_NO_KEEP ||
208 type == TOMOYO_TRANSITION_CONTROL_KEEP) {
209 domainname = program;
210 program = NULL;
211 }
197 if (program) { 212 if (program) {
198 if (!tomoyo_correct_path(program)) 213 if (!tomoyo_correct_path(program))
199 return -EINVAL; 214 return -EINVAL;
@@ -211,42 +226,16 @@ static int tomoyo_update_transition_control_entry(const char *domainname,
211 if (!e.domainname) 226 if (!e.domainname)
212 goto out; 227 goto out;
213 } 228 }
214 error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, 229 param->list = &tomoyo_policy_list[TOMOYO_ID_TRANSITION_CONTROL];
215 &tomoyo_policy_list 230 error = tomoyo_update_policy(&e.head, sizeof(e), param,
216 [TOMOYO_ID_TRANSITION_CONTROL],
217 tomoyo_same_transition_control); 231 tomoyo_same_transition_control);
218 out: 232out:
219 tomoyo_put_name(e.domainname); 233 tomoyo_put_name(e.domainname);
220 tomoyo_put_name(e.program); 234 tomoyo_put_name(e.program);
221 return error; 235 return error;
222} 236}
223 237
224/** 238/**
225 * tomoyo_write_transition_control - Write "struct tomoyo_transition_control" list.
226 *
227 * @data: String to parse.
228 * @is_delete: True if it is a delete request.
229 * @type: Type of this entry.
230 *
231 * Returns 0 on success, negative value otherwise.
232 */
233int tomoyo_write_transition_control(char *data, const bool is_delete,
234 const u8 type)
235{
236 char *domainname = strstr(data, " from ");
237 if (domainname) {
238 *domainname = '\0';
239 domainname += 6;
240 } else if (type == TOMOYO_TRANSITION_CONTROL_NO_KEEP ||
241 type == TOMOYO_TRANSITION_CONTROL_KEEP) {
242 domainname = data;
243 data = NULL;
244 }
245 return tomoyo_update_transition_control_entry(domainname, data, type,
246 is_delete);
247}
248
249/**
250 * tomoyo_transition_type - Get domain transition type. 239 * tomoyo_transition_type - Get domain transition type.
251 * 240 *
252 * @domainname: The name of domain. 241 * @domainname: The name of domain.
@@ -303,34 +292,41 @@ static u8 tomoyo_transition_type(const struct tomoyo_path_info *domainname,
303 return type; 292 return type;
304} 293}
305 294
295/**
296 * tomoyo_same_aggregator - Check for duplicated "struct tomoyo_aggregator" entry.
297 *
298 * @a: Pointer to "struct tomoyo_acl_head".
299 * @b: Pointer to "struct tomoyo_acl_head".
300 *
301 * Returns true if @a == @b, false otherwise.
302 */
306static bool tomoyo_same_aggregator(const struct tomoyo_acl_head *a, 303static bool tomoyo_same_aggregator(const struct tomoyo_acl_head *a,
307 const struct tomoyo_acl_head *b) 304 const struct tomoyo_acl_head *b)
308{ 305{
309 const struct tomoyo_aggregator *p1 = container_of(a, typeof(*p1), head); 306 const struct tomoyo_aggregator *p1 = container_of(a, typeof(*p1),
310 const struct tomoyo_aggregator *p2 = container_of(b, typeof(*p2), head); 307 head);
308 const struct tomoyo_aggregator *p2 = container_of(b, typeof(*p2),
309 head);
311 return p1->original_name == p2->original_name && 310 return p1->original_name == p2->original_name &&
312 p1->aggregated_name == p2->aggregated_name; 311 p1->aggregated_name == p2->aggregated_name;
313} 312}
314 313
315/** 314/**
316 * tomoyo_update_aggregator_entry - Update "struct tomoyo_aggregator" list. 315 * tomoyo_write_aggregator - Write "struct tomoyo_aggregator" list.
317 * 316 *
318 * @original_name: The original program's name. 317 * @param: Pointer to "struct tomoyo_acl_param".
319 * @aggregated_name: The program name to use.
320 * @is_delete: True if it is a delete request.
321 * 318 *
322 * Returns 0 on success, negative value otherwise. 319 * Returns 0 on success, negative value otherwise.
323 * 320 *
324 * Caller holds tomoyo_read_lock(). 321 * Caller holds tomoyo_read_lock().
325 */ 322 */
326static int tomoyo_update_aggregator_entry(const char *original_name, 323int tomoyo_write_aggregator(struct tomoyo_acl_param *param)
327 const char *aggregated_name,
328 const bool is_delete)
329{ 324{
330 struct tomoyo_aggregator e = { }; 325 struct tomoyo_aggregator e = { };
331 int error = is_delete ? -ENOENT : -ENOMEM; 326 int error = param->is_delete ? -ENOENT : -ENOMEM;
332 327 const char *original_name = tomoyo_read_token(param);
333 if (!tomoyo_correct_path(original_name) || 328 const char *aggregated_name = tomoyo_read_token(param);
329 if (!tomoyo_correct_word(original_name) ||
334 !tomoyo_correct_path(aggregated_name)) 330 !tomoyo_correct_path(aggregated_name))
335 return -EINVAL; 331 return -EINVAL;
336 e.original_name = tomoyo_get_name(original_name); 332 e.original_name = tomoyo_get_name(original_name);
@@ -338,36 +334,16 @@ static int tomoyo_update_aggregator_entry(const char *original_name,
338 if (!e.original_name || !e.aggregated_name || 334 if (!e.original_name || !e.aggregated_name ||
339 e.aggregated_name->is_patterned) /* No patterns allowed. */ 335 e.aggregated_name->is_patterned) /* No patterns allowed. */
340 goto out; 336 goto out;
341 error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, 337 param->list = &tomoyo_policy_list[TOMOYO_ID_AGGREGATOR];
342 &tomoyo_policy_list[TOMOYO_ID_AGGREGATOR], 338 error = tomoyo_update_policy(&e.head, sizeof(e), param,
343 tomoyo_same_aggregator); 339 tomoyo_same_aggregator);
344 out: 340out:
345 tomoyo_put_name(e.original_name); 341 tomoyo_put_name(e.original_name);
346 tomoyo_put_name(e.aggregated_name); 342 tomoyo_put_name(e.aggregated_name);
347 return error; 343 return error;
348} 344}
349 345
350/** 346/**
351 * tomoyo_write_aggregator - Write "struct tomoyo_aggregator" list.
352 *
353 * @data: String to parse.
354 * @is_delete: True if it is a delete request.
355 *
356 * Returns 0 on success, negative value otherwise.
357 *
358 * Caller holds tomoyo_read_lock().
359 */
360int tomoyo_write_aggregator(char *data, const bool is_delete)
361{
362 char *cp = strchr(data, ' ');
363
364 if (!cp)
365 return -EINVAL;
366 *cp++ = '\0';
367 return tomoyo_update_aggregator_entry(data, cp, is_delete);
368}
369
370/**
371 * tomoyo_assign_domain - Create a domain. 347 * tomoyo_assign_domain - Create a domain.
372 * 348 *
373 * @domainname: The name of domain. 349 * @domainname: The name of domain.