Blame view

security/tomoyo/gc.c 16.6 KB
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
1
2
3
  /*
   * security/tomoyo/gc.c
   *
0f2a55d5b   Tetsuo Handa   TOMOYO: Update ke...
4
   * Copyright (C) 2005-2011  NTT DATA CORPORATION
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
5
6
7
8
   */
  
  #include "common.h"
  #include <linux/kthread.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
9
  #include <linux/slab.h>
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
10

a427fd14d   Tetsuo Handa   TOMOYO: Remove to...
11
12
13
14
15
16
17
18
19
20
21
22
23
24
  /**
   * tomoyo_memory_free - Free memory for elements.
   *
   * @ptr:  Pointer to allocated memory.
   *
   * Returns nothing.
   *
   * Caller holds tomoyo_policy_lock mutex.
   */
  static inline void tomoyo_memory_free(void *ptr)
  {
  	tomoyo_memory_used[TOMOYO_MEMORY_POLICY] -= ksize(ptr);
  	kfree(ptr);
  }
2e503bbb4   Tetsuo Handa   TOMOYO: Fix lockd...
25
26
27
28
  /* The list for "struct tomoyo_io_buffer". */
  static LIST_HEAD(tomoyo_io_buffer_list);
  /* Lock for protecting tomoyo_io_buffer_list. */
  static DEFINE_SPINLOCK(tomoyo_io_buffer_list_lock);
2e503bbb4   Tetsuo Handa   TOMOYO: Fix lockd...
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
  /**
   * tomoyo_struct_used_by_io_buffer - Check whether the list element is used by /sys/kernel/security/tomoyo/ users or not.
   *
   * @element: Pointer to "struct list_head".
   *
   * Returns true if @element is used by /sys/kernel/security/tomoyo/ users,
   * false otherwise.
   */
  static bool tomoyo_struct_used_by_io_buffer(const struct list_head *element)
  {
  	struct tomoyo_io_buffer *head;
  	bool in_use = false;
  
  	spin_lock(&tomoyo_io_buffer_list_lock);
  	list_for_each_entry(head, &tomoyo_io_buffer_list, list) {
  		head->users++;
  		spin_unlock(&tomoyo_io_buffer_list_lock);
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
46
  		mutex_lock(&head->io_sem);
2e503bbb4   Tetsuo Handa   TOMOYO: Fix lockd...
47
48
49
50
  		if (head->r.domain == element || head->r.group == element ||
  		    head->r.acl == element || &head->w.domain->list == element)
  			in_use = true;
  		mutex_unlock(&head->io_sem);
2e503bbb4   Tetsuo Handa   TOMOYO: Fix lockd...
51
52
53
54
55
56
57
58
59
60
61
62
63
  		spin_lock(&tomoyo_io_buffer_list_lock);
  		head->users--;
  		if (in_use)
  			break;
  	}
  	spin_unlock(&tomoyo_io_buffer_list_lock);
  	return in_use;
  }
  
  /**
   * tomoyo_name_used_by_io_buffer - Check whether the string is used by /sys/kernel/security/tomoyo/ users or not.
   *
   * @string: String to check.
2e503bbb4   Tetsuo Handa   TOMOYO: Fix lockd...
64
65
66
67
   *
   * Returns true if @string is used by /sys/kernel/security/tomoyo/ users,
   * false otherwise.
   */
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
68
  static bool tomoyo_name_used_by_io_buffer(const char *string)
2e503bbb4   Tetsuo Handa   TOMOYO: Fix lockd...
69
70
  {
  	struct tomoyo_io_buffer *head;
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
71
  	const size_t size = strlen(string) + 1;
2e503bbb4   Tetsuo Handa   TOMOYO: Fix lockd...
72
73
74
75
76
77
78
  	bool in_use = false;
  
  	spin_lock(&tomoyo_io_buffer_list_lock);
  	list_for_each_entry(head, &tomoyo_io_buffer_list, list) {
  		int i;
  		head->users++;
  		spin_unlock(&tomoyo_io_buffer_list_lock);
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
79
  		mutex_lock(&head->io_sem);
2e503bbb4   Tetsuo Handa   TOMOYO: Fix lockd...
80
81
82
83
84
85
86
87
  		for (i = 0; i < TOMOYO_MAX_IO_READ_QUEUE; i++) {
  			const char *w = head->r.w[i];
  			if (w < string || w > string + size)
  				continue;
  			in_use = true;
  			break;
  		}
  		mutex_unlock(&head->io_sem);
2e503bbb4   Tetsuo Handa   TOMOYO: Fix lockd...
88
89
90
91
92
93
94
95
  		spin_lock(&tomoyo_io_buffer_list_lock);
  		head->users--;
  		if (in_use)
  			break;
  	}
  	spin_unlock(&tomoyo_io_buffer_list_lock);
  	return in_use;
  }
