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