Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0-only 2 : /* 3 : * Landlock LSM - Object management 4 : * 5 : * Copyright © 2016-2020 Mickaël Salaün <mic@digikod.net> 6 : * Copyright © 2018-2020 ANSSI 7 : */ 8 : 9 : #include <linux/bug.h> 10 : #include <linux/compiler_types.h> 11 : #include <linux/err.h> 12 : #include <linux/kernel.h> 13 : #include <linux/rcupdate.h> 14 : #include <linux/refcount.h> 15 : #include <linux/slab.h> 16 : #include <linux/spinlock.h> 17 : 18 : #include "object.h" 19 : 20 92 : struct landlock_object *landlock_create_object( 21 : const struct landlock_object_underops *const underops, 22 : void *const underobj) 23 : { 24 92 : struct landlock_object *new_object; 25 : 26 92 : if (WARN_ON_ONCE(!underops || !underobj)) 27 92 : return ERR_PTR(-ENOENT); 28 92 : new_object = kzalloc(sizeof(*new_object), GFP_KERNEL_ACCOUNT); 29 92 : if (!new_object) 30 92 : return ERR_PTR(-ENOMEM); 31 92 : refcount_set(&new_object->usage, 1); 32 92 : spin_lock_init(&new_object->lock); 33 92 : new_object->underops = underops; 34 92 : new_object->underobj = underobj; 35 92 : return new_object; 36 : } 37 : 38 : /* 39 : * The caller must own the object (i.e. thanks to object->usage) to safely put 40 : * it. 41 : */ 42 517 : void landlock_put_object(struct landlock_object *const object) 43 : { 44 : /* 45 : * The call to @object->underops->release(object) might sleep, e.g. 46 : * because of iput(). 47 : */ 48 517 : might_sleep(); 49 517 : if (!object) 50 : return; 51 : 52 : /* 53 : * If the @object's refcount cannot drop to zero, we can just decrement 54 : * the refcount without holding a lock. Otherwise, the decrement must 55 : * happen under @object->lock for synchronization with things like 56 : * get_inode_object(). 57 : */ 58 517 : if (refcount_dec_and_lock(&object->usage, &object->lock)) { 59 92 : __acquire(&object->lock); 60 : /* 61 : * With @object->lock initially held, remove the reference from 62 : * @object->underobj to @object (if it still exists). 63 : */ 64 92 : object->underops->release(object); 65 92 : kfree_rcu(object, rcu_free); 66 : } 67 : }