0df7e8b8f   Tetsuo Handa   TOMOYO: Cleanup p...
96
97
98
99
100
101
102
  /**
   * tomoyo_del_transition_control - Delete members in "struct tomoyo_transition_control".
   *
   * @element: Pointer to "struct list_head".
   *
   * Returns nothing.
   */
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
103
  static inline void tomoyo_del_transition_control(struct list_head *element)
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
104
  {
5448ec4f5   Tetsuo Handa   TOMOYO: Use commo...
105
  	struct tomoyo_transition_control *ptr =
e79acf0ef   Tetsuo Handa   TOMOYO: Pass "str...
106
  		container_of(element, typeof(*ptr), head.list);
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
107
108
109
  	tomoyo_put_name(ptr->domainname);
  	tomoyo_put_name(ptr->program);
  }
0df7e8b8f   Tetsuo Handa   TOMOYO: Cleanup p...
110
111
112
113
114
115
116
  /**
   * tomoyo_del_aggregator - Delete members in "struct tomoyo_aggregator".
   *
   * @element: Pointer to "struct list_head".
   *
   * Returns nothing.
   */
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
117
  static inline void tomoyo_del_aggregator(struct list_head *element)
1084307ca   Tetsuo Handa   TOMOYO: Add pathn...
118
  {
e2bf69077   Tetsuo Handa   TOMOYO: Rename sy...
119
  	struct tomoyo_aggregator *ptr =
e79acf0ef   Tetsuo Handa   TOMOYO: Pass "str...
120
  		container_of(element, typeof(*ptr), head.list);
1084307ca   Tetsuo Handa   TOMOYO: Add pathn...
121
122
123
  	tomoyo_put_name(ptr->original_name);
  	tomoyo_put_name(ptr->aggregated_name);
  }
0df7e8b8f   Tetsuo Handa   TOMOYO: Cleanup p...
124
125
126
127
128
129
130
  /**
   * tomoyo_del_manager - Delete members in "struct tomoyo_manager".
   *
   * @element: Pointer to "struct list_head".
   *
   * Returns nothing.
   */
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
131
  static inline void tomoyo_del_manager(struct list_head *element)
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
132
  {
e2bf69077   Tetsuo Handa   TOMOYO: Rename sy...
133
  	struct tomoyo_manager *ptr =
e79acf0ef   Tetsuo Handa   TOMOYO: Pass "str...
134
  		container_of(element, typeof(*ptr), head.list);
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
135
136
  	tomoyo_put_name(ptr->manager);
  }
0df7e8b8f   Tetsuo Handa   TOMOYO: Cleanup p...
137
138
139
140
141
142
143
  /**
   * tomoyo_del_acl - Delete members in "struct tomoyo_acl_info".
   *
   * @element: Pointer to "struct list_head".
   *
   * Returns nothing.
   */
