TOMOYO: Cleanup part 1.
[platform/adaptation/renesas_rcar/renesas_kernel.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 struct tomoyo_gc {
15         struct list_head list;
16         int type;
17         struct list_head *element;
18 };
19 static LIST_HEAD(tomoyo_gc_queue);
20 static DEFINE_MUTEX(tomoyo_gc_mutex);
21
22 /* Caller holds tomoyo_policy_lock mutex. */
23 static bool tomoyo_add_to_gc(const int type, struct list_head *element)
24 {
25         struct tomoyo_gc *entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
26         if (!entry)
27                 return false;
28         entry->type = type;
29         entry->element = element;
30         list_add(&entry->list, &tomoyo_gc_queue);
31         list_del_rcu(element);
32         return true;
33 }
34
35 static void tomoyo_del_transition_control(struct list_head *element)
36 {
37         struct tomoyo_transition_control *ptr =
38                 container_of(element, typeof(*ptr), head.list);
39         tomoyo_put_name(ptr->domainname);
40         tomoyo_put_name(ptr->program);
41 }
42
43 static void tomoyo_del_aggregator(struct list_head *element)
44 {
45         struct tomoyo_aggregator *ptr =
46                 container_of(element, typeof(*ptr), head.list);
47         tomoyo_put_name(ptr->original_name);
48         tomoyo_put_name(ptr->aggregated_name);
49 }
50
51 static void tomoyo_del_manager(struct list_head *element)
52 {
53         struct tomoyo_manager *ptr =
54                 container_of(element, typeof(*ptr), head.list);
55         tomoyo_put_name(ptr->manager);
56 }
57
58 static void tomoyo_del_acl(struct list_head *element)
59 {
60         struct tomoyo_acl_info *acl =
61                 container_of(element, typeof(*acl), list);
62         switch (acl->type) {
63         case TOMOYO_TYPE_PATH_ACL:
64                 {
65                         struct tomoyo_path_acl *entry
66                                 = container_of(acl, typeof(*entry), head);
67                         tomoyo_put_name_union(&entry->name);
68                 }
69                 break;
70         case TOMOYO_TYPE_PATH2_ACL:
71                 {
72                         struct tomoyo_path2_acl *entry
73                                 = container_of(acl, typeof(*entry), head);
74                         tomoyo_put_name_union(&entry->name1);
75                         tomoyo_put_name_union(&entry->name2);
76                 }
77                 break;
78         case TOMOYO_TYPE_PATH_NUMBER_ACL:
79                 {
80                         struct tomoyo_path_number_acl *entry
81                                 = container_of(acl, typeof(*entry), head);
82                         tomoyo_put_name_union(&entry->name);
83                         tomoyo_put_number_union(&entry->number);
84                 }
85                 break;
86         case TOMOYO_TYPE_MKDEV_ACL:
87                 {
88                         struct tomoyo_mkdev_acl *entry
89                                 = container_of(acl, typeof(*entry), head);
90                         tomoyo_put_name_union(&entry->name);
91                         tomoyo_put_number_union(&entry->mode);
92                         tomoyo_put_number_union(&entry->major);
93                         tomoyo_put_number_union(&entry->minor);
94                 }
95                 break;
96         case TOMOYO_TYPE_MOUNT_ACL:
97                 {
98                         struct tomoyo_mount_acl *entry
99                                 = container_of(acl, typeof(*entry), head);
100                         tomoyo_put_name_union(&entry->dev_name);
101                         tomoyo_put_name_union(&entry->dir_name);
102                         tomoyo_put_name_union(&entry->fs_type);
103                         tomoyo_put_number_union(&entry->flags);
104                 }
105                 break;
106         }
107 }
108
109 static bool tomoyo_del_domain(struct list_head *element)
110 {
111         struct tomoyo_domain_info *domain =
112                 container_of(element, typeof(*domain), list);
113         struct tomoyo_acl_info *acl;
114         struct tomoyo_acl_info *tmp;
115         /*
116          * Since we don't protect whole execve() operation using SRCU,
117          * we need to recheck domain->users at this point.
118          *
119          * (1) Reader starts SRCU section upon execve().
120          * (2) Reader traverses tomoyo_domain_list and finds this domain.
121          * (3) Writer marks this domain as deleted.
122          * (4) Garbage collector removes this domain from tomoyo_domain_list
123          *     because this domain is marked as deleted and used by nobody.
124          * (5) Reader saves reference to this domain into
125          *     "struct linux_binprm"->cred->security .
126          * (6) Reader finishes SRCU section, although execve() operation has
127          *     not finished yet.
128          * (7) Garbage collector waits for SRCU synchronization.
129          * (8) Garbage collector kfree() this domain because this domain is
130          *     used by nobody.
131          * (9) Reader finishes execve() operation and restores this domain from
132          *     "struct linux_binprm"->cred->security.
133          *
134          * By updating domain->users at (5), we can solve this race problem
135          * by rechecking domain->users at (8).
136          */
137         if (atomic_read(&domain->users))
138                 return false;
139         list_for_each_entry_safe(acl, tmp, &domain->acl_info_list, list) {
140                 tomoyo_del_acl(&acl->list);
141                 tomoyo_memory_free(acl);
142         }
143         tomoyo_put_name(domain->domainname);
144         return true;
145 }
146
147
148 static void tomoyo_del_name(struct list_head *element)
149 {
150         const struct tomoyo_name *ptr =
151                 container_of(element, typeof(*ptr), list);
152 }
153
154 static void tomoyo_del_path_group(struct list_head *element)
155 {
156         struct tomoyo_path_group *member =
157                 container_of(element, typeof(*member), head.list);
158         tomoyo_put_name(member->member_name);
159 }
160
161 static void tomoyo_del_group(struct list_head *element)
162 {
163         struct tomoyo_group *group =
164                 container_of(element, typeof(*group), list);
165         tomoyo_put_name(group->group_name);
166 }
167
168 static void tomoyo_del_number_group(struct list_head *element)
169 {
170         struct tomoyo_number_group *member =
171                 container_of(element, typeof(*member), head.list);
172 }
173
174 static bool tomoyo_collect_member(struct list_head *member_list, int id)
175 {
176         struct tomoyo_acl_head *member;
177         list_for_each_entry(member, member_list, list) {
178                 if (!member->is_deleted)
179                         continue;
180                 if (!tomoyo_add_to_gc(id, &member->list))
181                         return false;
182         }
183         return true;
184 }
185
186 static bool tomoyo_collect_acl(struct tomoyo_domain_info *domain)
187 {
188         struct tomoyo_acl_info *acl;
189         list_for_each_entry(acl, &domain->acl_info_list, list) {
190                 if (!acl->is_deleted)
191                         continue;
192                 if (!tomoyo_add_to_gc(TOMOYO_ID_ACL, &acl->list))
193                         return false;
194         }
195         return true;
196 }
197
198 static void tomoyo_collect_entry(void)
199 {
200         int i;
201         if (mutex_lock_interruptible(&tomoyo_policy_lock))
202                 return;
203         for (i = 0; i < TOMOYO_MAX_POLICY; i++) {
204                 if (!tomoyo_collect_member(&tomoyo_policy_list[i], i))
205                         goto unlock;
206         }
207         {
208                 struct tomoyo_domain_info *domain;
209                 list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
210                         if (!tomoyo_collect_acl(domain))
211                                 goto unlock;
212                         if (!domain->is_deleted || atomic_read(&domain->users))
213                                 continue;
214                         /*
215                          * Nobody is referring this domain. But somebody may
216                          * refer this domain after successful execve().
217                          * We recheck domain->users after SRCU synchronization.
218                          */
219                         if (!tomoyo_add_to_gc(TOMOYO_ID_DOMAIN, &domain->list))
220                                 goto unlock;
221                 }
222         }
223         for (i = 0; i < TOMOYO_MAX_HASH; i++) {
224                 struct tomoyo_name *ptr;
225                 list_for_each_entry_rcu(ptr, &tomoyo_name_list[i], list) {
226                         if (atomic_read(&ptr->users))
227                                 continue;
228                         if (!tomoyo_add_to_gc(TOMOYO_ID_NAME, &ptr->list))
229                                 goto unlock;
230                 }
231         }
232         for (i = 0; i < TOMOYO_MAX_GROUP; i++) {
233                 struct list_head *list = &tomoyo_group_list[i];
234                 int id;
235                 struct tomoyo_group *group;
236                 switch (i) {
237                 case 0:
238                         id = TOMOYO_ID_PATH_GROUP;
239                         break;
240                 default:
241                         id = TOMOYO_ID_NUMBER_GROUP;
242                         break;
243                 }
244                 list_for_each_entry(group, list, list) {
245                         if (!tomoyo_collect_member(&group->member_list, id))
246                                 goto unlock;
247                         if (!list_empty(&group->member_list) ||
248                             atomic_read(&group->users))
249                                 continue;
250                         if (!tomoyo_add_to_gc(TOMOYO_ID_GROUP, &group->list))
251                                 goto unlock;
252                 }
253         }
254  unlock:
255         mutex_unlock(&tomoyo_policy_lock);
256 }
257
258 static void tomoyo_kfree_entry(void)
259 {
260         struct tomoyo_gc *p;
261         struct tomoyo_gc *tmp;
262
263         list_for_each_entry_safe(p, tmp, &tomoyo_gc_queue, list) {
264                 struct list_head *element = p->element;
265                 switch (p->type) {
266                 case TOMOYO_ID_TRANSITION_CONTROL:
267                         tomoyo_del_transition_control(element);
268                         break;
269                 case TOMOYO_ID_AGGREGATOR:
270                         tomoyo_del_aggregator(element);
271                         break;
272                 case TOMOYO_ID_MANAGER:
273                         tomoyo_del_manager(element);
274                         break;
275                 case TOMOYO_ID_NAME:
276                         tomoyo_del_name(element);
277                         break;
278                 case TOMOYO_ID_ACL:
279                         tomoyo_del_acl(element);
280                         break;
281                 case TOMOYO_ID_DOMAIN:
282                         if (!tomoyo_del_domain(element))
283                                 continue;
284                         break;
285                 case TOMOYO_ID_PATH_GROUP:
286                         tomoyo_del_path_group(element);
287                         break;
288                 case TOMOYO_ID_GROUP:
289                         tomoyo_del_group(element);
290                         break;
291                 case TOMOYO_ID_NUMBER_GROUP:
292                         tomoyo_del_number_group(element);
293                         break;
294                 }
295                 tomoyo_memory_free(element);
296                 list_del(&p->list);
297                 kfree(p);
298         }
299 }
300
301 static int tomoyo_gc_thread(void *unused)
302 {
303         daemonize("GC for TOMOYO");
304         if (mutex_trylock(&tomoyo_gc_mutex)) {
305                 int i;
306                 for (i = 0; i < 10; i++) {
307                         tomoyo_collect_entry();
308                         if (list_empty(&tomoyo_gc_queue))
309                                 break;
310                         synchronize_srcu(&tomoyo_ss);
311                         tomoyo_kfree_entry();
312                 }
313                 mutex_unlock(&tomoyo_gc_mutex);
314         }
315         do_exit(0);
316 }
317
318 void tomoyo_run_gc(void)
319 {
320         struct task_struct *task = kthread_create(tomoyo_gc_thread, NULL,
321                                                   "GC for TOMOYO");
322         if (!IS_ERR(task))
323                 wake_up_process(task);
324 }