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
20*06a1c40aSMickaël Salaün struct landlock_object *
landlock_create_object(const struct landlock_object_underops * const underops,void * const underobj)21*06a1c40aSMickaë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