e79acf0ef   Tetsuo Handa   TOMOYO: Pass "str...
144
  static void tomoyo_del_acl(struct list_head *element)
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
145
  {
e79acf0ef   Tetsuo Handa   TOMOYO: Pass "str...
146
147
  	struct tomoyo_acl_info *acl =
  		container_of(element, typeof(*acl), list);
2066a3612   Tetsuo Handa   TOMOYO: Allow usi...
148
  	tomoyo_put_condition(acl->cond);
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
149
  	switch (acl->type) {
7ef612331   Tetsuo Handa   TOMOYO: Use short...
150
  	case TOMOYO_TYPE_PATH_ACL:
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
151
  		{
7ef612331   Tetsuo Handa   TOMOYO: Use short...
152
  			struct tomoyo_path_acl *entry
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
153
  				= container_of(acl, typeof(*entry), head);
7762fbfff   Tetsuo Handa   TOMOYO: Add pathn...
154
  			tomoyo_put_name_union(&entry->name);
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
155
156
  		}
  		break;
7ef612331   Tetsuo Handa   TOMOYO: Use short...
157
  	case TOMOYO_TYPE_PATH2_ACL:
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
158
  		{
7ef612331   Tetsuo Handa   TOMOYO: Use short...
159
  			struct tomoyo_path2_acl *entry
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
160
  				= container_of(acl, typeof(*entry), head);
7762fbfff   Tetsuo Handa   TOMOYO: Add pathn...
161
162
  			tomoyo_put_name_union(&entry->name1);
  			tomoyo_put_name_union(&entry->name2);
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
163
164
  		}
  		break;
a1f9bb6a3   Tetsuo Handa   TOMOYO: Split fil...
165
166
167
168
169
170
171
172
  	case TOMOYO_TYPE_PATH_NUMBER_ACL:
  		{
  			struct tomoyo_path_number_acl *entry
  				= container_of(acl, typeof(*entry), head);
  			tomoyo_put_name_union(&entry->name);
  			tomoyo_put_number_union(&entry->number);
  		}
  		break;
75093152a   Tetsuo Handa   TOMOYO: Rename sy...
173
  	case TOMOYO_TYPE_MKDEV_ACL:
a1f9bb6a3   Tetsuo Handa   TOMOYO: Split fil...
174
  		{
75093152a   Tetsuo Handa   TOMOYO: Rename sy...
175
  			struct tomoyo_mkdev_acl *entry
a1f9bb6a3   Tetsuo Handa   TOMOYO: Split fil...
176
177
178
179
180
181
182
  				= container_of(acl, typeof(*entry), head);
  			tomoyo_put_name_union(&entry->name);
  			tomoyo_put_number_union(&entry->mode);
  			tomoyo_put_number_union(&entry->major);
  			tomoyo_put_number_union(&entry->minor);
  		}
  		break;
2106ccd97   Tetsuo Handa   TOMOYO: Add mount...
183
184
185
186
187
188
189
190
191
192
  	case TOMOYO_TYPE_MOUNT_ACL:
  		{
  			struct tomoyo_mount_acl *entry
  				= container_of(acl, typeof(*entry), head);
  			tomoyo_put_name_union(&entry->dev_name);
  			tomoyo_put_name_union(&entry->dir_name);
  			tomoyo_put_name_union(&entry->fs_type);
  			tomoyo_put_number_union(&entry->flags);
  		}
  		break;
d58e0da85   Tetsuo Handa   TOMOYO: Add envir...
193
194
195
196
197
198
199
200
  	case TOMOYO_TYPE_ENV_ACL:
  		{
  			struct tomoyo_env_acl *entry =
  				container_of(acl, typeof(*entry), head);
  
  			tomoyo_put_name(entry->env);
  		}
  		break;
059d84dbb   Tetsuo Handa   TOMOYO: Add socke...
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
  	case TOMOYO_TYPE_INET_ACL:
  		{
  			struct tomoyo_inet_acl *entry =
  				container_of(acl, typeof(*entry), head);
  
  			tomoyo_put_group(entry->address.group);
  			tomoyo_put_number_union(&entry->port);
  		}
  		break;
  	case TOMOYO_TYPE_UNIX_ACL:
  		{
  			struct tomoyo_unix_acl *entry =
  				container_of(acl, typeof(*entry), head);
  
  			tomoyo_put_name_union(&entry->name);
  		}
  		break;
545a72603   Tetsuo Handa   TOMOYO: Fix quota...
218
219
220
221
222
223
224
  	case TOMOYO_TYPE_MANUAL_TASK_ACL:
  		{
  			struct tomoyo_task_acl *entry =
  				container_of(acl, typeof(*entry), head);
  			tomoyo_put_name(entry->domainname);
  		}
  		break;
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
225
226
  	}
  }
2e503bbb4   Tetsuo Handa   TOMOYO: Fix lockd...
227
228
229
230
231
  /**
   * tomoyo_del_domain - Delete members in "struct tomoyo_domain_info".
   *
   * @element: Pointer to "struct list_head".
   *
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
232
   * Returns nothing.
a427fd14d   Tetsuo Handa   TOMOYO: Remove to...
233
234
   *
   * Caller holds tomoyo_policy_lock mutex.
2e503bbb4   Tetsuo Handa   TOMOYO: Fix lockd...
235
   */
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
236
  static inline void tomoyo_del_domain(struct list_head *element)
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
237
  {
e79acf0ef   Tetsuo Handa   TOMOYO: Pass "str...
238
239
  	struct tomoyo_domain_info *domain =
  		container_of(element, typeof(*domain), list);
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
240
241
242
  	struct tomoyo_acl_info *acl;
  	struct tomoyo_acl_info *tmp;
  	/*
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
243
244
245
  	 * Since this domain is referenced from neither
  	 * "struct tomoyo_io_buffer" nor "struct cred"->security, we can delete
  	 * elements without checking for is_deleted flag.
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
246
  	 */
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
247
  	list_for_each_entry_safe(acl, tmp, &domain->acl_info_list, list) {
e79acf0ef   Tetsuo Handa   TOMOYO: Pass "str...
248
  		tomoyo_del_acl(&acl->list);
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
249
250
251
  		tomoyo_memory_free(acl);
  	}
  	tomoyo_put_name(domain->domainname);
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
252
  }
