]> bbs.cooldavid.org Git - net-next-2.6.git/blob - security/tomoyo/gc.c
be2d3b935533bc06cb7a08f4bdae5ec64890b8bb
[net-next-2.6.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 }