Blame view

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

a427fd14d   Tetsuo Handa   TOMOYO: Remove to...
12
13
14
15
16
17
18
19
20
21
22
23
24
25
  /**
   * 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...
26
27
28
29
  /* 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...
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
  /**
   * 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 ...
47
  		mutex_lock(&head->io_sem);
2e503bbb4   Tetsuo Handa   TOMOYO: Fix lockd...
48
49
50
51
  		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...
52
53
54
55
56
57
58
59
60
61
62
63
64
  		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...
65
66
67
68
   *
   * Returns true if @string is used by /sys/kernel/security/tomoyo/ users,
   * false otherwise.
   */
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
69
  static bool tomoyo_name_used_by_io_buffer(const char *string)
2e503bbb4   Tetsuo Handa   TOMOYO: Fix lockd...
70
71
  {
  	struct tomoyo_io_buffer *head;
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
72
  	const size_t size = strlen(string) + 1;
2e503bbb4   Tetsuo Handa   TOMOYO: Fix lockd...
73
74
75
76
77
  	bool in_use = false;
  
  	spin_lock(&tomoyo_io_buffer_list_lock);
  	list_for_each_entry(head, &tomoyo_io_buffer_list, list) {
  		int i;
cdcf6723a   Tetsuo Handa   tomoyo: Coding st...
78

2e503bbb4   Tetsuo Handa   TOMOYO: Fix lockd...
79
80
  		head->users++;
  		spin_unlock(&tomoyo_io_buffer_list_lock);
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
81
  		mutex_lock(&head->io_sem);
2e503bbb4   Tetsuo Handa   TOMOYO: Fix lockd...
82
83
  		for (i = 0; i < TOMOYO_MAX_IO_READ_QUEUE; i++) {
  			const char *w = head->r.w[i];
cdcf6723a   Tetsuo Handa   tomoyo: Coding st...
84

2e503bbb4   Tetsuo Handa   TOMOYO: Fix lockd...
85
86
87
88
89
90
  			if (w < string || w > string + size)
  				continue;
  			in_use = true;
  			break;
  		}
  		mutex_unlock(&head->io_sem);
2e503bbb4   Tetsuo Handa   TOMOYO: Fix lockd...
91
92
93
94
95
96
97
98
  		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...
99
100
101
102
103
104
105
  /**
   * tomoyo_del_transition_control - Delete members in "struct tomoyo_transition_control".
   *
   * @element: Pointer to "struct list_head".
   *
   * Returns nothing.
   */
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
106
  static inline void tomoyo_del_transition_control(struct list_head *element)
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
107
  {
5448ec4f5   Tetsuo Handa   TOMOYO: Use commo...
108
  	struct tomoyo_transition_control *ptr =
e79acf0ef   Tetsuo Handa   TOMOYO: Pass "str...
109
  		container_of(element, typeof(*ptr), head.list);
cdcf6723a   Tetsuo Handa   tomoyo: Coding st...
110

847b173ea   Tetsuo Handa   TOMOYO: Add garba...
111
112
113
  	tomoyo_put_name(ptr->domainname);
  	tomoyo_put_name(ptr->program);
  }
0df7e8b8f   Tetsuo Handa   TOMOYO: Cleanup p...
114
115
116
117
118
119
120
  /**
   * tomoyo_del_aggregator - Delete members in "struct tomoyo_aggregator".
   *
   * @element: Pointer to "struct list_head".
   *
   * Returns nothing.
   */
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
121
  static inline void tomoyo_del_aggregator(struct list_head *element)
1084307ca   Tetsuo Handa   TOMOYO: Add pathn...
122
  {
e2bf69077   Tetsuo Handa   TOMOYO: Rename sy...
123
  	struct tomoyo_aggregator *ptr =
e79acf0ef   Tetsuo Handa   TOMOYO: Pass "str...
124
  		container_of(element, typeof(*ptr), head.list);
cdcf6723a   Tetsuo Handa   tomoyo: Coding st...
125

1084307ca   Tetsuo Handa   TOMOYO: Add pathn...
126
127
128
  	tomoyo_put_name(ptr->original_name);
  	tomoyo_put_name(ptr->aggregated_name);
  }
0df7e8b8f   Tetsuo Handa   TOMOYO: Cleanup p...
129
130
131
132
133
134
135
  /**
   * tomoyo_del_manager - Delete members in "struct tomoyo_manager".
   *
   * @element: Pointer to "struct list_head".
   *
   * Returns nothing.
   */
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
136
  static inline void tomoyo_del_manager(struct list_head *element)
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
137
  {
e2bf69077   Tetsuo Handa   TOMOYO: Rename sy...
138
  	struct tomoyo_manager *ptr =
e79acf0ef   Tetsuo Handa   TOMOYO: Pass "str...
139
  		container_of(element, typeof(*ptr), head.list);
cdcf6723a   Tetsuo Handa   tomoyo: Coding st...
140

847b173ea   Tetsuo Handa   TOMOYO: Add garba...
141
142
  	tomoyo_put_name(ptr->manager);
  }
0df7e8b8f   Tetsuo Handa   TOMOYO: Cleanup p...
143
144
145
146
147
148
149
  /**
   * tomoyo_del_acl - Delete members in "struct tomoyo_acl_info".
   *
   * @element: Pointer to "struct list_head".
   *
   * Returns nothing.
   */
e79acf0ef   Tetsuo Handa   TOMOYO: Pass "str...
150
  static void tomoyo_del_acl(struct list_head *element)
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
151
  {
e79acf0ef   Tetsuo Handa   TOMOYO: Pass "str...
152
153
  	struct tomoyo_acl_info *acl =
  		container_of(element, typeof(*acl), list);
cdcf6723a   Tetsuo Handa   tomoyo: Coding st...
154

2066a3612   Tetsuo Handa   TOMOYO: Allow usi...
155
  	tomoyo_put_condition(acl->cond);
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
156
  	switch (acl->type) {
7ef612331   Tetsuo Handa   TOMOYO: Use short...
157
  	case TOMOYO_TYPE_PATH_ACL:
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
158
  		{
7ef612331   Tetsuo Handa   TOMOYO: Use short...
159
  			struct tomoyo_path_acl *entry
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
160
  				= container_of(acl, typeof(*entry), head);
7762fbfff   Tetsuo Handa   TOMOYO: Add pathn...
161
  			tomoyo_put_name_union(&entry->name);
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
162
163
  		}
  		break;
7ef612331   Tetsuo Handa   TOMOYO: Use short...
164
  	case TOMOYO_TYPE_PATH2_ACL:
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
165
  		{
7ef612331   Tetsuo Handa   TOMOYO: Use short...
166
  			struct tomoyo_path2_acl *entry
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
167
  				= container_of(acl, typeof(*entry), head);
7762fbfff   Tetsuo Handa   TOMOYO: Add pathn...
168
169
  			tomoyo_put_name_union(&entry->name1);
  			tomoyo_put_name_union(&entry->name2);
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
170
171
  		}
  		break;
a1f9bb6a3   Tetsuo Handa   TOMOYO: Split fil...
172
173
174
175
176
177
178
179
  	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...
180
  	case TOMOYO_TYPE_MKDEV_ACL:
a1f9bb6a3   Tetsuo Handa   TOMOYO: Split fil...
181
  		{
75093152a   Tetsuo Handa   TOMOYO: Rename sy...
182
  			struct tomoyo_mkdev_acl *entry
a1f9bb6a3   Tetsuo Handa   TOMOYO: Split fil...
183
184
185
186
187
188
189
  				= 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...
190
191
192
193
194
195
196
197
198
199
  	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...
200
201
202
203
204
205
206
207
  	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...
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
  	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...
225
226
227
228
  	case TOMOYO_TYPE_MANUAL_TASK_ACL:
  		{
  			struct tomoyo_task_acl *entry =
  				container_of(acl, typeof(*entry), head);
cdcf6723a   Tetsuo Handa   tomoyo: Coding st...
229

545a72603   Tetsuo Handa   TOMOYO: Fix quota...
230
231
232
  			tomoyo_put_name(entry->domainname);
  		}
  		break;
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
233
234
  	}
  }
2e503bbb4   Tetsuo Handa   TOMOYO: Fix lockd...
235
236
237
238
239
  /**
   * tomoyo_del_domain - Delete members in "struct tomoyo_domain_info".
   *
   * @element: Pointer to "struct list_head".
   *
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
240
   * Returns nothing.
a427fd14d   Tetsuo Handa   TOMOYO: Remove to...
241
242
   *
   * Caller holds tomoyo_policy_lock mutex.
2e503bbb4   Tetsuo Handa   TOMOYO: Fix lockd...
243
   */
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
244
  static inline void tomoyo_del_domain(struct list_head *element)
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
245
  {
e79acf0ef   Tetsuo Handa   TOMOYO: Pass "str...
246
247
  	struct tomoyo_domain_info *domain =
  		container_of(element, typeof(*domain), list);
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
248
249
  	struct tomoyo_acl_info *acl;
  	struct tomoyo_acl_info *tmp;
cdcf6723a   Tetsuo Handa   tomoyo: Coding st...
250

847b173ea   Tetsuo Handa   TOMOYO: Add garba...
251
  	/*
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
252
253
254
  	 * 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...
255
  	 */
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
256
  	list_for_each_entry_safe(acl, tmp, &domain->acl_info_list, list) {
e79acf0ef   Tetsuo Handa   TOMOYO: Pass "str...
257
  		tomoyo_del_acl(&acl->list);
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
258
259
260
  		tomoyo_memory_free(acl);
  	}
  	tomoyo_put_name(domain->domainname);
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
261
  }
2066a3612   Tetsuo Handa   TOMOYO: Allow usi...
262
263
264
265
266
267
268
269
270
271
272
273
274
  /**
   * 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...
275
  	const u16 names_count = cond->names_count;
5b636857f   Tetsuo Handa   TOMOYO: Allow usi...
276
277
  	const u16 argc = cond->argc;
  	const u16 envc = cond->envc;
2066a3612   Tetsuo Handa   TOMOYO: Allow usi...
278
279
280
281
282
  	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...
283
284
  	struct tomoyo_name_union *names_p
  		= (struct tomoyo_name_union *) (numbers_p + numbers_count);
5b636857f   Tetsuo Handa   TOMOYO: Allow usi...
285
286
287
288
  	const struct tomoyo_argv *argv
  		= (const struct tomoyo_argv *) (names_p + names_count);
  	const struct tomoyo_envp *envp
  		= (const struct tomoyo_envp *) (argv + argc);
cdcf6723a   Tetsuo Handa   tomoyo: Coding st...
289

2066a3612   Tetsuo Handa   TOMOYO: Allow usi...
290
291
  	for (i = 0; i < numbers_count; i++)
  		tomoyo_put_number_union(numbers_p++);
2ca9bf453   Tetsuo Handa   TOMOYO: Allow usi...
292
293
  	for (i = 0; i < names_count; i++)
  		tomoyo_put_name_union(names_p++);
5b636857f   Tetsuo Handa   TOMOYO: Allow usi...
294
295
296
297
298
299
  	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...
300
  }
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
301

0df7e8b8f   Tetsuo Handa   TOMOYO: Cleanup p...
302
303
304
305
306
307
308
  /**
   * tomoyo_del_name - Delete members in "struct tomoyo_name".
   *
   * @element: Pointer to "struct list_head".
   *
   * Returns nothing.
   */
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
309
  static inline void tomoyo_del_name(struct list_head *element)
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
310
  {
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
311
  	/* Nothing to do. */
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
312
  }
0df7e8b8f   Tetsuo Handa   TOMOYO: Cleanup p...
313
314
315
316
317
318
319
  /**
   * tomoyo_del_path_group - Delete members in "struct tomoyo_path_group".
   *
   * @element: Pointer to "struct list_head".
   *
   * Returns nothing.
   */
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
320
  static inline void tomoyo_del_path_group(struct list_head *element)
7762fbfff   Tetsuo Handa   TOMOYO: Add pathn...
321
  {
a98aa4deb   Tetsuo Handa   TOMOYO: Merge tom...
322
  	struct tomoyo_path_group *member =
e79acf0ef   Tetsuo Handa   TOMOYO: Pass "str...
323
  		container_of(element, typeof(*member), head.list);
cdcf6723a   Tetsuo Handa   tomoyo: Coding st...
324

7762fbfff   Tetsuo Handa   TOMOYO: Add pathn...
325
326
  	tomoyo_put_name(member->member_name);
  }
0df7e8b8f   Tetsuo Handa   TOMOYO: Cleanup p...
327
328
329
330
331
332
333
  /**
   * tomoyo_del_group - Delete "struct tomoyo_group".
   *
   * @element: Pointer to "struct list_head".
   *
   * Returns nothing.
   */
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
334
  static inline void tomoyo_del_group(struct list_head *element)
7762fbfff   Tetsuo Handa   TOMOYO: Add pathn...
335
  {
a98aa4deb   Tetsuo Handa   TOMOYO: Merge tom...
336
  	struct tomoyo_group *group =
0df7e8b8f   Tetsuo Handa   TOMOYO: Cleanup p...
337
  		container_of(element, typeof(*group), head.list);
cdcf6723a   Tetsuo Handa   tomoyo: Coding st...
338

7762fbfff   Tetsuo Handa   TOMOYO: Add pathn...
339
340
  	tomoyo_put_name(group->group_name);
  }
0df7e8b8f   Tetsuo Handa   TOMOYO: Cleanup p...
341
  /**
059d84dbb   Tetsuo Handa   TOMOYO: Add socke...
342
343
344
345
346
347
348
349
350
351
352
353
   * 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...
354
355
356
357
358
359
   * tomoyo_del_number_group - Delete members in "struct tomoyo_number_group".
   *
   * @element: Pointer to "struct list_head".
   *
   * Returns nothing.
   */
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
360
  static inline void tomoyo_del_number_group(struct list_head *element)
4c3e9e2de   Tetsuo Handa   TOMOYO: Add numer...
361
  {
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
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
432
433
434
435
436
437
438
439
440
441
442
443
  	/* 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 ...
444
445
446
447
448
  		break;
  	case TOMOYO_MAX_POLICY:
  		break;
  	}
  	mutex_lock(&tomoyo_policy_lock);
a427fd14d   Tetsuo Handa   TOMOYO: Remove to...
449
450
  	if (type == TOMOYO_ID_DOMAIN)
  		tomoyo_del_domain(element);
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
451
452
453
454
455
456
457
458
459
460
461
462
463
  	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...
464
  }
0df7e8b8f   Tetsuo Handa   TOMOYO: Cleanup p...
465
466
467
468
469
470
  /**
   * 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 ...
471
   * Returns nothing.
0df7e8b8f   Tetsuo Handa   TOMOYO: Cleanup p...
472
   */
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
473
  static void tomoyo_collect_member(const enum tomoyo_policy_id id,
0df7e8b8f   Tetsuo Handa   TOMOYO: Cleanup p...
474
  				  struct list_head *member_list)
d2f8b2348   Tetsuo Handa   TOMOYO: Use commo...
475
476
  {
  	struct tomoyo_acl_head *member;
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
477
  	struct tomoyo_acl_head *tmp;
cdcf6723a   Tetsuo Handa   tomoyo: Coding st...
478

f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
479
  	list_for_each_entry_safe(member, tmp, member_list, list) {
d2f8b2348   Tetsuo Handa   TOMOYO: Use commo...
480
481
  		if (!member->is_deleted)
  			continue;
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
482
483
  		member->is_deleted = TOMOYO_GC_IN_PROGRESS;
  		tomoyo_try_to_gc(id, &member->list);
d2f8b2348   Tetsuo Handa   TOMOYO: Use commo...
484
  	}
d2f8b2348   Tetsuo Handa   TOMOYO: Use commo...
485
  }
32997144f   Tetsuo Handa   TOMOYO: Add ACL g...
486
487
488
489
490
  /**
   * tomoyo_collect_acl - Delete elements in "struct tomoyo_domain_info".
   *
   * @list: Pointer to "struct list_head".
   *
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
491
   * Returns nothing.
32997144f   Tetsuo Handa   TOMOYO: Add ACL g...
492
   */
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
493
  static void tomoyo_collect_acl(struct list_head *list)
d2f8b2348   Tetsuo Handa   TOMOYO: Use commo...
494
495
  {
  	struct tomoyo_acl_info *acl;
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
496
  	struct tomoyo_acl_info *tmp;
cdcf6723a   Tetsuo Handa   tomoyo: Coding st...
497

f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
498
  	list_for_each_entry_safe(acl, tmp, list, list) {
d2f8b2348   Tetsuo Handa   TOMOYO: Use commo...
499
500
  		if (!acl->is_deleted)
  			continue;
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
501
502
  		acl->is_deleted = TOMOYO_GC_IN_PROGRESS;
  		tomoyo_try_to_gc(TOMOYO_ID_ACL, &acl->list);
d2f8b2348   Tetsuo Handa   TOMOYO: Use commo...
503
  	}
d2f8b2348   Tetsuo Handa   TOMOYO: Use commo...
504
  }
0df7e8b8f   Tetsuo Handa   TOMOYO: Cleanup p...
505
  /**
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
506
   * tomoyo_collect_entry - Try to kfree() deleted elements.
0df7e8b8f   Tetsuo Handa   TOMOYO: Cleanup p...
507
508
509
   *
   * Returns nothing.
   */
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
510
511
  static void tomoyo_collect_entry(void)
  {
d2f8b2348   Tetsuo Handa   TOMOYO: Use commo...
512
  	int i;
bd03a3e4c   Tetsuo Handa   TOMOYO: Add polic...
513
514
  	enum tomoyo_policy_id id;
  	struct tomoyo_policy_namespace *ns;
cdcf6723a   Tetsuo Handa   tomoyo: Coding st...
515

f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
516
  	mutex_lock(&tomoyo_policy_lock);
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
517
518
  	{
  		struct tomoyo_domain_info *domain;
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
519
  		struct tomoyo_domain_info *tmp;
cdcf6723a   Tetsuo Handa   tomoyo: Coding st...
520

f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
521
522
523
  		list_for_each_entry_safe(domain, tmp, &tomoyo_domain_list,
  					 list) {
  			tomoyo_collect_acl(&domain->acl_info_list);
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
524
525
  			if (!domain->is_deleted || atomic_read(&domain->users))
  				continue;
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
526
  			tomoyo_try_to_gc(TOMOYO_ID_DOMAIN, &domain->list);
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
527
528
  		}
  	}
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
529
  	list_for_each_entry(ns, &tomoyo_namespace_list, namespace_list) {
bd03a3e4c   Tetsuo Handa   TOMOYO: Add polic...
530
  		for (id = 0; id < TOMOYO_MAX_POLICY; id++)
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
531
  			tomoyo_collect_member(id, &ns->policy_list[id]);
bd03a3e4c   Tetsuo Handa   TOMOYO: Add polic...
532
  		for (i = 0; i < TOMOYO_MAX_ACL_GROUPS; i++)
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
533
534
535
536
537
  			tomoyo_collect_acl(&ns->acl_group[i]);
  	}
  	{
  		struct tomoyo_shared_acl_head *ptr;
  		struct tomoyo_shared_acl_head *tmp;
cdcf6723a   Tetsuo Handa   tomoyo: Coding st...
538

f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
539
540
541
542
543
544
545
546
547
  		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...
548
549
550
  		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 ...
551
  			struct tomoyo_group *tmp;
cdcf6723a   Tetsuo Handa   tomoyo: Coding st...
552

bd03a3e4c   Tetsuo Handa   TOMOYO: Add polic...
553
554
555
556
  			switch (i) {
  			case 0:
  				id = TOMOYO_ID_PATH_GROUP;
  				break;
059d84dbb   Tetsuo Handa   TOMOYO: Add socke...
557
  			case 1:
bd03a3e4c   Tetsuo Handa   TOMOYO: Add polic...
558
559
  				id = TOMOYO_ID_NUMBER_GROUP;
  				break;
059d84dbb   Tetsuo Handa   TOMOYO: Add socke...
560
561
562
  			default:
  				id = TOMOYO_ID_ADDRESS_GROUP;
  				break;
bd03a3e4c   Tetsuo Handa   TOMOYO: Add polic...
563
  			}
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
564
565
  			list_for_each_entry_safe(group, tmp, list, head.list) {
  				tomoyo_collect_member(id, &group->member_list);
bd03a3e4c   Tetsuo Handa   TOMOYO: Add polic...
566
  				if (!list_empty(&group->member_list) ||
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
567
  				    atomic_read(&group->head.users) > 0)
bd03a3e4c   Tetsuo Handa   TOMOYO: Add polic...
568
  					continue;
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
569
570
571
572
  				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...
573
  			}
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
574
575
  		}
  	}
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
576
577
  	for (i = 0; i < TOMOYO_MAX_HASH; i++) {
  		struct list_head *list = &tomoyo_name_list[i];
bd03a3e4c   Tetsuo Handa   TOMOYO: Add polic...
578
  		struct tomoyo_shared_acl_head *ptr;
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
579
  		struct tomoyo_shared_acl_head *tmp;
cdcf6723a   Tetsuo Handa   tomoyo: Coding st...
580

f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
581
582
  		list_for_each_entry_safe(ptr, tmp, list, list) {
  			if (atomic_read(&ptr->users) > 0)
4c3e9e2de   Tetsuo Handa   TOMOYO: Add numer...
583
  				continue;
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
584
585
  			atomic_set(&ptr->users, TOMOYO_GC_IN_PROGRESS);
  			tomoyo_try_to_gc(TOMOYO_ID_NAME, &ptr->list);
4c3e9e2de   Tetsuo Handa   TOMOYO: Add numer...
586
587
  		}
  	}
292823814   Tetsuo Handa   TOMOYO: Use mutex...
588
  	mutex_unlock(&tomoyo_policy_lock);
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
589
  }
2e503bbb4   Tetsuo Handa   TOMOYO: Fix lockd...
590
  /**
0df7e8b8f   Tetsuo Handa   TOMOYO: Cleanup p...
591
592
593
594
   * tomoyo_gc_thread - Garbage collector thread function.
   *
   * @unused: Unused.
   *
0df7e8b8f   Tetsuo Handa   TOMOYO: Cleanup p...
595
596
   * Returns 0.
   */
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
597
598
  static int tomoyo_gc_thread(void *unused)
  {
2e503bbb4   Tetsuo Handa   TOMOYO: Fix lockd...
599
600
  	/* Garbage collector thread is exclusive. */
  	static DEFINE_MUTEX(tomoyo_gc_mutex);
cdcf6723a   Tetsuo Handa   tomoyo: Coding st...
601

2e503bbb4   Tetsuo Handa   TOMOYO: Fix lockd...
602
603
  	if (!mutex_trylock(&tomoyo_gc_mutex))
  		goto out;
f9732ea14   Tetsuo Handa   TOMOYO: Simplify ...
604
  	tomoyo_collect_entry();
2e503bbb4   Tetsuo Handa   TOMOYO: Fix lockd...
605
606
607
608
609
610
611
612
613
614
615
616
617
  	{
  		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...
618
  		}
2e503bbb4   Tetsuo Handa   TOMOYO: Fix lockd...
619
  		spin_unlock(&tomoyo_io_buffer_list_lock);
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
620
  	}
2e503bbb4   Tetsuo Handa   TOMOYO: Fix lockd...
621
622
623
624
  	mutex_unlock(&tomoyo_gc_mutex);
  out:
  	/* This acts as do_exit(0). */
  	return 0;
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
625
  }
2e503bbb4   Tetsuo Handa   TOMOYO: Fix lockd...
626
627
628
629
630
631
632
633
634
  /**
   * 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...
635
  {
2e503bbb4   Tetsuo Handa   TOMOYO: Fix lockd...
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
  	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:...
652
653
  	if (is_write)
  		kthread_run(tomoyo_gc_thread, NULL, "GC for TOMOYO");
847b173ea   Tetsuo Handa   TOMOYO: Add garba...
654
  }