2066a3612   Tetsuo Handa   TOMOYO: Allow usi...
253
254
255
256
257
258
259
260
261
262
263
264
265
  /**
   * tomoyo_del_condition - Delete members in "struct tomoyo_condition".
   *
   * @element: Pointer to "struct list_head".
   *
   * Returns nothing.
   */
  void tomoyo_del_condition(struct list_head *element)
  {
  	struct tomoyo_condition *cond = container_of(element, typeof(*cond),
  						     head.list);
  	const u16 condc = cond->condc;
  	const u16 numbers_count = cond->numbers_count;
2ca9bf453   Tetsuo Handa   TOMOYO: Allow usi...
266
  	const u16 names_count = cond->names_count;
5b636857f   Tetsuo Handa   TOMOYO: Allow usi...
267
268
  	const u16 argc = cond->argc;
  	const u16 envc = cond->envc;
2066a3612   Tetsuo Handa   TOMOYO: Allow usi...
269
270
271
272
273
  	unsigned int i;
  	const struct tomoyo_condition_element *condp
  		= (const struct tomoyo_condition_element *) (cond + 1);
  	struct tomoyo_number_union *numbers_p
  		= (struct tomoyo_number_union *) (condp + condc);
2ca9bf453   Tetsuo Handa   TOMOYO: Allow usi...
274
275
  	struct tomoyo_name_union *names_p
  		= (struct tomoyo_name_union *) (numbers_p + numbers_count);
5b636857f   Tetsuo Handa   TOMOYO: Allow usi...
276
277
278
279
  	const struct tomoyo_argv *argv
  		= (const struct tomoyo_argv *) (names_p + names_count);
  	const struct tomoyo_envp *envp
  		= (const struct tomoyo_envp *) (argv + argc);
2066a3612   Tetsuo Handa   TOMOYO: Allow usi...
280
281
  	for (i = 0; i < numbers_count; i++)
  		tomoyo_put_number_union(numbers_p++);
2ca9bf453   Tetsuo Handa   TOMOYO: Allow usi...
282
283
  	for (i = 0; i < names_count; i++)
  		tomoyo_put_name_union(names_p++);
5b636857f   Tetsuo Handa   TOMOYO: Allow usi...
284
285
286
287
288
289
  	for (i = 0; i < argc; argv++, i++)
  		tomoyo_put_name(argv->value);
  	for (i = 0; i < envc; envp++, i++) {
  		tomoyo_put_name(envp->name);
  		tomoyo_put_name(envp->value);
  	}
2066a3612   Tetsuo Handa   TOMOYO: Allow usi...
290
  }
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
291

0df7e8b8f   Tetsuo Handa   TOMOYO: Cleanup p...
292
293
294
295
296
297
298
  /**
   * tomoyo_del_name - Delete members in "struct tomoyo_name".
   *
   * @element: Pointer to "struct list_head".
   *
   * Returns nothing.
   */
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
299
  static inline void tomoyo_del_name(struct list_head *element)
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
300
  {
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
301
  	/* Nothing to do. */
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
302
  }
0df7e8b8f   Tetsuo Handa   TOMOYO: Cleanup p...
303
304
305
306
307
308
309
  /**
   * tomoyo_del_path_group - Delete members in "struct tomoyo_path_group".
   *
   * @element: Pointer to "struct list_head".
   *
   * Returns nothing.
   */
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
310
  static inline void tomoyo_del_path_group(struct list_head *element)
