xref: /openbmc/linux/security/landlock/object.c (revision 695c7c06)
190945448SMickaël Salaün // SPDX-License-Identifier: GPL-2.0-only
290945448SMickaël Salaün /*
390945448SMickaël Salaün  * Landlock LSM - Object management
490945448SMickaël Salaün  *
590945448SMickaël Salaün  * Copyright © 2016-2020 Mickaël Salaün <mic@digikod.net>
690945448SMickaël Salaün  * Copyright © 2018-2020 ANSSI
790945448SMickaël Salaün  */
890945448SMickaël Salaün 
990945448SMickaël Salaün #include <linux/bug.h>
1090945448SMickaël Salaün #include <linux/compiler_types.h>
1190945448SMickaël Salaün #include <linux/err.h>
1290945448SMickaël Salaün #include <linux/kernel.h>
1390945448SMickaël Salaün #include <linux/rcupdate.h>
1490945448SMickaël Salaün #include <linux/refcount.h>
1590945448SMickaël Salaün #include <linux/slab.h>
1690945448SMickaël Salaün #include <linux/spinlock.h>
1790945448SMickaël Salaün 
1890945448SMickaël Salaün #include "object.h"
1990945448SMickaël Salaün 
20695c7c06SMickaël Salaün struct landlock_object *
landlock_create_object(const struct landlock_object_underops * const underops,void * const underobj)21695c7c06SMickaël Salaün landlock_create_object(const struct landlock_object_underops *const underops,
2290945448SMickaël Salaün 		       void *const underobj)
2390945448SMickaël Salaün {
2490945448SMickaël Salaün 	struct landlock_object *new_object;
2590945448SMickaël Salaün 
2690945448SMickaël Salaün 	if (WARN_ON_ONCE(!underops || !underobj))
2790945448SMickaël Salaün 		return ERR_PTR(-ENOENT);
2890945448SMickaël Salaün 	new_object = kzalloc(sizeof(*new_object), GFP_KERNEL_ACCOUNT);
2990945448SMickaël Salaün 	if (!new_object)
3090945448SMickaël Salaün 		return ERR_PTR(-ENOMEM);
3190945448SMickaël Salaün 	refcount_set(&new_object->usage, 1);
3290945448SMickaël Salaün 	spin_lock_init(&new_object->lock);
3390945448SMickaël Salaün 	new_object->underops = underops;
3490945448SMickaël Salaün 	new_object->underobj = underobj;
3590945448SMickaël Salaün 	return new_object;
3690945448SMickaël Salaün }
3790945448SMickaël Salaün 
3890945448SMickaël Salaün /*
3990945448SMickaël Salaün  * The caller must own the object (i.e. thanks to object->usage) to safely put
4090945448SMickaël Salaün  * it.
4190945448SMickaël Salaün  */
landlock_put_object(struct landlock_object * const object)4290945448SMickaël Salaün void landlock_put_object(struct landlock_object *const object)
4390945448SMickaël Salaün {
4490945448SMickaël Salaün 	/*
4590945448SMickaël Salaün 	 * The call to @object->underops->release(object) might sleep, e.g.
4690945448SMickaël Salaün 	 * because of iput().
4790945448SMickaël Salaün 	 */
4890945448SMickaël Salaün 	might_sleep();
4990945448SMickaël Salaün 	if (!object)
5090945448SMickaël Salaün 		return;
5190945448SMickaël Salaün 
5290945448SMickaël Salaün 	/*
5390945448SMickaël Salaün 	 * If the @object's refcount cannot drop to zero, we can just decrement
5490945448SMickaël Salaün 	 * the refcount without holding a lock. Otherwise, the decrement must
5590945448SMickaël Salaün 	 * happen under @object->lock for synchronization with things like
5690945448SMickaël Salaün 	 * get_inode_object().
5790945448SMickaël Salaün 	 */
5890945448SMickaël Salaün 	if (refcount_dec_and_lock(&object->usage, &object->lock)) {
5990945448SMickaël Salaün 		__acquire(&object->lock);
6090945448SMickaël Salaün 		/*
6190945448SMickaël Salaün 		 * With @object->lock initially held, remove the reference from
6290945448SMickaël Salaün 		 * @object->underobj to @object (if it still exists).
6390945448SMickaël Salaün 		 */
6490945448SMickaël Salaün 		object->underops->release(object);
6590945448SMickaël Salaün 		kfree_rcu(object, rcu_free);
6690945448SMickaël Salaün 	}
6790945448SMickaël Salaün }
68