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