7762fbfff   Tetsuo Handa   TOMOYO: Add pathn...
311
  {
a98aa4deb   Tetsuo Handa   TOMOYO: Merge tom...
312
  	struct tomoyo_path_group *member =
e79acf0ef   Tetsuo Handa   TOMOYO: Pass "str...
313
  		container_of(element, typeof(*member), head.list);
7762fbfff   Tetsuo Handa   TOMOYO: Add pathn...
314
315
  	tomoyo_put_name(member->member_name);
  }
0df7e8b8f   Tetsuo Handa   TOMOYO: Cleanup p...
316
317
318
319
320
321
322
  /**
   * tomoyo_del_group - Delete "struct tomoyo_group".
   *
   * @element: Pointer to "struct list_head".
   *
   * Returns nothing.
   */
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
323
  static inline void tomoyo_del_group(struct list_head *element)
7762fbfff   Tetsuo Handa   TOMOYO: Add pathn...
324
  {
a98aa4deb   Tetsuo Handa   TOMOYO: Merge tom...
325
  	struct tomoyo_group *group =
0df7e8b8f   Tetsuo Handa   TOMOYO: Cleanup p...
326
  		container_of(element, typeof(*group), head.list);
7762fbfff   Tetsuo Handa   TOMOYO: Add pathn...
327
328
  	tomoyo_put_name(group->group_name);
  }
0df7e8b8f   Tetsuo Handa   TOMOYO: Cleanup p...
329
  /**
059d84dbb   Tetsuo Handa   TOMOYO: Add socke...
330
331
332
333
334
335
336
337
338
339
340
341
   * tomoyo_del_address_group - Delete members in "struct tomoyo_address_group".
   *
   * @element: Pointer to "struct list_head".
   *
   * Returns nothing.
   */
  static inline void tomoyo_del_address_group(struct list_head *element)
  {
  	/* Nothing to do. */
  }
  
  /**
0df7e8b8f   Tetsuo Handa   TOMOYO: Cleanup p...
342
343
344
345
346
347
   * tomoyo_del_number_group - Delete members in "struct tomoyo_number_group".
   *
   * @element: Pointer to "struct list_head".
   *
   * Returns nothing.
   */
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
348
  static inline void tomoyo_del_number_group(struct list_head *element)
4c3e9e2de   Tetsuo Handa   TOMOYO: Add numer...
349
  {
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
  	/* Nothing to do. */
  }
  
  /**
   * tomoyo_try_to_gc - Try to kfree() an entry.
   *
   * @type:    One of values in "enum tomoyo_policy_id".
   * @element: Pointer to "struct list_head".
   *
   * Returns nothing.
   *
   * Caller holds tomoyo_policy_lock mutex.
   */
  static void tomoyo_try_to_gc(const enum tomoyo_policy_id type,
  			     struct list_head *element)
  {
  	/*
  	 * __list_del_entry() guarantees that the list element became no longer
  	 * reachable from the list which the element was originally on (e.g.
  	 * tomoyo_domain_list). Also, synchronize_srcu() guarantees that the
  	 * list element became no longer referenced by syscall users.
  	 */
  	__list_del_entry(element);
  	mutex_unlock(&tomoyo_policy_lock);
  	synchronize_srcu(&tomoyo_ss);
  	/*
  	 * However, there are two users which may still be using the list
  	 * element. We need to defer until both users forget this element.
  	 *
  	 * Don't kfree() until "struct tomoyo_io_buffer"->r.{domain,group,acl}
  	 * and "struct tomoyo_io_buffer"->w.domain forget this element.
  	 */
  	if (tomoyo_struct_used_by_io_buffer(element))
  		goto reinject;
  	switch (type) {
  	case TOMOYO_ID_TRANSITION_CONTROL:
  		tomoyo_del_transition_control(element);
  		break;
  	case TOMOYO_ID_MANAGER:
  		tomoyo_del_manager(element);
  		break;
  	case TOMOYO_ID_AGGREGATOR:
  		tomoyo_del_aggregator(element);
  		break;
  	case TOMOYO_ID_GROUP:
  		tomoyo_del_group(element);
  		break;
  	case TOMOYO_ID_PATH_GROUP:
  		tomoyo_del_path_group(element);
  		break;
  	case TOMOYO_ID_ADDRESS_GROUP:
  		tomoyo_del_address_group(element);
  		break;
  	case TOMOYO_ID_NUMBER_GROUP:
  		tomoyo_del_number_group(element);
  		break;
  	case TOMOYO_ID_CONDITION:
  		tomoyo_del_condition(element);
  		break;
  	case TOMOYO_ID_NAME:
  		/*
  		 * Don't kfree() until all "struct tomoyo_io_buffer"->r.w[]
  		 * forget this element.
  		 */
  		if (tomoyo_name_used_by_io_buffer
  		    (container_of(element, typeof(struct tomoyo_name),
  				  head.list)->entry.name))
  			goto reinject;
  		tomoyo_del_name(element);
  		break;
  	case TOMOYO_ID_ACL:
  		tomoyo_del_acl(element);
  		break;
  	case TOMOYO_ID_DOMAIN:
  		/*
  		 * Don't kfree() until all "struct cred"->security forget this
  		 * element.
  		 */
  		if (atomic_read(&container_of
  				(element, typeof(struct tomoyo_domain_info),
  				 list)->users))
  			goto reinject;
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
432
433
434
435
436
  		break;
  	case TOMOYO_MAX_POLICY:
  		break;
  	}
  	mutex_lock(&tomoyo_policy_lock);
a427fd14d   Tetsuo Handa   TOMOYO: Remove to...
437
438
  	if (type == TOMOYO_ID_DOMAIN)
  		tomoyo_del_domain(element);
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
439
440
441
442
443
444
445
446
447
448
449
450
451
  	tomoyo_memory_free(element);
  	return;
  reinject:
  	/*
  	 * We can safely reinject this element here bacause
  	 * (1) Appending list elements and removing list elements are protected
  	 *     by tomoyo_policy_lock mutex.
  	 * (2) Only this function removes list elements and this function is
  	 *     exclusively executed by tomoyo_gc_mutex mutex.
  	 * are true.
  	 */
  	mutex_lock(&tomoyo_policy_lock);
  	list_add_rcu(element, element->prev);
4c3e9e2de   Tetsuo Handa   TOMOYO: Add numer...
452
  }
