gc.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655
  1. /*
  2. * security/tomoyo/gc.c
  3. *
  4. * Copyright (C) 2005-2011 NTT DATA CORPORATION
  5. */
  6. #include "common.h"
  7. #include <linux/kthread.h>
  8. #include <linux/slab.h>
  9. /**
  10. * tomoyo_memory_free - Free memory for elements.
  11. *
  12. * @ptr: Pointer to allocated memory.
  13. *
  14. * Returns nothing.
  15. *
  16. * Caller holds tomoyo_policy_lock mutex.
  17. */
  18. static inline void tomoyo_memory_free(void *ptr)
  19. {
  20. tomoyo_memory_used[TOMOYO_MEMORY_POLICY] -= ksize(ptr);
  21. kfree(ptr);
  22. }
  23. /* The list for "struct tomoyo_io_buffer". */
  24. static LIST_HEAD(tomoyo_io_buffer_list);
  25. /* Lock for protecting tomoyo_io_buffer_list. */
  26. static DEFINE_SPINLOCK(tomoyo_io_buffer_list_lock);
  27. /**
  28. * tomoyo_struct_used_by_io_buffer - Check whether the list element is used by /sys/kernel/security/tomoyo/ users or not.
  29. *
  30. * @element: Pointer to "struct list_head".
  31. *
  32. * Returns true if @element is used by /sys/kernel/security/tomoyo/ users,
  33. * false otherwise.
  34. */
  35. static bool tomoyo_struct_used_by_io_buffer(const struct list_head *element)
  36. {
  37. struct tomoyo_io_buffer *head;
  38. bool in_use = false;
  39. spin_lock(&tomoyo_io_buffer_list_lock);
  40. list_for_each_entry(head, &tomoyo_io_buffer_list, list) {
  41. head->users++;
  42. spin_unlock(&tomoyo_io_buffer_list_lock);
  43. mutex_lock(&head->io_sem);
  44. if (head->r.domain == element || head->r.group == element ||
  45. head->r.acl == element || &head->w.domain->list == element)
  46. in_use = true;
  47. mutex_unlock(&head->io_sem);
  48. spin_lock(&tomoyo_io_buffer_list_lock);
  49. head->users--;
  50. if (in_use)
  51. break;
  52. }
  53. spin_unlock(&tomoyo_io_buffer_list_lock);
  54. return in_use;
  55. }
  56. /**
  57. * tomoyo_name_used_by_io_buffer - Check whether the string is used by /sys/kernel/security/tomoyo/ users or not.
  58. *
  59. * @string: String to check.
  60. *
  61. * Returns true if @string is used by /sys/kernel/security/tomoyo/ users,
  62. * false otherwise.
  63. */
  64. static bool tomoyo_name_used_by_io_buffer(const char *string)
  65. {
  66. struct tomoyo_io_buffer *head;
  67. const size_t size = strlen(string) + 1;
  68. bool in_use = false;
  69. spin_lock(&tomoyo_io_buffer_list_lock);
  70. list_for_each_entry(head, &tomoyo_io_buffer_list, list) {
  71. int i;
  72. head->users++;
  73. spin_unlock(&tomoyo_io_buffer_list_lock);
  74. mutex_lock(&head->io_sem);
  75. for (i = 0; i < TOMOYO_MAX_IO_READ_QUEUE; i++) {
  76. const char *w = head->r.w[i];
  77. if (w < string || w > string + size)
  78. continue;
  79. in_use = true;
  80. break;
  81. }
  82. mutex_unlock(&head->io_sem);
  83. spin_lock(&tomoyo_io_buffer_list_lock);
  84. head->users--;
  85. if (in_use)
  86. break;
  87. }
  88. spin_unlock(&tomoyo_io_buffer_list_lock);
  89. return in_use;
  90. }
  91. /**
  92. * tomoyo_del_transition_control - Delete members in "struct tomoyo_transition_control".
  93. *
  94. * @element: Pointer to "struct list_head".
  95. *
  96. * Returns nothing.
  97. */
  98. static inline void tomoyo_del_transition_control(struct list_head *element)
  99. {
  100. struct tomoyo_transition_control *ptr =
  101. container_of(element, typeof(*ptr), head.list);
  102. tomoyo_put_name(ptr->domainname);
  103. tomoyo_put_name(ptr->program);
  104. }
  105. /**
  106. * tomoyo_del_aggregator - Delete members in "struct tomoyo_aggregator".
  107. *
  108. * @element: Pointer to "struct list_head".
  109. *
  110. * Returns nothing.
  111. */
  112. static inline void tomoyo_del_aggregator(struct list_head *element)
  113. {
  114. struct tomoyo_aggregator *ptr =
  115. container_of(element, typeof(*ptr), head.list);
  116. tomoyo_put_name(ptr->original_name);
  117. tomoyo_put_name(ptr->aggregated_name);
  118. }
  119. /**
  120. * tomoyo_del_manager - Delete members in "struct tomoyo_manager".
  121. *
  122. * @element: Pointer to "struct list_head".
  123. *
  124. * Returns nothing.
  125. */
  126. static inline void tomoyo_del_manager(struct list_head *element)
  127. {
  128. struct tomoyo_manager *ptr =
  129. container_of(element, typeof(*ptr), head.list);
  130. tomoyo_put_name(ptr->manager);
  131. }
  132. /**
  133. * tomoyo_del_acl - Delete members in "struct tomoyo_acl_info".
  134. *
  135. * @element: Pointer to "struct list_head".
  136. *
  137. * Returns nothing.
  138. */
  139. static void tomoyo_del_acl(struct list_head *element)
  140. {
  141. struct tomoyo_acl_info *acl =
  142. container_of(element, typeof(*acl), list);
  143. tomoyo_put_condition(acl->cond);
  144. switch (acl->type) {
  145. case TOMOYO_TYPE_PATH_ACL:
  146. {
  147. struct tomoyo_path_acl *entry
  148. = container_of(acl, typeof(*entry), head);
  149. tomoyo_put_name_union(&entry->name);
  150. }
  151. break;
  152. case TOMOYO_TYPE_PATH2_ACL:
  153. {
  154. struct tomoyo_path2_acl *entry
  155. = container_of(acl, typeof(*entry), head);
  156. tomoyo_put_name_union(&entry->name1);
  157. tomoyo_put_name_union(&entry->name2);
  158. }
  159. break;
  160. case TOMOYO_TYPE_PATH_NUMBER_ACL:
  161. {
  162. struct tomoyo_path_number_acl *entry
  163. = container_of(acl, typeof(*entry), head);
  164. tomoyo_put_name_union(&entry->name);
  165. tomoyo_put_number_union(&entry->number);
  166. }
  167. break;
  168. case TOMOYO_TYPE_MKDEV_ACL:
  169. {
  170. struct tomoyo_mkdev_acl *entry
  171. = container_of(acl, typeof(*entry), head);
  172. tomoyo_put_name_union(&entry->name);
  173. tomoyo_put_number_union(&entry->mode);
  174. tomoyo_put_number_union(&entry->major);
  175. tomoyo_put_number_union(&entry->minor);
  176. }
  177. break;
  178. case TOMOYO_TYPE_MOUNT_ACL:
  179. {
  180. struct tomoyo_mount_acl *entry
  181. = container_of(acl, typeof(*entry), head);
  182. tomoyo_put_name_union(&entry->dev_name);
  183. tomoyo_put_name_union(&entry->dir_name);
  184. tomoyo_put_name_union(&entry->fs_type);
  185. tomoyo_put_number_union(&entry->flags);
  186. }
  187. break;
  188. case TOMOYO_TYPE_ENV_ACL:
  189. {
  190. struct tomoyo_env_acl *entry =
  191. container_of(acl, typeof(*entry), head);
  192. tomoyo_put_name(entry->env);
  193. }
  194. break;
  195. case TOMOYO_TYPE_INET_ACL:
  196. {
  197. struct tomoyo_inet_acl *entry =
  198. container_of(acl, typeof(*entry), head);
  199. tomoyo_put_group(entry->address.group);
  200. tomoyo_put_number_union(&entry->port);
  201. }
  202. break;
  203. case TOMOYO_TYPE_UNIX_ACL:
  204. {
  205. struct tomoyo_unix_acl *entry =
  206. container_of(acl, typeof(*entry), head);
  207. tomoyo_put_name_union(&entry->name);
  208. }
  209. break;
  210. case TOMOYO_TYPE_MANUAL_TASK_ACL:
  211. {
  212. struct tomoyo_task_acl *entry =
  213. container_of(acl, typeof(*entry), head);
  214. tomoyo_put_name(entry->domainname);
  215. }
  216. break;
  217. }
  218. }
  219. /**
  220. * tomoyo_del_domain - Delete members in "struct tomoyo_domain_info".
  221. *
  222. * @element: Pointer to "struct list_head".
  223. *
  224. * Returns nothing.
  225. *
  226. * Caller holds tomoyo_policy_lock mutex.
  227. */
  228. static inline void tomoyo_del_domain(struct list_head *element)
  229. {
  230. struct tomoyo_domain_info *domain =
  231. container_of(element, typeof(*domain), list);
  232. struct tomoyo_acl_info *acl;
  233. struct tomoyo_acl_info *tmp;
  234. /*
  235. * Since this domain is referenced from neither
  236. * "struct tomoyo_io_buffer" nor "struct cred"->security, we can delete
  237. * elements without checking for is_deleted flag.
  238. */
  239. list_for_each_entry_safe(acl, tmp, &domain->acl_info_list, list) {
  240. tomoyo_del_acl(&acl->list);
  241. tomoyo_memory_free(acl);
  242. }
  243. tomoyo_put_name(domain->domainname);
  244. }
  245. /**
  246. * tomoyo_del_condition - Delete members in "struct tomoyo_condition".
  247. *
  248. * @element: Pointer to "struct list_head".
  249. *
  250. * Returns nothing.
  251. */
  252. void tomoyo_del_condition(struct list_head *element)
  253. {
  254. struct tomoyo_condition *cond = container_of(element, typeof(*cond),
  255. head.list);
  256. const u16 condc = cond->condc;
  257. const u16 numbers_count = cond->numbers_count;
  258. const u16 names_count = cond->names_count;
  259. const u16 argc = cond->argc;
  260. const u16 envc = cond->envc;
  261. unsigned int i;
  262. const struct tomoyo_condition_element *condp
  263. = (const struct tomoyo_condition_element *) (cond + 1);
  264. struct tomoyo_number_union *numbers_p
  265. = (struct tomoyo_number_union *) (condp + condc);
  266. struct tomoyo_name_union *names_p
  267. = (struct tomoyo_name_union *) (numbers_p + numbers_count);
  268. const struct tomoyo_argv *argv
  269. = (const struct tomoyo_argv *) (names_p + names_count);
  270. const struct tomoyo_envp *envp
  271. = (const struct tomoyo_envp *) (argv + argc);
  272. for (i = 0; i < numbers_count; i++)
  273. tomoyo_put_number_union(numbers_p++);
  274. for (i = 0; i < names_count; i++)
  275. tomoyo_put_name_union(names_p++);
  276. for (i = 0; i < argc; argv++, i++)
  277. tomoyo_put_name(argv->value);
  278. for (i = 0; i < envc; envp++, i++) {
  279. tomoyo_put_name(envp->name);
  280. tomoyo_put_name(envp->value);
  281. }
  282. }
  283. /**
  284. * tomoyo_del_name - Delete members in "struct tomoyo_name".
  285. *
  286. * @element: Pointer to "struct list_head".
  287. *
  288. * Returns nothing.
  289. */
  290. static inline void tomoyo_del_name(struct list_head *element)
  291. {
  292. /* Nothing to do. */
  293. }
  294. /**
  295. * tomoyo_del_path_group - Delete members in "struct tomoyo_path_group".
  296. *
  297. * @element: Pointer to "struct list_head".
  298. *
  299. * Returns nothing.
  300. */
  301. static inline void tomoyo_del_path_group(struct list_head *element)
  302. {
  303. struct tomoyo_path_group *member =
  304. container_of(element, typeof(*member), head.list);
  305. tomoyo_put_name(member->member_name);
  306. }
  307. /**
  308. * tomoyo_del_group - Delete "struct tomoyo_group".
  309. *
  310. * @element: Pointer to "struct list_head".
  311. *
  312. * Returns nothing.
  313. */
  314. static inline void tomoyo_del_group(struct list_head *element)
  315. {
  316. struct tomoyo_group *group =
  317. container_of(element, typeof(*group), head.list);
  318. tomoyo_put_name(group->group_name);
  319. }
  320. /**
  321. * tomoyo_del_address_group - Delete members in "struct tomoyo_address_group".
  322. *
  323. * @element: Pointer to "struct list_head".
  324. *
  325. * Returns nothing.
  326. */
  327. static inline void tomoyo_del_address_group(struct list_head *element)
  328. {
  329. /* Nothing to do. */
  330. }
  331. /**
  332. * tomoyo_del_number_group - Delete members in "struct tomoyo_number_group".
  333. *
  334. * @element: Pointer to "struct list_head".
  335. *
  336. * Returns nothing.
  337. */
  338. static inline void tomoyo_del_number_group(struct list_head *element)
  339. {
  340. /* Nothing to do. */
  341. }
  342. /**
  343. * tomoyo_try_to_gc - Try to kfree() an entry.
  344. *
  345. * @type: One of values in "enum tomoyo_policy_id".
  346. * @element: Pointer to "struct list_head".
  347. *
  348. * Returns nothing.
  349. *
  350. * Caller holds tomoyo_policy_lock mutex.
  351. */
  352. static void tomoyo_try_to_gc(const enum tomoyo_policy_id type,
  353. struct list_head *element)
  354. {
  355. /*
  356. * __list_del_entry() guarantees that the list element became no longer
  357. * reachable from the list which the element was originally on (e.g.
  358. * tomoyo_domain_list). Also, synchronize_srcu() guarantees that the
  359. * list element became no longer referenced by syscall users.
  360. */
  361. __list_del_entry(element);
  362. mutex_unlock(&tomoyo_policy_lock);
  363. synchronize_srcu(&tomoyo_ss);
  364. /*
  365. * However, there are two users which may still be using the list
  366. * element. We need to defer until both users forget this element.
  367. *
  368. * Don't kfree() until "struct tomoyo_io_buffer"->r.{domain,group,acl}
  369. * and "struct tomoyo_io_buffer"->w.domain forget this element.
  370. */
  371. if (tomoyo_struct_used_by_io_buffer(element))
  372. goto reinject;
  373. switch (type) {
  374. case TOMOYO_ID_TRANSITION_CONTROL:
  375. tomoyo_del_transition_control(element);
  376. break;
  377. case TOMOYO_ID_MANAGER:
  378. tomoyo_del_manager(element);
  379. break;
  380. case TOMOYO_ID_AGGREGATOR:
  381. tomoyo_del_aggregator(element);
  382. break;
  383. case TOMOYO_ID_GROUP:
  384. tomoyo_del_group(element);
  385. break;
  386. case TOMOYO_ID_PATH_GROUP:
  387. tomoyo_del_path_group(element);
  388. break;
  389. case TOMOYO_ID_ADDRESS_GROUP:
  390. tomoyo_del_address_group(element);
  391. break;
  392. case TOMOYO_ID_NUMBER_GROUP:
  393. tomoyo_del_number_group(element);
  394. break;
  395. case TOMOYO_ID_CONDITION:
  396. tomoyo_del_condition(element);
  397. break;
  398. case TOMOYO_ID_NAME:
  399. /*
  400. * Don't kfree() until all "struct tomoyo_io_buffer"->r.w[]
  401. * forget this element.
  402. */
  403. if (tomoyo_name_used_by_io_buffer
  404. (container_of(element, typeof(struct tomoyo_name),
  405. head.list)->entry.name))
  406. goto reinject;
  407. tomoyo_del_name(element);
  408. break;
  409. case TOMOYO_ID_ACL:
  410. tomoyo_del_acl(element);
  411. break;
  412. case TOMOYO_ID_DOMAIN:
  413. /*
  414. * Don't kfree() until all "struct cred"->security forget this
  415. * element.
  416. */
  417. if (atomic_read(&container_of
  418. (element, typeof(struct tomoyo_domain_info),
  419. list)->users))
  420. goto reinject;
  421. break;
  422. case TOMOYO_MAX_POLICY:
  423. break;
  424. }
  425. mutex_lock(&tomoyo_policy_lock);
  426. if (type == TOMOYO_ID_DOMAIN)
  427. tomoyo_del_domain(element);
  428. tomoyo_memory_free(element);
  429. return;
  430. reinject:
  431. /*
  432. * We can safely reinject this element here bacause
  433. * (1) Appending list elements and removing list elements are protected
  434. * by tomoyo_policy_lock mutex.
  435. * (2) Only this function removes list elements and this function is
  436. * exclusively executed by tomoyo_gc_mutex mutex.
  437. * are true.
  438. */
  439. mutex_lock(&tomoyo_policy_lock);
  440. list_add_rcu(element, element->prev);
  441. }
  442. /**
  443. * tomoyo_collect_member - Delete elements with "struct tomoyo_acl_head".
  444. *
  445. * @id: One of values in "enum tomoyo_policy_id".
  446. * @member_list: Pointer to "struct list_head".
  447. *
  448. * Returns nothing.
  449. */
  450. static void tomoyo_collect_member(const enum tomoyo_policy_id id,
  451. struct list_head *member_list)
  452. {
  453. struct tomoyo_acl_head *member;
  454. struct tomoyo_acl_head *tmp;
  455. list_for_each_entry_safe(member, tmp, member_list, list) {
  456. if (!member->is_deleted)
  457. continue;
  458. member->is_deleted = TOMOYO_GC_IN_PROGRESS;
  459. tomoyo_try_to_gc(id, &member->list);
  460. }
  461. }
  462. /**
  463. * tomoyo_collect_acl - Delete elements in "struct tomoyo_domain_info".
  464. *
  465. * @list: Pointer to "struct list_head".
  466. *
  467. * Returns nothing.
  468. */
  469. static void tomoyo_collect_acl(struct list_head *list)
  470. {
  471. struct tomoyo_acl_info *acl;
  472. struct tomoyo_acl_info *tmp;
  473. list_for_each_entry_safe(acl, tmp, list, list) {
  474. if (!acl->is_deleted)
  475. continue;
  476. acl->is_deleted = TOMOYO_GC_IN_PROGRESS;
  477. tomoyo_try_to_gc(TOMOYO_ID_ACL, &acl->list);
  478. }
  479. }
  480. /**
  481. * tomoyo_collect_entry - Try to kfree() deleted elements.
  482. *
  483. * Returns nothing.
  484. */
  485. static void tomoyo_collect_entry(void)
  486. {
  487. int i;
  488. enum tomoyo_policy_id id;
  489. struct tomoyo_policy_namespace *ns;
  490. mutex_lock(&tomoyo_policy_lock);
  491. {
  492. struct tomoyo_domain_info *domain;
  493. struct tomoyo_domain_info *tmp;
  494. list_for_each_entry_safe(domain, tmp, &tomoyo_domain_list,
  495. list) {
  496. tomoyo_collect_acl(&domain->acl_info_list);
  497. if (!domain->is_deleted || atomic_read(&domain->users))
  498. continue;
  499. tomoyo_try_to_gc(TOMOYO_ID_DOMAIN, &domain->list);
  500. }
  501. }
  502. list_for_each_entry(ns, &tomoyo_namespace_list, namespace_list) {
  503. for (id = 0; id < TOMOYO_MAX_POLICY; id++)
  504. tomoyo_collect_member(id, &ns->policy_list[id]);
  505. for (i = 0; i < TOMOYO_MAX_ACL_GROUPS; i++)
  506. tomoyo_collect_acl(&ns->acl_group[i]);
  507. }
  508. {
  509. struct tomoyo_shared_acl_head *ptr;
  510. struct tomoyo_shared_acl_head *tmp;
  511. list_for_each_entry_safe(ptr, tmp, &tomoyo_condition_list,
  512. list) {
  513. if (atomic_read(&ptr->users) > 0)
  514. continue;
  515. atomic_set(&ptr->users, TOMOYO_GC_IN_PROGRESS);
  516. tomoyo_try_to_gc(TOMOYO_ID_CONDITION, &ptr->list);
  517. }
  518. }
  519. list_for_each_entry(ns, &tomoyo_namespace_list, namespace_list) {
  520. for (i = 0; i < TOMOYO_MAX_GROUP; i++) {
  521. struct list_head *list = &ns->group_list[i];
  522. struct tomoyo_group *group;
  523. struct tomoyo_group *tmp;
  524. switch (i) {
  525. case 0:
  526. id = TOMOYO_ID_PATH_GROUP;
  527. break;
  528. case 1:
  529. id = TOMOYO_ID_NUMBER_GROUP;
  530. break;
  531. default:
  532. id = TOMOYO_ID_ADDRESS_GROUP;
  533. break;
  534. }
  535. list_for_each_entry_safe(group, tmp, list, head.list) {
  536. tomoyo_collect_member(id, &group->member_list);
  537. if (!list_empty(&group->member_list) ||
  538. atomic_read(&group->head.users) > 0)
  539. continue;
  540. atomic_set(&group->head.users,
  541. TOMOYO_GC_IN_PROGRESS);
  542. tomoyo_try_to_gc(TOMOYO_ID_GROUP,
  543. &group->head.list);
  544. }
  545. }
  546. }
  547. for (i = 0; i < TOMOYO_MAX_HASH; i++) {
  548. struct list_head *list = &tomoyo_name_list[i];
  549. struct tomoyo_shared_acl_head *ptr;
  550. struct tomoyo_shared_acl_head *tmp;
  551. list_for_each_entry_safe(ptr, tmp, list, list) {
  552. if (atomic_read(&ptr->users) > 0)
  553. continue;
  554. atomic_set(&ptr->users, TOMOYO_GC_IN_PROGRESS);
  555. tomoyo_try_to_gc(TOMOYO_ID_NAME, &ptr->list);
  556. }
  557. }
  558. mutex_unlock(&tomoyo_policy_lock);
  559. }
  560. /**
  561. * tomoyo_gc_thread - Garbage collector thread function.
  562. *
  563. * @unused: Unused.
  564. *
  565. * Returns 0.
  566. */
  567. static int tomoyo_gc_thread(void *unused)
  568. {
  569. /* Garbage collector thread is exclusive. */
  570. static DEFINE_MUTEX(tomoyo_gc_mutex);
  571. if (!mutex_trylock(&tomoyo_gc_mutex))
  572. goto out;
  573. tomoyo_collect_entry();
  574. {
  575. struct tomoyo_io_buffer *head;
  576. struct tomoyo_io_buffer *tmp;
  577. spin_lock(&tomoyo_io_buffer_list_lock);
  578. list_for_each_entry_safe(head, tmp, &tomoyo_io_buffer_list,
  579. list) {
  580. if (head->users)
  581. continue;
  582. list_del(&head->list);
  583. kfree(head->read_buf);
  584. kfree(head->write_buf);
  585. kfree(head);
  586. }
  587. spin_unlock(&tomoyo_io_buffer_list_lock);
  588. }
  589. mutex_unlock(&tomoyo_gc_mutex);
  590. out:
  591. /* This acts as do_exit(0). */
  592. return 0;
  593. }
  594. /**
  595. * tomoyo_notify_gc - Register/unregister /sys/kernel/security/tomoyo/ users.
  596. *
  597. * @head: Pointer to "struct tomoyo_io_buffer".
  598. * @is_register: True if register, false if unregister.
  599. *
  600. * Returns nothing.
  601. */
  602. void tomoyo_notify_gc(struct tomoyo_io_buffer *head, const bool is_register)
  603. {
  604. bool is_write = false;
  605. spin_lock(&tomoyo_io_buffer_list_lock);
  606. if (is_register) {
  607. head->users = 1;
  608. list_add(&head->list, &tomoyo_io_buffer_list);
  609. } else {
  610. is_write = head->write_buf != NULL;
  611. if (!--head->users) {
  612. list_del(&head->list);
  613. kfree(head->read_buf);
  614. kfree(head->write_buf);
  615. kfree(head);
  616. }
  617. }
  618. spin_unlock(&tomoyo_io_buffer_list_lock);
  619. if (is_write) {
  620. struct task_struct *task = kthread_create(tomoyo_gc_thread,
  621. NULL,
  622. "GC for TOMOYO");
  623. if (!IS_ERR(task))
  624. wake_up_process(task);
  625. }
  626. }