TOMOYO: Add mount restriction.
[deliverable/linux.git] / security / tomoyo / gc.c
1 /*
2 * security/tomoyo/gc.c
3 *
4 * Implementation of the Domain-Based Mandatory Access Control.
5 *
6 * Copyright (C) 2005-2010 NTT DATA CORPORATION
7 *
8 */
9
10 #include "common.h"
11 #include <linux/kthread.h>
12 #include <linux/slab.h>
13
14 enum tomoyo_gc_id {
15 TOMOYO_ID_PATH_GROUP,
16 TOMOYO_ID_PATH_GROUP_MEMBER,
17 TOMOYO_ID_NUMBER_GROUP,
18 TOMOYO_ID_NUMBER_GROUP_MEMBER,
19 TOMOYO_ID_DOMAIN_INITIALIZER,
20 TOMOYO_ID_DOMAIN_KEEPER,
21 TOMOYO_ID_ALIAS,
22 TOMOYO_ID_GLOBALLY_READABLE,
23 TOMOYO_ID_PATTERN,
24 TOMOYO_ID_NO_REWRITE,
25 TOMOYO_ID_MANAGER,
26 TOMOYO_ID_NAME,
27 TOMOYO_ID_ACL,
28 TOMOYO_ID_DOMAIN
29 };
30
31 struct tomoyo_gc_entry {
32 struct list_head list;
33 int type;
34 void *element;
35 };
36 static LIST_HEAD(tomoyo_gc_queue);
37 static DEFINE_MUTEX(tomoyo_gc_mutex);
38
39 /* Caller holds tomoyo_policy_lock mutex. */
40 static bool tomoyo_add_to_gc(const int type, void *element)
41 {
42 struct tomoyo_gc_entry *entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
43 if (!entry)
44 return false;
45 entry->type = type;
46 entry->element = element;
47 list_add(&entry->list, &tomoyo_gc_queue);
48 return true;
49 }
50
51 static void tomoyo_del_allow_read
52 (struct tomoyo_globally_readable_file_entry *ptr)
53 {
54 tomoyo_put_name(ptr->filename);
55 }
56
57 static void tomoyo_del_file_pattern(struct tomoyo_pattern_entry *ptr)
58 {
59 tomoyo_put_name(ptr->pattern);
60 }
61
62 static void tomoyo_del_no_rewrite(struct tomoyo_no_rewrite_entry *ptr)
63 {
64 tomoyo_put_name(ptr->pattern);
65 }
66
67 static void tomoyo_del_domain_initializer
68 (struct tomoyo_domain_initializer_entry *ptr)
69 {
70 tomoyo_put_name(ptr->domainname);
71 tomoyo_put_name(ptr->program);
72 }
73
74 static void tomoyo_del_domain_keeper(struct tomoyo_domain_keeper_entry *ptr)
75 {
76 tomoyo_put_name(ptr->domainname);
77 tomoyo_put_name(ptr->program);
78 }
79
80 static void tomoyo_del_alias(struct tomoyo_alias_entry *ptr)
81 {
82 tomoyo_put_name(ptr->original_name);
83 tomoyo_put_name(ptr->aliased_name);
84 }
85
86 static void tomoyo_del_manager(struct tomoyo_policy_manager_entry *ptr)
87 {
88 tomoyo_put_name(ptr->manager);
89 }
90
91 static void tomoyo_del_acl(struct tomoyo_acl_info *acl)
92 {
93 switch (acl->type) {
94 case TOMOYO_TYPE_PATH_ACL:
95 {
96 struct tomoyo_path_acl *entry
97 = container_of(acl, typeof(*entry), head);
98 tomoyo_put_name_union(&entry->name);
99 }
100 break;
101 case TOMOYO_TYPE_PATH2_ACL:
102 {
103 struct tomoyo_path2_acl *entry
104 = container_of(acl, typeof(*entry), head);
105 tomoyo_put_name_union(&entry->name1);
106 tomoyo_put_name_union(&entry->name2);
107 }
108 break;
109 case TOMOYO_TYPE_PATH_NUMBER_ACL:
110 {
111 struct tomoyo_path_number_acl *entry
112 = container_of(acl, typeof(*entry), head);
113 tomoyo_put_name_union(&entry->name);
114 tomoyo_put_number_union(&entry->number);
115 }
116 break;
117 case TOMOYO_TYPE_PATH_NUMBER3_ACL:
118 {
119 struct tomoyo_path_number3_acl *entry
120 = container_of(acl, typeof(*entry), head);
121 tomoyo_put_name_union(&entry->name);
122 tomoyo_put_number_union(&entry->mode);
123 tomoyo_put_number_union(&entry->major);
124 tomoyo_put_number_union(&entry->minor);
125 }
126 break;
127 case TOMOYO_TYPE_MOUNT_ACL:
128 {
129 struct tomoyo_mount_acl *entry
130 = container_of(acl, typeof(*entry), head);
131 tomoyo_put_name_union(&entry->dev_name);
132 tomoyo_put_name_union(&entry->dir_name);
133 tomoyo_put_name_union(&entry->fs_type);
134 tomoyo_put_number_union(&entry->flags);
135 }
136 break;
137 default:
138 printk(KERN_WARNING "Unknown type\n");
139 break;
140 }
141 }
142
143 static bool tomoyo_del_domain(struct tomoyo_domain_info *domain)
144 {
145 struct tomoyo_acl_info *acl;
146 struct tomoyo_acl_info *tmp;
147 /*
148 * Since we don't protect whole execve() operation using SRCU,
149 * we need to recheck domain->users at this point.
150 *
151 * (1) Reader starts SRCU section upon execve().
152 * (2) Reader traverses tomoyo_domain_list and finds this domain.
153 * (3) Writer marks this domain as deleted.
154 * (4) Garbage collector removes this domain from tomoyo_domain_list
155 * because this domain is marked as deleted and used by nobody.
156 * (5) Reader saves reference to this domain into
157 * "struct linux_binprm"->cred->security .
158 * (6) Reader finishes SRCU section, although execve() operation has
159 * not finished yet.
160 * (7) Garbage collector waits for SRCU synchronization.
161 * (8) Garbage collector kfree() this domain because this domain is
162 * used by nobody.
163 * (9) Reader finishes execve() operation and restores this domain from
164 * "struct linux_binprm"->cred->security.
165 *
166 * By updating domain->users at (5), we can solve this race problem
167 * by rechecking domain->users at (8).
168 */
169 if (atomic_read(&domain->users))
170 return false;
171 list_for_each_entry_safe(acl, tmp, &domain->acl_info_list, list) {
172 tomoyo_del_acl(acl);
173 tomoyo_memory_free(acl);
174 }
175 tomoyo_put_name(domain->domainname);
176 return true;
177 }
178
179
180 static void tomoyo_del_name(const struct tomoyo_name_entry *ptr)
181 {
182 }
183
184 static void tomoyo_del_path_group_member(struct tomoyo_path_group_member
185 *member)
186 {
187 tomoyo_put_name(member->member_name);
188 }
189
190 static void tomoyo_del_path_group(struct tomoyo_path_group *group)
191 {
192 tomoyo_put_name(group->group_name);
193 }
194
195 static void tomoyo_del_number_group_member(struct tomoyo_number_group_member
196 *member)
197 {
198 }
199
200 static void tomoyo_del_number_group(struct tomoyo_number_group *group)
201 {
202 tomoyo_put_name(group->group_name);
203 }
204
205 static void tomoyo_collect_entry(void)
206 {
207 if (mutex_lock_interruptible(&tomoyo_policy_lock))
208 return;
209 {
210 struct tomoyo_globally_readable_file_entry *ptr;
211 list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list,
212 list) {
213 if (!ptr->is_deleted)
214 continue;
215 if (tomoyo_add_to_gc(TOMOYO_ID_GLOBALLY_READABLE, ptr))
216 list_del_rcu(&ptr->list);
217 else
218 break;
219 }
220 }
221 {
222 struct tomoyo_pattern_entry *ptr;
223 list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) {
224 if (!ptr->is_deleted)
225 continue;
226 if (tomoyo_add_to_gc(TOMOYO_ID_PATTERN, ptr))
227 list_del_rcu(&ptr->list);
228 else
229 break;
230 }
231 }
232 {
233 struct tomoyo_no_rewrite_entry *ptr;
234 list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) {
235 if (!ptr->is_deleted)
236 continue;
237 if (tomoyo_add_to_gc(TOMOYO_ID_NO_REWRITE, ptr))
238 list_del_rcu(&ptr->list);
239 else
240 break;
241 }
242 }
243 {
244 struct tomoyo_domain_initializer_entry *ptr;
245 list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list,
246 list) {
247 if (!ptr->is_deleted)
248 continue;
249 if (tomoyo_add_to_gc(TOMOYO_ID_DOMAIN_INITIALIZER, ptr))
250 list_del_rcu(&ptr->list);
251 else
252 break;
253 }
254 }
255 {
256 struct tomoyo_domain_keeper_entry *ptr;
257 list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) {
258 if (!ptr->is_deleted)
259 continue;
260 if (tomoyo_add_to_gc(TOMOYO_ID_DOMAIN_KEEPER, ptr))
261 list_del_rcu(&ptr->list);
262 else
263 break;
264 }
265 }
266 {
267 struct tomoyo_alias_entry *ptr;
268 list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) {
269 if (!ptr->is_deleted)
270 continue;
271 if (tomoyo_add_to_gc(TOMOYO_ID_ALIAS, ptr))
272 list_del_rcu(&ptr->list);
273 else
274 break;
275 }
276 }
277 {
278 struct tomoyo_policy_manager_entry *ptr;
279 list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list,
280 list) {
281 if (!ptr->is_deleted)
282 continue;
283 if (tomoyo_add_to_gc(TOMOYO_ID_MANAGER, ptr))
284 list_del_rcu(&ptr->list);
285 else
286 break;
287 }
288 }
289 {
290 struct tomoyo_domain_info *domain;
291 list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
292 struct tomoyo_acl_info *acl;
293 list_for_each_entry_rcu(acl, &domain->acl_info_list,
294 list) {
295 switch (acl->type) {
296 case TOMOYO_TYPE_PATH_ACL:
297 if (container_of(acl,
298 struct tomoyo_path_acl,
299 head)->perm)
300 continue;
301 break;
302 case TOMOYO_TYPE_PATH2_ACL:
303 if (container_of(acl,
304 struct tomoyo_path2_acl,
305 head)->perm)
306 continue;
307 break;
308 case TOMOYO_TYPE_PATH_NUMBER_ACL:
309 if (container_of(acl,
310 struct tomoyo_path_number_acl,
311 head)->perm)
312 continue;
313 break;
314 case TOMOYO_TYPE_PATH_NUMBER3_ACL:
315 if (container_of(acl,
316 struct tomoyo_path_number3_acl,
317 head)->perm)
318 continue;
319 break;
320 default:
321 continue;
322 }
323 if (tomoyo_add_to_gc(TOMOYO_ID_ACL, acl))
324 list_del_rcu(&acl->list);
325 else
326 break;
327 }
328 if (!domain->is_deleted || atomic_read(&domain->users))
329 continue;
330 /*
331 * Nobody is referring this domain. But somebody may
332 * refer this domain after successful execve().
333 * We recheck domain->users after SRCU synchronization.
334 */
335 if (tomoyo_add_to_gc(TOMOYO_ID_DOMAIN, domain))
336 list_del_rcu(&domain->list);
337 else
338 break;
339 }
340 }
341 {
342 int i;
343 for (i = 0; i < TOMOYO_MAX_HASH; i++) {
344 struct tomoyo_name_entry *ptr;
345 list_for_each_entry_rcu(ptr, &tomoyo_name_list[i],
346 list) {
347 if (atomic_read(&ptr->users))
348 continue;
349 if (tomoyo_add_to_gc(TOMOYO_ID_NAME, ptr))
350 list_del_rcu(&ptr->list);
351 else {
352 i = TOMOYO_MAX_HASH;
353 break;
354 }
355 }
356 }
357 }
358 {
359 struct tomoyo_path_group *group;
360 list_for_each_entry_rcu(group, &tomoyo_path_group_list, list) {
361 struct tomoyo_path_group_member *member;
362 list_for_each_entry_rcu(member, &group->member_list,
363 list) {
364 if (!member->is_deleted)
365 continue;
366 if (tomoyo_add_to_gc(TOMOYO_ID_PATH_GROUP_MEMBER,
367 member))
368 list_del_rcu(&member->list);
369 else
370 break;
371 }
372 if (!list_empty(&group->member_list) ||
373 atomic_read(&group->users))
374 continue;
375 if (tomoyo_add_to_gc(TOMOYO_ID_PATH_GROUP, group))
376 list_del_rcu(&group->list);
377 else
378 break;
379 }
380 }
381 {
382 struct tomoyo_number_group *group;
383 list_for_each_entry_rcu(group, &tomoyo_number_group_list, list) {
384 struct tomoyo_number_group_member *member;
385 list_for_each_entry_rcu(member, &group->member_list,
386 list) {
387 if (!member->is_deleted)
388 continue;
389 if (tomoyo_add_to_gc(TOMOYO_ID_NUMBER_GROUP_MEMBER,
390 member))
391 list_del_rcu(&member->list);
392 else
393 break;
394 }
395 if (!list_empty(&group->member_list) ||
396 atomic_read(&group->users))
397 continue;
398 if (tomoyo_add_to_gc(TOMOYO_ID_NUMBER_GROUP, group))
399 list_del_rcu(&group->list);
400 else
401 break;
402 }
403 }
404 mutex_unlock(&tomoyo_policy_lock);
405 }
406
407 static void tomoyo_kfree_entry(void)
408 {
409 struct tomoyo_gc_entry *p;
410 struct tomoyo_gc_entry *tmp;
411
412 list_for_each_entry_safe(p, tmp, &tomoyo_gc_queue, list) {
413 switch (p->type) {
414 case TOMOYO_ID_DOMAIN_INITIALIZER:
415 tomoyo_del_domain_initializer(p->element);
416 break;
417 case TOMOYO_ID_DOMAIN_KEEPER:
418 tomoyo_del_domain_keeper(p->element);
419 break;
420 case TOMOYO_ID_ALIAS:
421 tomoyo_del_alias(p->element);
422 break;
423 case TOMOYO_ID_GLOBALLY_READABLE:
424 tomoyo_del_allow_read(p->element);
425 break;
426 case TOMOYO_ID_PATTERN:
427 tomoyo_del_file_pattern(p->element);
428 break;
429 case TOMOYO_ID_NO_REWRITE:
430 tomoyo_del_no_rewrite(p->element);
431 break;
432 case TOMOYO_ID_MANAGER:
433 tomoyo_del_manager(p->element);
434 break;
435 case TOMOYO_ID_NAME:
436 tomoyo_del_name(p->element);
437 break;
438 case TOMOYO_ID_ACL:
439 tomoyo_del_acl(p->element);
440 break;
441 case TOMOYO_ID_DOMAIN:
442 if (!tomoyo_del_domain(p->element))
443 continue;
444 break;
445 case TOMOYO_ID_PATH_GROUP_MEMBER:
446 tomoyo_del_path_group_member(p->element);
447 break;
448 case TOMOYO_ID_PATH_GROUP:
449 tomoyo_del_path_group(p->element);
450 break;
451 case TOMOYO_ID_NUMBER_GROUP_MEMBER:
452 tomoyo_del_number_group_member(p->element);
453 break;
454 case TOMOYO_ID_NUMBER_GROUP:
455 tomoyo_del_number_group(p->element);
456 break;
457 default:
458 printk(KERN_WARNING "Unknown type\n");
459 break;
460 }
461 tomoyo_memory_free(p->element);
462 list_del(&p->list);
463 kfree(p);
464 }
465 }
466
467 static int tomoyo_gc_thread(void *unused)
468 {
469 daemonize("GC for TOMOYO");
470 if (mutex_trylock(&tomoyo_gc_mutex)) {
471 int i;
472 for (i = 0; i < 10; i++) {
473 tomoyo_collect_entry();
474 if (list_empty(&tomoyo_gc_queue))
475 break;
476 synchronize_srcu(&tomoyo_ss);
477 tomoyo_kfree_entry();
478 }
479 mutex_unlock(&tomoyo_gc_mutex);
480 }
481 do_exit(0);
482 }
483
484 void tomoyo_run_gc(void)
485 {
486 struct task_struct *task = kthread_create(tomoyo_gc_thread, NULL,
487 "GC for TOMOYO");
488 if (!IS_ERR(task))
489 wake_up_process(task);
490 }
This page took 0.090116 seconds and 5 git commands to generate.