0df7e8b8f   Tetsuo Handa   TOMOYO: Cleanup p...
453
454
455
456
457
458
  /**
   * tomoyo_collect_member - Delete elements with "struct tomoyo_acl_head".
   *
   * @id:          One of values in "enum tomoyo_policy_id".
   * @member_list: Pointer to "struct list_head".
   *
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
459
   * Returns nothing.
0df7e8b8f   Tetsuo Handa   TOMOYO: Cleanup p...
460
   */
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
461
  static void tomoyo_collect_member(const enum tomoyo_policy_id id,
0df7e8b8f   Tetsuo Handa   TOMOYO: Cleanup p...
462
  				  struct list_head *member_list)
d2f8b2348   Tetsuo Handa   TOMOYO: Use commo...
463
464
  {
  	struct tomoyo_acl_head *member;
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
465
466
  	struct tomoyo_acl_head *tmp;
  	list_for_each_entry_safe(member, tmp, member_list, list) {
d2f8b2348   Tetsuo Handa   TOMOYO: Use commo...
467
468
  		if (!member->is_deleted)
  			continue;
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
469
470
  		member->is_deleted = TOMOYO_GC_IN_PROGRESS;
  		tomoyo_try_to_gc(id, &member->list);
d2f8b2348   Tetsuo Handa   TOMOYO: Use commo...
471
  	}
d2f8b2348   Tetsuo Handa   TOMOYO: Use commo...
472
  }
32997144f   Tetsuo Handa   TOMOYO: Add ACL g...
473
474
475
476
477
  /**
   * tomoyo_collect_acl - Delete elements in "struct tomoyo_domain_info".
   *
   * @list: Pointer to "struct list_head".
   *
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
478
   * Returns nothing.
32997144f   Tetsuo Handa   TOMOYO: Add ACL g...
479
   */
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
480
  static void tomoyo_collect_acl(struct list_head *list)
d2f8b2348   Tetsuo Handa   TOMOYO: Use commo...
481
482
  {
  	struct tomoyo_acl_info *acl;
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
483
484
  	struct tomoyo_acl_info *tmp;
  	list_for_each_entry_safe(acl, tmp, list, list) {
d2f8b2348   Tetsuo Handa   TOMOYO: Use commo...
485
486
  		if (!acl->is_deleted)
  			continue;
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
487
488
  		acl->is_deleted = TOMOYO_GC_IN_PROGRESS;
  		tomoyo_try_to_gc(TOMOYO_ID_ACL, &acl->list);
d2f8b2348   Tetsuo Handa   TOMOYO: Use commo...
489
  	}
d2f8b2348   Tetsuo Handa   TOMOYO: Use commo...
490
  }
