gc.c revision bd03a3e4c9a9df0c6b007045fa7fc8889111a478
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
14struct tomoyo_gc {
15	struct list_head list;
16	enum tomoyo_policy_id type;
17	struct list_head *element;
18};
19static LIST_HEAD(tomoyo_gc_queue);
20static DEFINE_MUTEX(tomoyo_gc_mutex);
21
22/**
23 * tomoyo_add_to_gc - Add an entry to to be deleted list.
24 *
25 * @type:    One of values in "enum tomoyo_policy_id".
26 * @element: Pointer to "struct list_head".
27 *
28 * Returns true on success, false otherwise.
29 *
30 * Caller holds tomoyo_policy_lock mutex.
31 *
32 * Adding an entry needs kmalloc(). Thus, if we try to add thousands of
33 * entries at once, it will take too long time. Thus, do not add more than 128
34 * entries per a scan. But to be able to handle worst case where all entries
35 * are in-use, we accept one more entry per a scan.
36 *
37 * If we use singly linked list using "struct list_head"->prev (which is
38 * LIST_POISON2), we can avoid kmalloc().
39 */
40static bool tomoyo_add_to_gc(const int type, struct list_head *element)
41{
42	struct tomoyo_gc *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	list_del_rcu(element);
49	return true;
50}
51
52/**
53 * tomoyo_del_transition_control - Delete members in "struct tomoyo_transition_control".
54 *
55 * @element: Pointer to "struct list_head".
56 *
57 * Returns nothing.
58 */
59static void tomoyo_del_transition_control(struct list_head *element)
60{
61	struct tomoyo_transition_control *ptr =
62		container_of(element, typeof(*ptr), head.list);
63	tomoyo_put_name(ptr->domainname);
64	tomoyo_put_name(ptr->program);
65}
66
67/**
68 * tomoyo_del_aggregator - Delete members in "struct tomoyo_aggregator".
69 *
70 * @element: Pointer to "struct list_head".
71 *
72 * Returns nothing.
73 */
74static void tomoyo_del_aggregator(struct list_head *element)
75{
76	struct tomoyo_aggregator *ptr =
77		container_of(element, typeof(*ptr), head.list);
78	tomoyo_put_name(ptr->original_name);
79	tomoyo_put_name(ptr->aggregated_name);
80}
81
82/**
83 * tomoyo_del_manager - Delete members in "struct tomoyo_manager".
84 *
85 * @element: Pointer to "struct list_head".
86 *
87 * Returns nothing.
88 */
89static void tomoyo_del_manager(struct list_head *element)
90{
91	struct tomoyo_manager *ptr =
92		container_of(element, typeof(*ptr), head.list);
93	tomoyo_put_name(ptr->manager);
94}
95
96/**
97 * tomoyo_del_acl - Delete members in "struct tomoyo_acl_info".
98 *
99 * @element: Pointer to "struct list_head".
100 *
101 * Returns nothing.
102 */
103static void tomoyo_del_acl(struct list_head *element)
104{
105	struct tomoyo_acl_info *acl =
106		container_of(element, typeof(*acl), list);
107	switch (acl->type) {
108	case TOMOYO_TYPE_PATH_ACL:
109		{
110			struct tomoyo_path_acl *entry
111				= container_of(acl, typeof(*entry), head);
112			tomoyo_put_name_union(&entry->name);
113		}
114		break;
115	case TOMOYO_TYPE_PATH2_ACL:
116		{
117			struct tomoyo_path2_acl *entry
118				= container_of(acl, typeof(*entry), head);
119			tomoyo_put_name_union(&entry->name1);
120			tomoyo_put_name_union(&entry->name2);
121		}
122		break;
123	case TOMOYO_TYPE_PATH_NUMBER_ACL:
124		{
125			struct tomoyo_path_number_acl *entry
126				= container_of(acl, typeof(*entry), head);
127			tomoyo_put_name_union(&entry->name);
128			tomoyo_put_number_union(&entry->number);
129		}
130		break;
131	case TOMOYO_TYPE_MKDEV_ACL:
132		{
133			struct tomoyo_mkdev_acl *entry
134				= container_of(acl, typeof(*entry), head);
135			tomoyo_put_name_union(&entry->name);
136			tomoyo_put_number_union(&entry->mode);
137			tomoyo_put_number_union(&entry->major);
138			tomoyo_put_number_union(&entry->minor);
139		}
140		break;
141	case TOMOYO_TYPE_MOUNT_ACL:
142		{
143			struct tomoyo_mount_acl *entry
144				= container_of(acl, typeof(*entry), head);
145			tomoyo_put_name_union(&entry->dev_name);
146			tomoyo_put_name_union(&entry->dir_name);
147			tomoyo_put_name_union(&entry->fs_type);
148			tomoyo_put_number_union(&entry->flags);
149		}
150		break;
151	}
152}
153
154static bool tomoyo_del_domain(struct list_head *element)
155{
156	struct tomoyo_domain_info *domain =
157		container_of(element, typeof(*domain), list);
158	struct tomoyo_acl_info *acl;
159	struct tomoyo_acl_info *tmp;
160	/*
161	 * Since we don't protect whole execve() operation using SRCU,
162	 * we need to recheck domain->users at this point.
163	 *
164	 * (1) Reader starts SRCU section upon execve().
165	 * (2) Reader traverses tomoyo_domain_list and finds this domain.
166	 * (3) Writer marks this domain as deleted.
167	 * (4) Garbage collector removes this domain from tomoyo_domain_list
168	 *     because this domain is marked as deleted and used by nobody.
169	 * (5) Reader saves reference to this domain into
170	 *     "struct linux_binprm"->cred->security .
171	 * (6) Reader finishes SRCU section, although execve() operation has
172	 *     not finished yet.
173	 * (7) Garbage collector waits for SRCU synchronization.
174	 * (8) Garbage collector kfree() this domain because this domain is
175	 *     used by nobody.
176	 * (9) Reader finishes execve() operation and restores this domain from
177	 *     "struct linux_binprm"->cred->security.
178	 *
179	 * By updating domain->users at (5), we can solve this race problem
180	 * by rechecking domain->users at (8).
181	 */
182	if (atomic_read(&domain->users))
183		return false;
184	list_for_each_entry_safe(acl, tmp, &domain->acl_info_list, list) {
185		tomoyo_del_acl(&acl->list);
186		tomoyo_memory_free(acl);
187	}
188	tomoyo_put_name(domain->domainname);
189	return true;
190}
191
192
193/**
194 * tomoyo_del_name - Delete members in "struct tomoyo_name".
195 *
196 * @element: Pointer to "struct list_head".
197 *
198 * Returns nothing.
199 */
200static void tomoyo_del_name(struct list_head *element)
201{
202	const struct tomoyo_name *ptr =
203		container_of(element, typeof(*ptr), head.list);
204}
205
206/**
207 * tomoyo_del_path_group - Delete members in "struct tomoyo_path_group".
208 *
209 * @element: Pointer to "struct list_head".
210 *
211 * Returns nothing.
212 */
213static void tomoyo_del_path_group(struct list_head *element)
214{
215	struct tomoyo_path_group *member =
216		container_of(element, typeof(*member), head.list);
217	tomoyo_put_name(member->member_name);
218}
219
220/**
221 * tomoyo_del_group - Delete "struct tomoyo_group".
222 *
223 * @element: Pointer to "struct list_head".
224 *
225 * Returns nothing.
226 */
227static void tomoyo_del_group(struct list_head *element)
228{
229	struct tomoyo_group *group =
230		container_of(element, typeof(*group), head.list);
231	tomoyo_put_name(group->group_name);
232}
233
234/**
235 * tomoyo_del_number_group - Delete members in "struct tomoyo_number_group".
236 *
237 * @element: Pointer to "struct list_head".
238 *
239 * Returns nothing.
240 */
241static void tomoyo_del_number_group(struct list_head *element)
242{
243	struct tomoyo_number_group *member =
244		container_of(element, typeof(*member), head.list);
245}
246
247/**
248 * tomoyo_collect_member - Delete elements with "struct tomoyo_acl_head".
249 *
250 * @id:          One of values in "enum tomoyo_policy_id".
251 * @member_list: Pointer to "struct list_head".
252 *
253 * Returns true if some elements are deleted, false otherwise.
254 */
255static bool tomoyo_collect_member(const enum tomoyo_policy_id id,
256				  struct list_head *member_list)
257{
258	struct tomoyo_acl_head *member;
259	list_for_each_entry(member, member_list, list) {
260		if (!member->is_deleted)
261			continue;
262		if (!tomoyo_add_to_gc(id, &member->list))
263			return false;
264	}
265        return true;
266}
267
268/**
269 * tomoyo_collect_acl - Delete elements in "struct tomoyo_domain_info".
270 *
271 * @list: Pointer to "struct list_head".
272 *
273 * Returns true if some elements are deleted, false otherwise.
274 */
275static bool tomoyo_collect_acl(struct list_head *list)
276{
277	struct tomoyo_acl_info *acl;
278	list_for_each_entry(acl, list, list) {
279		if (!acl->is_deleted)
280			continue;
281		if (!tomoyo_add_to_gc(TOMOYO_ID_ACL, &acl->list))
282			return false;
283	}
284	return true;
285}
286
287/**
288 * tomoyo_collect_entry - Scan lists for deleted elements.
289 *
290 * Returns nothing.
291 */
292static void tomoyo_collect_entry(void)
293{
294	int i;
295	enum tomoyo_policy_id id;
296	struct tomoyo_policy_namespace *ns;
297	int idx;
298	if (mutex_lock_interruptible(&tomoyo_policy_lock))
299		return;
300	idx = tomoyo_read_lock();
301	{
302		struct tomoyo_domain_info *domain;
303		list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
304			if (!tomoyo_collect_acl(&domain->acl_info_list))
305				goto unlock;
306			if (!domain->is_deleted || atomic_read(&domain->users))
307				continue;
308			/*
309			 * Nobody is referring this domain. But somebody may
310			 * refer this domain after successful execve().
311			 * We recheck domain->users after SRCU synchronization.
312			 */
313			if (!tomoyo_add_to_gc(TOMOYO_ID_DOMAIN, &domain->list))
314				goto unlock;
315		}
316	}
317	list_for_each_entry_rcu(ns, &tomoyo_namespace_list, namespace_list) {
318		for (id = 0; id < TOMOYO_MAX_POLICY; id++)
319			if (!tomoyo_collect_member(id, &ns->policy_list[id]))
320				goto unlock;
321		for (i = 0; i < TOMOYO_MAX_ACL_GROUPS; i++)
322			if (!tomoyo_collect_acl(&ns->acl_group[i]))
323				goto unlock;
324		for (i = 0; i < TOMOYO_MAX_GROUP; i++) {
325			struct list_head *list = &ns->group_list[i];
326			struct tomoyo_group *group;
327			switch (i) {
328			case 0:
329				id = TOMOYO_ID_PATH_GROUP;
330				break;
331			default:
332				id = TOMOYO_ID_NUMBER_GROUP;
333				break;
334			}
335			list_for_each_entry(group, list, head.list) {
336				if (!tomoyo_collect_member
337				    (id, &group->member_list))
338					goto unlock;
339				if (!list_empty(&group->member_list) ||
340				    atomic_read(&group->head.users))
341					continue;
342				if (!tomoyo_add_to_gc(TOMOYO_ID_GROUP,
343						      &group->head.list))
344					goto unlock;
345			}
346		}
347	}
348	for (i = 0; i < TOMOYO_MAX_HASH; i++) {
349		struct list_head *list = &tomoyo_name_list[i];
350		struct tomoyo_shared_acl_head *ptr;
351		list_for_each_entry(ptr, list, list) {
352			if (atomic_read(&ptr->users))
353				continue;
354			if (!tomoyo_add_to_gc(TOMOYO_ID_NAME, &ptr->list))
355				goto unlock;
356		}
357	}
358unlock:
359	tomoyo_read_unlock(idx);
360	mutex_unlock(&tomoyo_policy_lock);
361}
362
363static void tomoyo_kfree_entry(void)
364{
365	struct tomoyo_gc *p;
366	struct tomoyo_gc *tmp;
367
368	list_for_each_entry_safe(p, tmp, &tomoyo_gc_queue, list) {
369		struct list_head *element = p->element;
370		switch (p->type) {
371		case TOMOYO_ID_TRANSITION_CONTROL:
372			tomoyo_del_transition_control(element);
373			break;
374		case TOMOYO_ID_AGGREGATOR:
375			tomoyo_del_aggregator(element);
376			break;
377		case TOMOYO_ID_MANAGER:
378			tomoyo_del_manager(element);
379			break;
380		case TOMOYO_ID_NAME:
381			tomoyo_del_name(element);
382			break;
383		case TOMOYO_ID_ACL:
384			tomoyo_del_acl(element);
385			break;
386		case TOMOYO_ID_DOMAIN:
387			if (!tomoyo_del_domain(element))
388				continue;
389			break;
390		case TOMOYO_ID_PATH_GROUP:
391			tomoyo_del_path_group(element);
392			break;
393		case TOMOYO_ID_GROUP:
394			tomoyo_del_group(element);
395			break;
396		case TOMOYO_ID_NUMBER_GROUP:
397			tomoyo_del_number_group(element);
398			break;
399		case TOMOYO_MAX_POLICY:
400			break;
401		}
402		tomoyo_memory_free(element);
403		list_del(&p->list);
404		kfree(p);
405	}
406}
407
408/**
409 * tomoyo_gc_thread - Garbage collector thread function.
410 *
411 * @unused: Unused.
412 *
413 * In case OOM-killer choose this thread for termination, we create this thread
414 * as a short live thread whenever /sys/kernel/security/tomoyo/ interface was
415 * close()d.
416 *
417 * Returns 0.
418 */
419static int tomoyo_gc_thread(void *unused)
420{
421	daemonize("GC for TOMOYO");
422	if (mutex_trylock(&tomoyo_gc_mutex)) {
423		int i;
424		for (i = 0; i < 10; i++) {
425			tomoyo_collect_entry();
426			if (list_empty(&tomoyo_gc_queue))
427				break;
428			synchronize_srcu(&tomoyo_ss);
429			tomoyo_kfree_entry();
430		}
431		mutex_unlock(&tomoyo_gc_mutex);
432	}
433	do_exit(0);
434}
435
436void tomoyo_run_gc(void)
437{
438	struct task_struct *task = kthread_create(tomoyo_gc_thread, NULL,
439						  "GC for TOMOYO");
440	if (!IS_ERR(task))
441		wake_up_process(task);
442}
443