cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

gc.c (17027B)


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