0df7e8b8f   Tetsuo Handa   TOMOYO: Cleanup p...
491
  /**
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
492
   * tomoyo_collect_entry - Try to kfree() deleted elements.
0df7e8b8f   Tetsuo Handa   TOMOYO: Cleanup p...
493
494
495
   *
   * Returns nothing.
   */
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
496
497
  static void tomoyo_collect_entry(void)
  {
d2f8b2348   Tetsuo Handa   TOMOYO: Use commo...
498
  	int i;
bd03a3e4c   Tetsuo Handa   TOMOYO: Add polic...
499
500
  	enum tomoyo_policy_id id;
  	struct tomoyo_policy_namespace *ns;
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
501
  	mutex_lock(&tomoyo_policy_lock);
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
502
503
  	{
  		struct tomoyo_domain_info *domain;
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
504
505
506
507
  		struct tomoyo_domain_info *tmp;
  		list_for_each_entry_safe(domain, tmp, &tomoyo_domain_list,
  					 list) {
  			tomoyo_collect_acl(&domain->acl_info_list);
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
508
509
  			if (!domain->is_deleted || atomic_read(&domain->users))
  				continue;
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
510
  			tomoyo_try_to_gc(TOMOYO_ID_DOMAIN, &domain->list);
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
511
512
  		}
  	}
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
513
  	list_for_each_entry(ns, &tomoyo_namespace_list, namespace_list) {
bd03a3e4c   Tetsuo Handa   TOMOYO: Add polic...
514
  		for (id = 0; id < TOMOYO_MAX_POLICY; id++)
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
515
  			tomoyo_collect_member(id, &ns->policy_list[id]);
bd03a3e4c   Tetsuo Handa   TOMOYO: Add polic...
516
  		for (i = 0; i < TOMOYO_MAX_ACL_GROUPS; i++)
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
517
518
519
520
521
522
523
524
525
526
527
528
529
530
  			tomoyo_collect_acl(&ns->acl_group[i]);
  	}
  	{
  		struct tomoyo_shared_acl_head *ptr;
  		struct tomoyo_shared_acl_head *tmp;
  		list_for_each_entry_safe(ptr, tmp, &tomoyo_condition_list,
  					 list) {
  			if (atomic_read(&ptr->users) > 0)
  				continue;
  			atomic_set(&ptr->users, TOMOYO_GC_IN_PROGRESS);
  			tomoyo_try_to_gc(TOMOYO_ID_CONDITION, &ptr->list);
  		}
  	}
  	list_for_each_entry(ns, &tomoyo_namespace_list, namespace_list) {
bd03a3e4c   Tetsuo Handa   TOMOYO: Add polic...
531
532
533
  		for (i = 0; i < TOMOYO_MAX_GROUP; i++) {
  			struct list_head *list = &ns->group_list[i];
  			struct tomoyo_group *group;
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
534
  			struct tomoyo_group *tmp;
bd03a3e4c   Tetsuo Handa   TOMOYO: Add polic...
535
536
537
538
  			switch (i) {
  			case 0:
  				id = TOMOYO_ID_PATH_GROUP;
  				break;
059d84dbb   Tetsuo Handa   TOMOYO: Add socke...
539
  			case 1:
bd03a3e4c   Tetsuo Handa   TOMOYO: Add polic...
540
541
  				id = TOMOYO_ID_NUMBER_GROUP;
  				break;
059d84dbb   Tetsuo Handa   TOMOYO: Add socke...
542
543
544
  			default:
  				id = TOMOYO_ID_ADDRESS_GROUP;
  				break;
bd03a3e4c   Tetsuo Handa   TOMOYO: Add polic...
545
  			}
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
546
547
  			list_for_each_entry_safe(group, tmp, list, head.list) {
  				tomoyo_collect_member(id, &group->member_list);
bd03a3e4c   Tetsuo Handa   TOMOYO: Add polic...
548
  				if (!list_empty(&group->member_list) ||
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
549
  				    atomic_read(&group->head.users) > 0)
bd03a3e4c   Tetsuo Handa   TOMOYO: Add polic...
550
  					continue;
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
551
552
553
554
  				atomic_set(&group->head.users,
  					   TOMOYO_GC_IN_PROGRESS);
  				tomoyo_try_to_gc(TOMOYO_ID_GROUP,
  						 &group->head.list);
bd03a3e4c   Tetsuo Handa   TOMOYO: Add polic...
555
  			}
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
556
557
  		}
  	}
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
558
559
  	for (i = 0; i < TOMOYO_MAX_HASH; i++) {
  		struct list_head *list = &tomoyo_name_list[i];
bd03a3e4c   Tetsuo Handa   TOMOYO: Add polic...
560
  		struct tomoyo_shared_acl_head *ptr;
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
561
562
563
  		struct tomoyo_shared_acl_head *tmp;
  		list_for_each_entry_safe(ptr, tmp, list, list) {
  			if (atomic_read(&ptr->users) > 0)
4c3e9e2de   Tetsuo Handa   TOMOYO: Add numer...
564
  				continue;
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
565
566
  			atomic_set(&ptr->users, TOMOYO_GC_IN_PROGRESS);
  			tomoyo_try_to_gc(TOMOYO_ID_NAME, &ptr->list);
4c3e9e2de   Tetsuo Handa   TOMOYO: Add numer...
567
568
  		}
  	}
292823814   Tetsuo Handa   TOMOYO: Use mutex...
569
  	mutex_unlock(&tomoyo_policy_lock);
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
570
  }
