18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * security/tomoyo/gc.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2005-2011 NTT DATA CORPORATION 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include "common.h" 98c2ecf20Sopenharmony_ci#include <linux/kthread.h> 108c2ecf20Sopenharmony_ci#include <linux/slab.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci/** 138c2ecf20Sopenharmony_ci * tomoyo_memory_free - Free memory for elements. 148c2ecf20Sopenharmony_ci * 158c2ecf20Sopenharmony_ci * @ptr: Pointer to allocated memory. 168c2ecf20Sopenharmony_ci * 178c2ecf20Sopenharmony_ci * Returns nothing. 188c2ecf20Sopenharmony_ci * 198c2ecf20Sopenharmony_ci * Caller holds tomoyo_policy_lock mutex. 208c2ecf20Sopenharmony_ci */ 218c2ecf20Sopenharmony_cistatic inline void tomoyo_memory_free(void *ptr) 228c2ecf20Sopenharmony_ci{ 238c2ecf20Sopenharmony_ci tomoyo_memory_used[TOMOYO_MEMORY_POLICY] -= ksize(ptr); 248c2ecf20Sopenharmony_ci kfree(ptr); 258c2ecf20Sopenharmony_ci} 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci/* The list for "struct tomoyo_io_buffer". */ 288c2ecf20Sopenharmony_cistatic LIST_HEAD(tomoyo_io_buffer_list); 298c2ecf20Sopenharmony_ci/* Lock for protecting tomoyo_io_buffer_list. */ 308c2ecf20Sopenharmony_cistatic DEFINE_SPINLOCK(tomoyo_io_buffer_list_lock); 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci/** 338c2ecf20Sopenharmony_ci * tomoyo_struct_used_by_io_buffer - Check whether the list element is used by /sys/kernel/security/tomoyo/ users or not. 348c2ecf20Sopenharmony_ci * 358c2ecf20Sopenharmony_ci * @element: Pointer to "struct list_head". 368c2ecf20Sopenharmony_ci * 378c2ecf20Sopenharmony_ci * Returns true if @element is used by /sys/kernel/security/tomoyo/ users, 388c2ecf20Sopenharmony_ci * false otherwise. 398c2ecf20Sopenharmony_ci */ 408c2ecf20Sopenharmony_cistatic bool tomoyo_struct_used_by_io_buffer(const struct list_head *element) 418c2ecf20Sopenharmony_ci{ 428c2ecf20Sopenharmony_ci struct tomoyo_io_buffer *head; 438c2ecf20Sopenharmony_ci bool in_use = false; 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci spin_lock(&tomoyo_io_buffer_list_lock); 468c2ecf20Sopenharmony_ci list_for_each_entry(head, &tomoyo_io_buffer_list, list) { 478c2ecf20Sopenharmony_ci head->users++; 488c2ecf20Sopenharmony_ci spin_unlock(&tomoyo_io_buffer_list_lock); 498c2ecf20Sopenharmony_ci mutex_lock(&head->io_sem); 508c2ecf20Sopenharmony_ci if (head->r.domain == element || head->r.group == element || 518c2ecf20Sopenharmony_ci head->r.acl == element || &head->w.domain->list == element) 528c2ecf20Sopenharmony_ci in_use = true; 538c2ecf20Sopenharmony_ci mutex_unlock(&head->io_sem); 548c2ecf20Sopenharmony_ci spin_lock(&tomoyo_io_buffer_list_lock); 558c2ecf20Sopenharmony_ci head->users--; 568c2ecf20Sopenharmony_ci if (in_use) 578c2ecf20Sopenharmony_ci break; 588c2ecf20Sopenharmony_ci } 598c2ecf20Sopenharmony_ci spin_unlock(&tomoyo_io_buffer_list_lock); 608c2ecf20Sopenharmony_ci return in_use; 618c2ecf20Sopenharmony_ci} 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci/** 648c2ecf20Sopenharmony_ci * tomoyo_name_used_by_io_buffer - Check whether the string is used by /sys/kernel/security/tomoyo/ users or not. 658c2ecf20Sopenharmony_ci * 668c2ecf20Sopenharmony_ci * @string: String to check. 678c2ecf20Sopenharmony_ci * 688c2ecf20Sopenharmony_ci * Returns true if @string is used by /sys/kernel/security/tomoyo/ users, 698c2ecf20Sopenharmony_ci * false otherwise. 708c2ecf20Sopenharmony_ci */ 718c2ecf20Sopenharmony_cistatic bool tomoyo_name_used_by_io_buffer(const char *string) 728c2ecf20Sopenharmony_ci{ 738c2ecf20Sopenharmony_ci struct tomoyo_io_buffer *head; 748c2ecf20Sopenharmony_ci const size_t size = strlen(string) + 1; 758c2ecf20Sopenharmony_ci bool in_use = false; 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci spin_lock(&tomoyo_io_buffer_list_lock); 788c2ecf20Sopenharmony_ci list_for_each_entry(head, &tomoyo_io_buffer_list, list) { 798c2ecf20Sopenharmony_ci int i; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci head->users++; 828c2ecf20Sopenharmony_ci spin_unlock(&tomoyo_io_buffer_list_lock); 838c2ecf20Sopenharmony_ci mutex_lock(&head->io_sem); 848c2ecf20Sopenharmony_ci for (i = 0; i < TOMOYO_MAX_IO_READ_QUEUE; i++) { 858c2ecf20Sopenharmony_ci const char *w = head->r.w[i]; 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci if (w < string || w > string + size) 888c2ecf20Sopenharmony_ci continue; 898c2ecf20Sopenharmony_ci in_use = true; 908c2ecf20Sopenharmony_ci break; 918c2ecf20Sopenharmony_ci } 928c2ecf20Sopenharmony_ci mutex_unlock(&head->io_sem); 938c2ecf20Sopenharmony_ci spin_lock(&tomoyo_io_buffer_list_lock); 948c2ecf20Sopenharmony_ci head->users--; 958c2ecf20Sopenharmony_ci if (in_use) 968c2ecf20Sopenharmony_ci break; 978c2ecf20Sopenharmony_ci } 988c2ecf20Sopenharmony_ci spin_unlock(&tomoyo_io_buffer_list_lock); 998c2ecf20Sopenharmony_ci return in_use; 1008c2ecf20Sopenharmony_ci} 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci/** 1038c2ecf20Sopenharmony_ci * tomoyo_del_transition_control - Delete members in "struct tomoyo_transition_control". 1048c2ecf20Sopenharmony_ci * 1058c2ecf20Sopenharmony_ci * @element: Pointer to "struct list_head". 1068c2ecf20Sopenharmony_ci * 1078c2ecf20Sopenharmony_ci * Returns nothing. 1088c2ecf20Sopenharmony_ci */ 1098c2ecf20Sopenharmony_cistatic inline void tomoyo_del_transition_control(struct list_head *element) 1108c2ecf20Sopenharmony_ci{ 1118c2ecf20Sopenharmony_ci struct tomoyo_transition_control *ptr = 1128c2ecf20Sopenharmony_ci container_of(element, typeof(*ptr), head.list); 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci tomoyo_put_name(ptr->domainname); 1158c2ecf20Sopenharmony_ci tomoyo_put_name(ptr->program); 1168c2ecf20Sopenharmony_ci} 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci/** 1198c2ecf20Sopenharmony_ci * tomoyo_del_aggregator - Delete members in "struct tomoyo_aggregator". 1208c2ecf20Sopenharmony_ci * 1218c2ecf20Sopenharmony_ci * @element: Pointer to "struct list_head". 1228c2ecf20Sopenharmony_ci * 1238c2ecf20Sopenharmony_ci * Returns nothing. 1248c2ecf20Sopenharmony_ci */ 1258c2ecf20Sopenharmony_cistatic inline void tomoyo_del_aggregator(struct list_head *element) 1268c2ecf20Sopenharmony_ci{ 1278c2ecf20Sopenharmony_ci struct tomoyo_aggregator *ptr = 1288c2ecf20Sopenharmony_ci container_of(element, typeof(*ptr), head.list); 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci tomoyo_put_name(ptr->original_name); 1318c2ecf20Sopenharmony_ci tomoyo_put_name(ptr->aggregated_name); 1328c2ecf20Sopenharmony_ci} 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci/** 1358c2ecf20Sopenharmony_ci * tomoyo_del_manager - Delete members in "struct tomoyo_manager". 1368c2ecf20Sopenharmony_ci * 1378c2ecf20Sopenharmony_ci * @element: Pointer to "struct list_head". 1388c2ecf20Sopenharmony_ci * 1398c2ecf20Sopenharmony_ci * Returns nothing. 1408c2ecf20Sopenharmony_ci */ 1418c2ecf20Sopenharmony_cistatic inline void tomoyo_del_manager(struct list_head *element) 1428c2ecf20Sopenharmony_ci{ 1438c2ecf20Sopenharmony_ci struct tomoyo_manager *ptr = 1448c2ecf20Sopenharmony_ci container_of(element, typeof(*ptr), head.list); 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci tomoyo_put_name(ptr->manager); 1478c2ecf20Sopenharmony_ci} 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci/** 1508c2ecf20Sopenharmony_ci * tomoyo_del_acl - Delete members in "struct tomoyo_acl_info". 1518c2ecf20Sopenharmony_ci * 1528c2ecf20Sopenharmony_ci * @element: Pointer to "struct list_head". 1538c2ecf20Sopenharmony_ci * 1548c2ecf20Sopenharmony_ci * Returns nothing. 1558c2ecf20Sopenharmony_ci */ 1568c2ecf20Sopenharmony_cistatic void tomoyo_del_acl(struct list_head *element) 1578c2ecf20Sopenharmony_ci{ 1588c2ecf20Sopenharmony_ci struct tomoyo_acl_info *acl = 1598c2ecf20Sopenharmony_ci container_of(element, typeof(*acl), list); 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci tomoyo_put_condition(acl->cond); 1628c2ecf20Sopenharmony_ci switch (acl->type) { 1638c2ecf20Sopenharmony_ci case TOMOYO_TYPE_PATH_ACL: 1648c2ecf20Sopenharmony_ci { 1658c2ecf20Sopenharmony_ci struct tomoyo_path_acl *entry 1668c2ecf20Sopenharmony_ci = container_of(acl, typeof(*entry), head); 1678c2ecf20Sopenharmony_ci tomoyo_put_name_union(&entry->name); 1688c2ecf20Sopenharmony_ci } 1698c2ecf20Sopenharmony_ci break; 1708c2ecf20Sopenharmony_ci case TOMOYO_TYPE_PATH2_ACL: 1718c2ecf20Sopenharmony_ci { 1728c2ecf20Sopenharmony_ci struct tomoyo_path2_acl *entry 1738c2ecf20Sopenharmony_ci = container_of(acl, typeof(*entry), head); 1748c2ecf20Sopenharmony_ci tomoyo_put_name_union(&entry->name1); 1758c2ecf20Sopenharmony_ci tomoyo_put_name_union(&entry->name2); 1768c2ecf20Sopenharmony_ci } 1778c2ecf20Sopenharmony_ci break; 1788c2ecf20Sopenharmony_ci case TOMOYO_TYPE_PATH_NUMBER_ACL: 1798c2ecf20Sopenharmony_ci { 1808c2ecf20Sopenharmony_ci struct tomoyo_path_number_acl *entry 1818c2ecf20Sopenharmony_ci = container_of(acl, typeof(*entry), head); 1828c2ecf20Sopenharmony_ci tomoyo_put_name_union(&entry->name); 1838c2ecf20Sopenharmony_ci tomoyo_put_number_union(&entry->number); 1848c2ecf20Sopenharmony_ci } 1858c2ecf20Sopenharmony_ci break; 1868c2ecf20Sopenharmony_ci case TOMOYO_TYPE_MKDEV_ACL: 1878c2ecf20Sopenharmony_ci { 1888c2ecf20Sopenharmony_ci struct tomoyo_mkdev_acl *entry 1898c2ecf20Sopenharmony_ci = container_of(acl, typeof(*entry), head); 1908c2ecf20Sopenharmony_ci tomoyo_put_name_union(&entry->name); 1918c2ecf20Sopenharmony_ci tomoyo_put_number_union(&entry->mode); 1928c2ecf20Sopenharmony_ci tomoyo_put_number_union(&entry->major); 1938c2ecf20Sopenharmony_ci tomoyo_put_number_union(&entry->minor); 1948c2ecf20Sopenharmony_ci } 1958c2ecf20Sopenharmony_ci break; 1968c2ecf20Sopenharmony_ci case TOMOYO_TYPE_MOUNT_ACL: 1978c2ecf20Sopenharmony_ci { 1988c2ecf20Sopenharmony_ci struct tomoyo_mount_acl *entry 1998c2ecf20Sopenharmony_ci = container_of(acl, typeof(*entry), head); 2008c2ecf20Sopenharmony_ci tomoyo_put_name_union(&entry->dev_name); 2018c2ecf20Sopenharmony_ci tomoyo_put_name_union(&entry->dir_name); 2028c2ecf20Sopenharmony_ci tomoyo_put_name_union(&entry->fs_type); 2038c2ecf20Sopenharmony_ci tomoyo_put_number_union(&entry->flags); 2048c2ecf20Sopenharmony_ci } 2058c2ecf20Sopenharmony_ci break; 2068c2ecf20Sopenharmony_ci case TOMOYO_TYPE_ENV_ACL: 2078c2ecf20Sopenharmony_ci { 2088c2ecf20Sopenharmony_ci struct tomoyo_env_acl *entry = 2098c2ecf20Sopenharmony_ci container_of(acl, typeof(*entry), head); 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci tomoyo_put_name(entry->env); 2128c2ecf20Sopenharmony_ci } 2138c2ecf20Sopenharmony_ci break; 2148c2ecf20Sopenharmony_ci case TOMOYO_TYPE_INET_ACL: 2158c2ecf20Sopenharmony_ci { 2168c2ecf20Sopenharmony_ci struct tomoyo_inet_acl *entry = 2178c2ecf20Sopenharmony_ci container_of(acl, typeof(*entry), head); 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci tomoyo_put_group(entry->address.group); 2208c2ecf20Sopenharmony_ci tomoyo_put_number_union(&entry->port); 2218c2ecf20Sopenharmony_ci } 2228c2ecf20Sopenharmony_ci break; 2238c2ecf20Sopenharmony_ci case TOMOYO_TYPE_UNIX_ACL: 2248c2ecf20Sopenharmony_ci { 2258c2ecf20Sopenharmony_ci struct tomoyo_unix_acl *entry = 2268c2ecf20Sopenharmony_ci container_of(acl, typeof(*entry), head); 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci tomoyo_put_name_union(&entry->name); 2298c2ecf20Sopenharmony_ci } 2308c2ecf20Sopenharmony_ci break; 2318c2ecf20Sopenharmony_ci case TOMOYO_TYPE_MANUAL_TASK_ACL: 2328c2ecf20Sopenharmony_ci { 2338c2ecf20Sopenharmony_ci struct tomoyo_task_acl *entry = 2348c2ecf20Sopenharmony_ci container_of(acl, typeof(*entry), head); 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci tomoyo_put_name(entry->domainname); 2378c2ecf20Sopenharmony_ci } 2388c2ecf20Sopenharmony_ci break; 2398c2ecf20Sopenharmony_ci } 2408c2ecf20Sopenharmony_ci} 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci/** 2438c2ecf20Sopenharmony_ci * tomoyo_del_domain - Delete members in "struct tomoyo_domain_info". 2448c2ecf20Sopenharmony_ci * 2458c2ecf20Sopenharmony_ci * @element: Pointer to "struct list_head". 2468c2ecf20Sopenharmony_ci * 2478c2ecf20Sopenharmony_ci * Returns nothing. 2488c2ecf20Sopenharmony_ci * 2498c2ecf20Sopenharmony_ci * Caller holds tomoyo_policy_lock mutex. 2508c2ecf20Sopenharmony_ci */ 2518c2ecf20Sopenharmony_cistatic inline void tomoyo_del_domain(struct list_head *element) 2528c2ecf20Sopenharmony_ci{ 2538c2ecf20Sopenharmony_ci struct tomoyo_domain_info *domain = 2548c2ecf20Sopenharmony_ci container_of(element, typeof(*domain), list); 2558c2ecf20Sopenharmony_ci struct tomoyo_acl_info *acl; 2568c2ecf20Sopenharmony_ci struct tomoyo_acl_info *tmp; 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci /* 2598c2ecf20Sopenharmony_ci * Since this domain is referenced from neither 2608c2ecf20Sopenharmony_ci * "struct tomoyo_io_buffer" nor "struct cred"->security, we can delete 2618c2ecf20Sopenharmony_ci * elements without checking for is_deleted flag. 2628c2ecf20Sopenharmony_ci */ 2638c2ecf20Sopenharmony_ci list_for_each_entry_safe(acl, tmp, &domain->acl_info_list, list) { 2648c2ecf20Sopenharmony_ci tomoyo_del_acl(&acl->list); 2658c2ecf20Sopenharmony_ci tomoyo_memory_free(acl); 2668c2ecf20Sopenharmony_ci } 2678c2ecf20Sopenharmony_ci tomoyo_put_name(domain->domainname); 2688c2ecf20Sopenharmony_ci} 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci/** 2718c2ecf20Sopenharmony_ci * tomoyo_del_condition - Delete members in "struct tomoyo_condition". 2728c2ecf20Sopenharmony_ci * 2738c2ecf20Sopenharmony_ci * @element: Pointer to "struct list_head". 2748c2ecf20Sopenharmony_ci * 2758c2ecf20Sopenharmony_ci * Returns nothing. 2768c2ecf20Sopenharmony_ci */ 2778c2ecf20Sopenharmony_civoid tomoyo_del_condition(struct list_head *element) 2788c2ecf20Sopenharmony_ci{ 2798c2ecf20Sopenharmony_ci struct tomoyo_condition *cond = container_of(element, typeof(*cond), 2808c2ecf20Sopenharmony_ci head.list); 2818c2ecf20Sopenharmony_ci const u16 condc = cond->condc; 2828c2ecf20Sopenharmony_ci const u16 numbers_count = cond->numbers_count; 2838c2ecf20Sopenharmony_ci const u16 names_count = cond->names_count; 2848c2ecf20Sopenharmony_ci const u16 argc = cond->argc; 2858c2ecf20Sopenharmony_ci const u16 envc = cond->envc; 2868c2ecf20Sopenharmony_ci unsigned int i; 2878c2ecf20Sopenharmony_ci const struct tomoyo_condition_element *condp 2888c2ecf20Sopenharmony_ci = (const struct tomoyo_condition_element *) (cond + 1); 2898c2ecf20Sopenharmony_ci struct tomoyo_number_union *numbers_p 2908c2ecf20Sopenharmony_ci = (struct tomoyo_number_union *) (condp + condc); 2918c2ecf20Sopenharmony_ci struct tomoyo_name_union *names_p 2928c2ecf20Sopenharmony_ci = (struct tomoyo_name_union *) (numbers_p + numbers_count); 2938c2ecf20Sopenharmony_ci const struct tomoyo_argv *argv 2948c2ecf20Sopenharmony_ci = (const struct tomoyo_argv *) (names_p + names_count); 2958c2ecf20Sopenharmony_ci const struct tomoyo_envp *envp 2968c2ecf20Sopenharmony_ci = (const struct tomoyo_envp *) (argv + argc); 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci for (i = 0; i < numbers_count; i++) 2998c2ecf20Sopenharmony_ci tomoyo_put_number_union(numbers_p++); 3008c2ecf20Sopenharmony_ci for (i = 0; i < names_count; i++) 3018c2ecf20Sopenharmony_ci tomoyo_put_name_union(names_p++); 3028c2ecf20Sopenharmony_ci for (i = 0; i < argc; argv++, i++) 3038c2ecf20Sopenharmony_ci tomoyo_put_name(argv->value); 3048c2ecf20Sopenharmony_ci for (i = 0; i < envc; envp++, i++) { 3058c2ecf20Sopenharmony_ci tomoyo_put_name(envp->name); 3068c2ecf20Sopenharmony_ci tomoyo_put_name(envp->value); 3078c2ecf20Sopenharmony_ci } 3088c2ecf20Sopenharmony_ci} 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci/** 3118c2ecf20Sopenharmony_ci * tomoyo_del_name - Delete members in "struct tomoyo_name". 3128c2ecf20Sopenharmony_ci * 3138c2ecf20Sopenharmony_ci * @element: Pointer to "struct list_head". 3148c2ecf20Sopenharmony_ci * 3158c2ecf20Sopenharmony_ci * Returns nothing. 3168c2ecf20Sopenharmony_ci */ 3178c2ecf20Sopenharmony_cistatic inline void tomoyo_del_name(struct list_head *element) 3188c2ecf20Sopenharmony_ci{ 3198c2ecf20Sopenharmony_ci /* Nothing to do. */ 3208c2ecf20Sopenharmony_ci} 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci/** 3238c2ecf20Sopenharmony_ci * tomoyo_del_path_group - Delete members in "struct tomoyo_path_group". 3248c2ecf20Sopenharmony_ci * 3258c2ecf20Sopenharmony_ci * @element: Pointer to "struct list_head". 3268c2ecf20Sopenharmony_ci * 3278c2ecf20Sopenharmony_ci * Returns nothing. 3288c2ecf20Sopenharmony_ci */ 3298c2ecf20Sopenharmony_cistatic inline void tomoyo_del_path_group(struct list_head *element) 3308c2ecf20Sopenharmony_ci{ 3318c2ecf20Sopenharmony_ci struct tomoyo_path_group *member = 3328c2ecf20Sopenharmony_ci container_of(element, typeof(*member), head.list); 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci tomoyo_put_name(member->member_name); 3358c2ecf20Sopenharmony_ci} 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci/** 3388c2ecf20Sopenharmony_ci * tomoyo_del_group - Delete "struct tomoyo_group". 3398c2ecf20Sopenharmony_ci * 3408c2ecf20Sopenharmony_ci * @element: Pointer to "struct list_head". 3418c2ecf20Sopenharmony_ci * 3428c2ecf20Sopenharmony_ci * Returns nothing. 3438c2ecf20Sopenharmony_ci */ 3448c2ecf20Sopenharmony_cistatic inline void tomoyo_del_group(struct list_head *element) 3458c2ecf20Sopenharmony_ci{ 3468c2ecf20Sopenharmony_ci struct tomoyo_group *group = 3478c2ecf20Sopenharmony_ci container_of(element, typeof(*group), head.list); 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci tomoyo_put_name(group->group_name); 3508c2ecf20Sopenharmony_ci} 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci/** 3538c2ecf20Sopenharmony_ci * tomoyo_del_address_group - Delete members in "struct tomoyo_address_group". 3548c2ecf20Sopenharmony_ci * 3558c2ecf20Sopenharmony_ci * @element: Pointer to "struct list_head". 3568c2ecf20Sopenharmony_ci * 3578c2ecf20Sopenharmony_ci * Returns nothing. 3588c2ecf20Sopenharmony_ci */ 3598c2ecf20Sopenharmony_cistatic inline void tomoyo_del_address_group(struct list_head *element) 3608c2ecf20Sopenharmony_ci{ 3618c2ecf20Sopenharmony_ci /* Nothing to do. */ 3628c2ecf20Sopenharmony_ci} 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci/** 3658c2ecf20Sopenharmony_ci * tomoyo_del_number_group - Delete members in "struct tomoyo_number_group". 3668c2ecf20Sopenharmony_ci * 3678c2ecf20Sopenharmony_ci * @element: Pointer to "struct list_head". 3688c2ecf20Sopenharmony_ci * 3698c2ecf20Sopenharmony_ci * Returns nothing. 3708c2ecf20Sopenharmony_ci */ 3718c2ecf20Sopenharmony_cistatic inline void tomoyo_del_number_group(struct list_head *element) 3728c2ecf20Sopenharmony_ci{ 3738c2ecf20Sopenharmony_ci /* Nothing to do. */ 3748c2ecf20Sopenharmony_ci} 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci/** 3778c2ecf20Sopenharmony_ci * tomoyo_try_to_gc - Try to kfree() an entry. 3788c2ecf20Sopenharmony_ci * 3798c2ecf20Sopenharmony_ci * @type: One of values in "enum tomoyo_policy_id". 3808c2ecf20Sopenharmony_ci * @element: Pointer to "struct list_head". 3818c2ecf20Sopenharmony_ci * 3828c2ecf20Sopenharmony_ci * Returns nothing. 3838c2ecf20Sopenharmony_ci * 3848c2ecf20Sopenharmony_ci * Caller holds tomoyo_policy_lock mutex. 3858c2ecf20Sopenharmony_ci */ 3868c2ecf20Sopenharmony_cistatic void tomoyo_try_to_gc(const enum tomoyo_policy_id type, 3878c2ecf20Sopenharmony_ci struct list_head *element) 3888c2ecf20Sopenharmony_ci{ 3898c2ecf20Sopenharmony_ci /* 3908c2ecf20Sopenharmony_ci * __list_del_entry() guarantees that the list element became no longer 3918c2ecf20Sopenharmony_ci * reachable from the list which the element was originally on (e.g. 3928c2ecf20Sopenharmony_ci * tomoyo_domain_list). Also, synchronize_srcu() guarantees that the 3938c2ecf20Sopenharmony_ci * list element became no longer referenced by syscall users. 3948c2ecf20Sopenharmony_ci */ 3958c2ecf20Sopenharmony_ci __list_del_entry(element); 3968c2ecf20Sopenharmony_ci mutex_unlock(&tomoyo_policy_lock); 3978c2ecf20Sopenharmony_ci synchronize_srcu(&tomoyo_ss); 3988c2ecf20Sopenharmony_ci /* 3998c2ecf20Sopenharmony_ci * However, there are two users which may still be using the list 4008c2ecf20Sopenharmony_ci * element. We need to defer until both users forget this element. 4018c2ecf20Sopenharmony_ci * 4028c2ecf20Sopenharmony_ci * Don't kfree() until "struct tomoyo_io_buffer"->r.{domain,group,acl} 4038c2ecf20Sopenharmony_ci * and "struct tomoyo_io_buffer"->w.domain forget this element. 4048c2ecf20Sopenharmony_ci */ 4058c2ecf20Sopenharmony_ci if (tomoyo_struct_used_by_io_buffer(element)) 4068c2ecf20Sopenharmony_ci goto reinject; 4078c2ecf20Sopenharmony_ci switch (type) { 4088c2ecf20Sopenharmony_ci case TOMOYO_ID_TRANSITION_CONTROL: 4098c2ecf20Sopenharmony_ci tomoyo_del_transition_control(element); 4108c2ecf20Sopenharmony_ci break; 4118c2ecf20Sopenharmony_ci case TOMOYO_ID_MANAGER: 4128c2ecf20Sopenharmony_ci tomoyo_del_manager(element); 4138c2ecf20Sopenharmony_ci break; 4148c2ecf20Sopenharmony_ci case TOMOYO_ID_AGGREGATOR: 4158c2ecf20Sopenharmony_ci tomoyo_del_aggregator(element); 4168c2ecf20Sopenharmony_ci break; 4178c2ecf20Sopenharmony_ci case TOMOYO_ID_GROUP: 4188c2ecf20Sopenharmony_ci tomoyo_del_group(element); 4198c2ecf20Sopenharmony_ci break; 4208c2ecf20Sopenharmony_ci case TOMOYO_ID_PATH_GROUP: 4218c2ecf20Sopenharmony_ci tomoyo_del_path_group(element); 4228c2ecf20Sopenharmony_ci break; 4238c2ecf20Sopenharmony_ci case TOMOYO_ID_ADDRESS_GROUP: 4248c2ecf20Sopenharmony_ci tomoyo_del_address_group(element); 4258c2ecf20Sopenharmony_ci break; 4268c2ecf20Sopenharmony_ci case TOMOYO_ID_NUMBER_GROUP: 4278c2ecf20Sopenharmony_ci tomoyo_del_number_group(element); 4288c2ecf20Sopenharmony_ci break; 4298c2ecf20Sopenharmony_ci case TOMOYO_ID_CONDITION: 4308c2ecf20Sopenharmony_ci tomoyo_del_condition(element); 4318c2ecf20Sopenharmony_ci break; 4328c2ecf20Sopenharmony_ci case TOMOYO_ID_NAME: 4338c2ecf20Sopenharmony_ci /* 4348c2ecf20Sopenharmony_ci * Don't kfree() until all "struct tomoyo_io_buffer"->r.w[] 4358c2ecf20Sopenharmony_ci * forget this element. 4368c2ecf20Sopenharmony_ci */ 4378c2ecf20Sopenharmony_ci if (tomoyo_name_used_by_io_buffer 4388c2ecf20Sopenharmony_ci (container_of(element, typeof(struct tomoyo_name), 4398c2ecf20Sopenharmony_ci head.list)->entry.name)) 4408c2ecf20Sopenharmony_ci goto reinject; 4418c2ecf20Sopenharmony_ci tomoyo_del_name(element); 4428c2ecf20Sopenharmony_ci break; 4438c2ecf20Sopenharmony_ci case TOMOYO_ID_ACL: 4448c2ecf20Sopenharmony_ci tomoyo_del_acl(element); 4458c2ecf20Sopenharmony_ci break; 4468c2ecf20Sopenharmony_ci case TOMOYO_ID_DOMAIN: 4478c2ecf20Sopenharmony_ci /* 4488c2ecf20Sopenharmony_ci * Don't kfree() until all "struct cred"->security forget this 4498c2ecf20Sopenharmony_ci * element. 4508c2ecf20Sopenharmony_ci */ 4518c2ecf20Sopenharmony_ci if (atomic_read(&container_of 4528c2ecf20Sopenharmony_ci (element, typeof(struct tomoyo_domain_info), 4538c2ecf20Sopenharmony_ci list)->users)) 4548c2ecf20Sopenharmony_ci goto reinject; 4558c2ecf20Sopenharmony_ci break; 4568c2ecf20Sopenharmony_ci case TOMOYO_MAX_POLICY: 4578c2ecf20Sopenharmony_ci break; 4588c2ecf20Sopenharmony_ci } 4598c2ecf20Sopenharmony_ci mutex_lock(&tomoyo_policy_lock); 4608c2ecf20Sopenharmony_ci if (type == TOMOYO_ID_DOMAIN) 4618c2ecf20Sopenharmony_ci tomoyo_del_domain(element); 4628c2ecf20Sopenharmony_ci tomoyo_memory_free(element); 4638c2ecf20Sopenharmony_ci return; 4648c2ecf20Sopenharmony_cireinject: 4658c2ecf20Sopenharmony_ci /* 4668c2ecf20Sopenharmony_ci * We can safely reinject this element here bacause 4678c2ecf20Sopenharmony_ci * (1) Appending list elements and removing list elements are protected 4688c2ecf20Sopenharmony_ci * by tomoyo_policy_lock mutex. 4698c2ecf20Sopenharmony_ci * (2) Only this function removes list elements and this function is 4708c2ecf20Sopenharmony_ci * exclusively executed by tomoyo_gc_mutex mutex. 4718c2ecf20Sopenharmony_ci * are true. 4728c2ecf20Sopenharmony_ci */ 4738c2ecf20Sopenharmony_ci mutex_lock(&tomoyo_policy_lock); 4748c2ecf20Sopenharmony_ci list_add_rcu(element, element->prev); 4758c2ecf20Sopenharmony_ci} 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_ci/** 4788c2ecf20Sopenharmony_ci * tomoyo_collect_member - Delete elements with "struct tomoyo_acl_head". 4798c2ecf20Sopenharmony_ci * 4808c2ecf20Sopenharmony_ci * @id: One of values in "enum tomoyo_policy_id". 4818c2ecf20Sopenharmony_ci * @member_list: Pointer to "struct list_head". 4828c2ecf20Sopenharmony_ci * 4838c2ecf20Sopenharmony_ci * Returns nothing. 4848c2ecf20Sopenharmony_ci */ 4858c2ecf20Sopenharmony_cistatic void tomoyo_collect_member(const enum tomoyo_policy_id id, 4868c2ecf20Sopenharmony_ci struct list_head *member_list) 4878c2ecf20Sopenharmony_ci{ 4888c2ecf20Sopenharmony_ci struct tomoyo_acl_head *member; 4898c2ecf20Sopenharmony_ci struct tomoyo_acl_head *tmp; 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_ci list_for_each_entry_safe(member, tmp, member_list, list) { 4928c2ecf20Sopenharmony_ci if (!member->is_deleted) 4938c2ecf20Sopenharmony_ci continue; 4948c2ecf20Sopenharmony_ci member->is_deleted = TOMOYO_GC_IN_PROGRESS; 4958c2ecf20Sopenharmony_ci tomoyo_try_to_gc(id, &member->list); 4968c2ecf20Sopenharmony_ci } 4978c2ecf20Sopenharmony_ci} 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_ci/** 5008c2ecf20Sopenharmony_ci * tomoyo_collect_acl - Delete elements in "struct tomoyo_domain_info". 5018c2ecf20Sopenharmony_ci * 5028c2ecf20Sopenharmony_ci * @list: Pointer to "struct list_head". 5038c2ecf20Sopenharmony_ci * 5048c2ecf20Sopenharmony_ci * Returns nothing. 5058c2ecf20Sopenharmony_ci */ 5068c2ecf20Sopenharmony_cistatic void tomoyo_collect_acl(struct list_head *list) 5078c2ecf20Sopenharmony_ci{ 5088c2ecf20Sopenharmony_ci struct tomoyo_acl_info *acl; 5098c2ecf20Sopenharmony_ci struct tomoyo_acl_info *tmp; 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_ci list_for_each_entry_safe(acl, tmp, list, list) { 5128c2ecf20Sopenharmony_ci if (!acl->is_deleted) 5138c2ecf20Sopenharmony_ci continue; 5148c2ecf20Sopenharmony_ci acl->is_deleted = TOMOYO_GC_IN_PROGRESS; 5158c2ecf20Sopenharmony_ci tomoyo_try_to_gc(TOMOYO_ID_ACL, &acl->list); 5168c2ecf20Sopenharmony_ci } 5178c2ecf20Sopenharmony_ci} 5188c2ecf20Sopenharmony_ci 5198c2ecf20Sopenharmony_ci/** 5208c2ecf20Sopenharmony_ci * tomoyo_collect_entry - Try to kfree() deleted elements. 5218c2ecf20Sopenharmony_ci * 5228c2ecf20Sopenharmony_ci * Returns nothing. 5238c2ecf20Sopenharmony_ci */ 5248c2ecf20Sopenharmony_cistatic void tomoyo_collect_entry(void) 5258c2ecf20Sopenharmony_ci{ 5268c2ecf20Sopenharmony_ci int i; 5278c2ecf20Sopenharmony_ci enum tomoyo_policy_id id; 5288c2ecf20Sopenharmony_ci struct tomoyo_policy_namespace *ns; 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_ci mutex_lock(&tomoyo_policy_lock); 5318c2ecf20Sopenharmony_ci { 5328c2ecf20Sopenharmony_ci struct tomoyo_domain_info *domain; 5338c2ecf20Sopenharmony_ci struct tomoyo_domain_info *tmp; 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_ci list_for_each_entry_safe(domain, tmp, &tomoyo_domain_list, 5368c2ecf20Sopenharmony_ci list) { 5378c2ecf20Sopenharmony_ci tomoyo_collect_acl(&domain->acl_info_list); 5388c2ecf20Sopenharmony_ci if (!domain->is_deleted || atomic_read(&domain->users)) 5398c2ecf20Sopenharmony_ci continue; 5408c2ecf20Sopenharmony_ci tomoyo_try_to_gc(TOMOYO_ID_DOMAIN, &domain->list); 5418c2ecf20Sopenharmony_ci } 5428c2ecf20Sopenharmony_ci } 5438c2ecf20Sopenharmony_ci list_for_each_entry(ns, &tomoyo_namespace_list, namespace_list) { 5448c2ecf20Sopenharmony_ci for (id = 0; id < TOMOYO_MAX_POLICY; id++) 5458c2ecf20Sopenharmony_ci tomoyo_collect_member(id, &ns->policy_list[id]); 5468c2ecf20Sopenharmony_ci for (i = 0; i < TOMOYO_MAX_ACL_GROUPS; i++) 5478c2ecf20Sopenharmony_ci tomoyo_collect_acl(&ns->acl_group[i]); 5488c2ecf20Sopenharmony_ci } 5498c2ecf20Sopenharmony_ci { 5508c2ecf20Sopenharmony_ci struct tomoyo_shared_acl_head *ptr; 5518c2ecf20Sopenharmony_ci struct tomoyo_shared_acl_head *tmp; 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_ci list_for_each_entry_safe(ptr, tmp, &tomoyo_condition_list, 5548c2ecf20Sopenharmony_ci list) { 5558c2ecf20Sopenharmony_ci if (atomic_read(&ptr->users) > 0) 5568c2ecf20Sopenharmony_ci continue; 5578c2ecf20Sopenharmony_ci atomic_set(&ptr->users, TOMOYO_GC_IN_PROGRESS); 5588c2ecf20Sopenharmony_ci tomoyo_try_to_gc(TOMOYO_ID_CONDITION, &ptr->list); 5598c2ecf20Sopenharmony_ci } 5608c2ecf20Sopenharmony_ci } 5618c2ecf20Sopenharmony_ci list_for_each_entry(ns, &tomoyo_namespace_list, namespace_list) { 5628c2ecf20Sopenharmony_ci for (i = 0; i < TOMOYO_MAX_GROUP; i++) { 5638c2ecf20Sopenharmony_ci struct list_head *list = &ns->group_list[i]; 5648c2ecf20Sopenharmony_ci struct tomoyo_group *group; 5658c2ecf20Sopenharmony_ci struct tomoyo_group *tmp; 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_ci switch (i) { 5688c2ecf20Sopenharmony_ci case 0: 5698c2ecf20Sopenharmony_ci id = TOMOYO_ID_PATH_GROUP; 5708c2ecf20Sopenharmony_ci break; 5718c2ecf20Sopenharmony_ci case 1: 5728c2ecf20Sopenharmony_ci id = TOMOYO_ID_NUMBER_GROUP; 5738c2ecf20Sopenharmony_ci break; 5748c2ecf20Sopenharmony_ci default: 5758c2ecf20Sopenharmony_ci id = TOMOYO_ID_ADDRESS_GROUP; 5768c2ecf20Sopenharmony_ci break; 5778c2ecf20Sopenharmony_ci } 5788c2ecf20Sopenharmony_ci list_for_each_entry_safe(group, tmp, list, head.list) { 5798c2ecf20Sopenharmony_ci tomoyo_collect_member(id, &group->member_list); 5808c2ecf20Sopenharmony_ci if (!list_empty(&group->member_list) || 5818c2ecf20Sopenharmony_ci atomic_read(&group->head.users) > 0) 5828c2ecf20Sopenharmony_ci continue; 5838c2ecf20Sopenharmony_ci atomic_set(&group->head.users, 5848c2ecf20Sopenharmony_ci TOMOYO_GC_IN_PROGRESS); 5858c2ecf20Sopenharmony_ci tomoyo_try_to_gc(TOMOYO_ID_GROUP, 5868c2ecf20Sopenharmony_ci &group->head.list); 5878c2ecf20Sopenharmony_ci } 5888c2ecf20Sopenharmony_ci } 5898c2ecf20Sopenharmony_ci } 5908c2ecf20Sopenharmony_ci for (i = 0; i < TOMOYO_MAX_HASH; i++) { 5918c2ecf20Sopenharmony_ci struct list_head *list = &tomoyo_name_list[i]; 5928c2ecf20Sopenharmony_ci struct tomoyo_shared_acl_head *ptr; 5938c2ecf20Sopenharmony_ci struct tomoyo_shared_acl_head *tmp; 5948c2ecf20Sopenharmony_ci 5958c2ecf20Sopenharmony_ci list_for_each_entry_safe(ptr, tmp, list, list) { 5968c2ecf20Sopenharmony_ci if (atomic_read(&ptr->users) > 0) 5978c2ecf20Sopenharmony_ci continue; 5988c2ecf20Sopenharmony_ci atomic_set(&ptr->users, TOMOYO_GC_IN_PROGRESS); 5998c2ecf20Sopenharmony_ci tomoyo_try_to_gc(TOMOYO_ID_NAME, &ptr->list); 6008c2ecf20Sopenharmony_ci } 6018c2ecf20Sopenharmony_ci } 6028c2ecf20Sopenharmony_ci mutex_unlock(&tomoyo_policy_lock); 6038c2ecf20Sopenharmony_ci} 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_ci/** 6068c2ecf20Sopenharmony_ci * tomoyo_gc_thread - Garbage collector thread function. 6078c2ecf20Sopenharmony_ci * 6088c2ecf20Sopenharmony_ci * @unused: Unused. 6098c2ecf20Sopenharmony_ci * 6108c2ecf20Sopenharmony_ci * Returns 0. 6118c2ecf20Sopenharmony_ci */ 6128c2ecf20Sopenharmony_cistatic int tomoyo_gc_thread(void *unused) 6138c2ecf20Sopenharmony_ci{ 6148c2ecf20Sopenharmony_ci /* Garbage collector thread is exclusive. */ 6158c2ecf20Sopenharmony_ci static DEFINE_MUTEX(tomoyo_gc_mutex); 6168c2ecf20Sopenharmony_ci 6178c2ecf20Sopenharmony_ci if (!mutex_trylock(&tomoyo_gc_mutex)) 6188c2ecf20Sopenharmony_ci goto out; 6198c2ecf20Sopenharmony_ci tomoyo_collect_entry(); 6208c2ecf20Sopenharmony_ci { 6218c2ecf20Sopenharmony_ci struct tomoyo_io_buffer *head; 6228c2ecf20Sopenharmony_ci struct tomoyo_io_buffer *tmp; 6238c2ecf20Sopenharmony_ci 6248c2ecf20Sopenharmony_ci spin_lock(&tomoyo_io_buffer_list_lock); 6258c2ecf20Sopenharmony_ci list_for_each_entry_safe(head, tmp, &tomoyo_io_buffer_list, 6268c2ecf20Sopenharmony_ci list) { 6278c2ecf20Sopenharmony_ci if (head->users) 6288c2ecf20Sopenharmony_ci continue; 6298c2ecf20Sopenharmony_ci list_del(&head->list); 6308c2ecf20Sopenharmony_ci kfree(head->read_buf); 6318c2ecf20Sopenharmony_ci kfree(head->write_buf); 6328c2ecf20Sopenharmony_ci kfree(head); 6338c2ecf20Sopenharmony_ci } 6348c2ecf20Sopenharmony_ci spin_unlock(&tomoyo_io_buffer_list_lock); 6358c2ecf20Sopenharmony_ci } 6368c2ecf20Sopenharmony_ci mutex_unlock(&tomoyo_gc_mutex); 6378c2ecf20Sopenharmony_ciout: 6388c2ecf20Sopenharmony_ci /* This acts as do_exit(0). */ 6398c2ecf20Sopenharmony_ci return 0; 6408c2ecf20Sopenharmony_ci} 6418c2ecf20Sopenharmony_ci 6428c2ecf20Sopenharmony_ci/** 6438c2ecf20Sopenharmony_ci * tomoyo_notify_gc - Register/unregister /sys/kernel/security/tomoyo/ users. 6448c2ecf20Sopenharmony_ci * 6458c2ecf20Sopenharmony_ci * @head: Pointer to "struct tomoyo_io_buffer". 6468c2ecf20Sopenharmony_ci * @is_register: True if register, false if unregister. 6478c2ecf20Sopenharmony_ci * 6488c2ecf20Sopenharmony_ci * Returns nothing. 6498c2ecf20Sopenharmony_ci */ 6508c2ecf20Sopenharmony_civoid tomoyo_notify_gc(struct tomoyo_io_buffer *head, const bool is_register) 6518c2ecf20Sopenharmony_ci{ 6528c2ecf20Sopenharmony_ci bool is_write = false; 6538c2ecf20Sopenharmony_ci 6548c2ecf20Sopenharmony_ci spin_lock(&tomoyo_io_buffer_list_lock); 6558c2ecf20Sopenharmony_ci if (is_register) { 6568c2ecf20Sopenharmony_ci head->users = 1; 6578c2ecf20Sopenharmony_ci list_add(&head->list, &tomoyo_io_buffer_list); 6588c2ecf20Sopenharmony_ci } else { 6598c2ecf20Sopenharmony_ci is_write = head->write_buf != NULL; 6608c2ecf20Sopenharmony_ci if (!--head->users) { 6618c2ecf20Sopenharmony_ci list_del(&head->list); 6628c2ecf20Sopenharmony_ci kfree(head->read_buf); 6638c2ecf20Sopenharmony_ci kfree(head->write_buf); 6648c2ecf20Sopenharmony_ci kfree(head); 6658c2ecf20Sopenharmony_ci } 6668c2ecf20Sopenharmony_ci } 6678c2ecf20Sopenharmony_ci spin_unlock(&tomoyo_io_buffer_list_lock); 6688c2ecf20Sopenharmony_ci if (is_write) 6698c2ecf20Sopenharmony_ci kthread_run(tomoyo_gc_thread, NULL, "GC for TOMOYO"); 6708c2ecf20Sopenharmony_ci} 671