writeback: split writeback_inodes_wb
[linux-2.6/next.git] / security / tomoyo / gc.c
blobb9cc71b04314b0b50b8f301cacb9b9ac432ad963
1 /*
2 * security/tomoyo/gc.c
4 * Implementation of the Domain-Based Mandatory Access Control.
6 * Copyright (C) 2005-2010 NTT DATA CORPORATION
8 */
10 #include "common.h"
11 #include <linux/kthread.h>
12 #include <linux/slab.h>
14 enum tomoyo_gc_id {
15 TOMOYO_ID_PATH_GROUP,
16 TOMOYO_ID_PATH_GROUP_MEMBER,
17 TOMOYO_ID_DOMAIN_INITIALIZER,
18 TOMOYO_ID_DOMAIN_KEEPER,
19 TOMOYO_ID_ALIAS,
20 TOMOYO_ID_GLOBALLY_READABLE,
21 TOMOYO_ID_PATTERN,
22 TOMOYO_ID_NO_REWRITE,
23 TOMOYO_ID_MANAGER,
24 TOMOYO_ID_NAME,
25 TOMOYO_ID_ACL,
26 TOMOYO_ID_DOMAIN
29 struct tomoyo_gc_entry {
30 struct list_head list;
31 int type;
32 void *element;
34 static LIST_HEAD(tomoyo_gc_queue);
35 static DEFINE_MUTEX(tomoyo_gc_mutex);
37 /* Caller holds tomoyo_policy_lock mutex. */
38 static bool tomoyo_add_to_gc(const int type, void *element)
40 struct tomoyo_gc_entry *entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
41 if (!entry)
42 return false;
43 entry->type = type;
44 entry->element = element;
45 list_add(&entry->list, &tomoyo_gc_queue);
46 return true;
49 static void tomoyo_del_allow_read
50 (struct tomoyo_globally_readable_file_entry *ptr)
52 tomoyo_put_name(ptr->filename);
55 static void tomoyo_del_file_pattern(struct tomoyo_pattern_entry *ptr)
57 tomoyo_put_name(ptr->pattern);
60 static void tomoyo_del_no_rewrite(struct tomoyo_no_rewrite_entry *ptr)
62 tomoyo_put_name(ptr->pattern);
65 static void tomoyo_del_domain_initializer
66 (struct tomoyo_domain_initializer_entry *ptr)
68 tomoyo_put_name(ptr->domainname);
69 tomoyo_put_name(ptr->program);
72 static void tomoyo_del_domain_keeper(struct tomoyo_domain_keeper_entry *ptr)
74 tomoyo_put_name(ptr->domainname);
75 tomoyo_put_name(ptr->program);
78 static void tomoyo_del_alias(struct tomoyo_alias_entry *ptr)
80 tomoyo_put_name(ptr->original_name);
81 tomoyo_put_name(ptr->aliased_name);
84 static void tomoyo_del_manager(struct tomoyo_policy_manager_entry *ptr)
86 tomoyo_put_name(ptr->manager);
89 static void tomoyo_del_acl(struct tomoyo_acl_info *acl)
91 switch (acl->type) {
92 case TOMOYO_TYPE_PATH_ACL:
94 struct tomoyo_path_acl *entry
95 = container_of(acl, typeof(*entry), head);
96 tomoyo_put_name_union(&entry->name);
98 break;
99 case TOMOYO_TYPE_PATH2_ACL:
101 struct tomoyo_path2_acl *entry
102 = container_of(acl, typeof(*entry), head);
103 tomoyo_put_name_union(&entry->name1);
104 tomoyo_put_name_union(&entry->name2);
106 break;
107 default:
108 printk(KERN_WARNING "Unknown type\n");
109 break;
113 static bool tomoyo_del_domain(struct tomoyo_domain_info *domain)
115 struct tomoyo_acl_info *acl;
116 struct tomoyo_acl_info *tmp;
118 * Since we don't protect whole execve() operation using SRCU,
119 * we need to recheck domain->users at this point.
121 * (1) Reader starts SRCU section upon execve().
122 * (2) Reader traverses tomoyo_domain_list and finds this domain.
123 * (3) Writer marks this domain as deleted.
124 * (4) Garbage collector removes this domain from tomoyo_domain_list
125 * because this domain is marked as deleted and used by nobody.
126 * (5) Reader saves reference to this domain into
127 * "struct linux_binprm"->cred->security .
128 * (6) Reader finishes SRCU section, although execve() operation has
129 * not finished yet.
130 * (7) Garbage collector waits for SRCU synchronization.
131 * (8) Garbage collector kfree() this domain because this domain is
132 * used by nobody.
133 * (9) Reader finishes execve() operation and restores this domain from
134 * "struct linux_binprm"->cred->security.
136 * By updating domain->users at (5), we can solve this race problem
137 * by rechecking domain->users at (8).
139 if (atomic_read(&domain->users))
140 return false;
141 list_for_each_entry_safe(acl, tmp, &domain->acl_info_list, list) {
142 tomoyo_del_acl(acl);
143 tomoyo_memory_free(acl);
145 tomoyo_put_name(domain->domainname);
146 return true;
150 static void tomoyo_del_name(const struct tomoyo_name_entry *ptr)
154 static void tomoyo_del_path_group_member(struct tomoyo_path_group_member
155 *member)
157 tomoyo_put_name(member->member_name);
160 static void tomoyo_del_path_group(struct tomoyo_path_group *group)
162 tomoyo_put_name(group->group_name);
165 static void tomoyo_collect_entry(void)
167 if (mutex_lock_interruptible(&tomoyo_policy_lock))
168 return;
170 struct tomoyo_globally_readable_file_entry *ptr;
171 list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list,
172 list) {
173 if (!ptr->is_deleted)
174 continue;
175 if (tomoyo_add_to_gc(TOMOYO_ID_GLOBALLY_READABLE, ptr))
176 list_del_rcu(&ptr->list);
177 else
178 break;
182 struct tomoyo_pattern_entry *ptr;
183 list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) {
184 if (!ptr->is_deleted)
185 continue;
186 if (tomoyo_add_to_gc(TOMOYO_ID_PATTERN, ptr))
187 list_del_rcu(&ptr->list);
188 else
189 break;
193 struct tomoyo_no_rewrite_entry *ptr;
194 list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) {
195 if (!ptr->is_deleted)
196 continue;
197 if (tomoyo_add_to_gc(TOMOYO_ID_NO_REWRITE, ptr))
198 list_del_rcu(&ptr->list);
199 else
200 break;
204 struct tomoyo_domain_initializer_entry *ptr;
205 list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list,
206 list) {
207 if (!ptr->is_deleted)
208 continue;
209 if (tomoyo_add_to_gc(TOMOYO_ID_DOMAIN_INITIALIZER, ptr))
210 list_del_rcu(&ptr->list);
211 else
212 break;
216 struct tomoyo_domain_keeper_entry *ptr;
217 list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) {
218 if (!ptr->is_deleted)
219 continue;
220 if (tomoyo_add_to_gc(TOMOYO_ID_DOMAIN_KEEPER, ptr))
221 list_del_rcu(&ptr->list);
222 else
223 break;
227 struct tomoyo_alias_entry *ptr;
228 list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) {
229 if (!ptr->is_deleted)
230 continue;
231 if (tomoyo_add_to_gc(TOMOYO_ID_ALIAS, ptr))
232 list_del_rcu(&ptr->list);
233 else
234 break;
238 struct tomoyo_policy_manager_entry *ptr;
239 list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list,
240 list) {
241 if (!ptr->is_deleted)
242 continue;
243 if (tomoyo_add_to_gc(TOMOYO_ID_MANAGER, ptr))
244 list_del_rcu(&ptr->list);
245 else
246 break;
250 struct tomoyo_domain_info *domain;
251 list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
252 struct tomoyo_acl_info *acl;
253 list_for_each_entry_rcu(acl, &domain->acl_info_list,
254 list) {
255 switch (acl->type) {
256 case TOMOYO_TYPE_PATH_ACL:
257 if (container_of(acl,
258 struct tomoyo_path_acl,
259 head)->perm ||
260 container_of(acl,
261 struct tomoyo_path_acl,
262 head)->perm_high)
263 continue;
264 break;
265 case TOMOYO_TYPE_PATH2_ACL:
266 if (container_of(acl,
267 struct tomoyo_path2_acl,
268 head)->perm)
269 continue;
270 break;
271 default:
272 continue;
274 if (tomoyo_add_to_gc(TOMOYO_ID_ACL, acl))
275 list_del_rcu(&acl->list);
276 else
277 break;
279 if (!domain->is_deleted || atomic_read(&domain->users))
280 continue;
282 * Nobody is referring this domain. But somebody may
283 * refer this domain after successful execve().
284 * We recheck domain->users after SRCU synchronization.
286 if (tomoyo_add_to_gc(TOMOYO_ID_DOMAIN, domain))
287 list_del_rcu(&domain->list);
288 else
289 break;
293 int i;
294 for (i = 0; i < TOMOYO_MAX_HASH; i++) {
295 struct tomoyo_name_entry *ptr;
296 list_for_each_entry_rcu(ptr, &tomoyo_name_list[i],
297 list) {
298 if (atomic_read(&ptr->users))
299 continue;
300 if (tomoyo_add_to_gc(TOMOYO_ID_NAME, ptr))
301 list_del_rcu(&ptr->list);
302 else {
303 i = TOMOYO_MAX_HASH;
304 break;
310 struct tomoyo_path_group *group;
311 list_for_each_entry_rcu(group, &tomoyo_path_group_list, list) {
312 struct tomoyo_path_group_member *member;
313 list_for_each_entry_rcu(member, &group->member_list,
314 list) {
315 if (!member->is_deleted)
316 continue;
317 if (tomoyo_add_to_gc(TOMOYO_ID_PATH_GROUP_MEMBER,
318 member))
319 list_del_rcu(&member->list);
320 else
321 break;
323 if (!list_empty(&group->member_list) ||
324 atomic_read(&group->users))
325 continue;
326 if (tomoyo_add_to_gc(TOMOYO_ID_PATH_GROUP, group))
327 list_del_rcu(&group->list);
328 else
329 break;
332 mutex_unlock(&tomoyo_policy_lock);
335 static void tomoyo_kfree_entry(void)
337 struct tomoyo_gc_entry *p;
338 struct tomoyo_gc_entry *tmp;
340 list_for_each_entry_safe(p, tmp, &tomoyo_gc_queue, list) {
341 switch (p->type) {
342 case TOMOYO_ID_DOMAIN_INITIALIZER:
343 tomoyo_del_domain_initializer(p->element);
344 break;
345 case TOMOYO_ID_DOMAIN_KEEPER:
346 tomoyo_del_domain_keeper(p->element);
347 break;
348 case TOMOYO_ID_ALIAS:
349 tomoyo_del_alias(p->element);
350 break;
351 case TOMOYO_ID_GLOBALLY_READABLE:
352 tomoyo_del_allow_read(p->element);
353 break;
354 case TOMOYO_ID_PATTERN:
355 tomoyo_del_file_pattern(p->element);
356 break;
357 case TOMOYO_ID_NO_REWRITE:
358 tomoyo_del_no_rewrite(p->element);
359 break;
360 case TOMOYO_ID_MANAGER:
361 tomoyo_del_manager(p->element);
362 break;
363 case TOMOYO_ID_NAME:
364 tomoyo_del_name(p->element);
365 break;
366 case TOMOYO_ID_ACL:
367 tomoyo_del_acl(p->element);
368 break;
369 case TOMOYO_ID_DOMAIN:
370 if (!tomoyo_del_domain(p->element))
371 continue;
372 break;
373 case TOMOYO_ID_PATH_GROUP_MEMBER:
374 tomoyo_del_path_group_member(p->element);
375 break;
376 case TOMOYO_ID_PATH_GROUP:
377 tomoyo_del_path_group(p->element);
378 break;
379 default:
380 printk(KERN_WARNING "Unknown type\n");
381 break;
383 tomoyo_memory_free(p->element);
384 list_del(&p->list);
385 kfree(p);
389 static int tomoyo_gc_thread(void *unused)
391 daemonize("GC for TOMOYO");
392 if (mutex_trylock(&tomoyo_gc_mutex)) {
393 int i;
394 for (i = 0; i < 10; i++) {
395 tomoyo_collect_entry();
396 if (list_empty(&tomoyo_gc_queue))
397 break;
398 synchronize_srcu(&tomoyo_ss);
399 tomoyo_kfree_entry();
401 mutex_unlock(&tomoyo_gc_mutex);
403 do_exit(0);
406 void tomoyo_run_gc(void)
408 struct task_struct *task = kthread_create(tomoyo_gc_thread, NULL,
409 "GC for TOMOYO");
410 if (!IS_ERR(task))
411 wake_up_process(task);