2e503bbb4   Tetsuo Handa   TOMOYO: Fix lockd...
571
  /**
0df7e8b8f   Tetsuo Handa   TOMOYO: Cleanup p...
572
573
574
575
   * tomoyo_gc_thread - Garbage collector thread function.
   *
   * @unused: Unused.
   *
0df7e8b8f   Tetsuo Handa   TOMOYO: Cleanup p...
576
577
   * Returns 0.
   */
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
578
579
  static int tomoyo_gc_thread(void *unused)
  {
2e503bbb4   Tetsuo Handa   TOMOYO: Fix lockd...
580
581
582
583
  	/* Garbage collector thread is exclusive. */
  	static DEFINE_MUTEX(tomoyo_gc_mutex);
  	if (!mutex_trylock(&tomoyo_gc_mutex))
  		goto out;
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
584
  	tomoyo_collect_entry();
2e503bbb4   Tetsuo Handa   TOMOYO: Fix lockd...
585
586
587
588
589
590
591
592
593
594
595
596
597
  	{
  		struct tomoyo_io_buffer *head;
  		struct tomoyo_io_buffer *tmp;
  
  		spin_lock(&tomoyo_io_buffer_list_lock);
  		list_for_each_entry_safe(head, tmp, &tomoyo_io_buffer_list,
  					 list) {
  			if (head->users)
  				continue;
  			list_del(&head->list);
  			kfree(head->read_buf);
  			kfree(head->write_buf);
  			kfree(head);
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
598
  		}
2e503bbb4   Tetsuo Handa   TOMOYO: Fix lockd...
599
  		spin_unlock(&tomoyo_io_buffer_list_lock);
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
600
  	}
2e503bbb4   Tetsuo Handa   TOMOYO: Fix lockd...
601
602
603
604
  	mutex_unlock(&tomoyo_gc_mutex);
  out:
  	/* This acts as do_exit(0). */
  	return 0;
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
605
  }
2e503bbb4   Tetsuo Handa   TOMOYO: Fix lockd...
606
607
608
609
610
611
612
613
614
  /**
   * tomoyo_notify_gc - Register/unregister /sys/kernel/security/tomoyo/ users.
   *
   * @head:        Pointer to "struct tomoyo_io_buffer".
   * @is_register: True if register, false if unregister.
   *
   * Returns nothing.
   */
  void tomoyo_notify_gc(struct tomoyo_io_buffer *head, const bool is_register)
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
615
  {
2e503bbb4   Tetsuo Handa   TOMOYO: Fix lockd...
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
  	bool is_write = false;
  
  	spin_lock(&tomoyo_io_buffer_list_lock);
  	if (is_register) {
  		head->users = 1;
  		list_add(&head->list, &tomoyo_io_buffer_list);
  	} else {
  		is_write = head->write_buf != NULL;
  		if (!--head->users) {
  			list_del(&head->list);
  			kfree(head->read_buf);
  			kfree(head->write_buf);
  			kfree(head);
  		}
  	}
  	spin_unlock(&tomoyo_io_buffer_list_lock);
40d273782   Mike Danese   security: tomoyo:...
632
633
  	if (is_write)
  		kthread_run(tomoyo_gc_thread, NULL, "GC for TOMOYO");
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
634
  }