Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-only 2 : : /* 3 : : * AppArmor security module 4 : : * 5 : : * This file contains AppArmor security identifier (secid) manipulation fns 6 : : * 7 : : * Copyright 2009-2017 Canonical Ltd. 8 : : * 9 : : * AppArmor allocates a unique secid for every label used. If a label 10 : : * is replaced it receives the secid of the label it is replacing. 11 : : */ 12 : : 13 : : #include <linux/errno.h> 14 : : #include <linux/err.h> 15 : : #include <linux/gfp.h> 16 : : #include <linux/idr.h> 17 : : #include <linux/slab.h> 18 : : #include <linux/spinlock.h> 19 : : 20 : : #include "include/cred.h" 21 : : #include "include/lib.h" 22 : : #include "include/secid.h" 23 : : #include "include/label.h" 24 : : #include "include/policy_ns.h" 25 : : 26 : : /* 27 : : * secids - do not pin labels with a refcount. They rely on the label 28 : : * properly updating/freeing them 29 : : */ 30 : : #define AA_FIRST_SECID 2 31 : : 32 : : static DEFINE_IDR(aa_secids); 33 : : static DEFINE_SPINLOCK(secid_lock); 34 : : 35 : : /* 36 : : * TODO: allow policy to reserve a secid range? 37 : : * TODO: add secid pinning 38 : : * TODO: use secid_update in label replace 39 : : */ 40 : : 41 : : /** 42 : : * aa_secid_update - update a secid mapping to a new label 43 : : * @secid: secid to update 44 : : * @label: label the secid will now map to 45 : : */ 46 : 0 : void aa_secid_update(u32 secid, struct aa_label *label) 47 : : { 48 : : unsigned long flags; 49 : : 50 : 0 : spin_lock_irqsave(&secid_lock, flags); 51 : 0 : idr_replace(&aa_secids, label, secid); 52 : : spin_unlock_irqrestore(&secid_lock, flags); 53 : 0 : } 54 : : 55 : : /** 56 : : * 57 : : * see label for inverse aa_label_to_secid 58 : : */ 59 : 0 : struct aa_label *aa_secid_to_label(u32 secid) 60 : : { 61 : : struct aa_label *label; 62 : : 63 : : rcu_read_lock(); 64 : 0 : label = idr_find(&aa_secids, secid); 65 : : rcu_read_unlock(); 66 : : 67 : 0 : return label; 68 : : } 69 : : 70 : 0 : int apparmor_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) 71 : : { 72 : : /* TODO: cache secctx and ref count so we don't have to recreate */ 73 : : struct aa_label *label = aa_secid_to_label(secid); 74 : : int len; 75 : : 76 : : AA_BUG(!seclen); 77 : : 78 : 0 : if (!label) 79 : : return -EINVAL; 80 : : 81 : 0 : if (secdata) 82 : 0 : len = aa_label_asxprint(secdata, root_ns, label, 83 : : FLAG_SHOW_MODE | FLAG_VIEW_SUBNS | 84 : : FLAG_HIDDEN_UNCONFINED | FLAG_ABS_ROOT, 85 : : GFP_ATOMIC); 86 : : else 87 : 0 : len = aa_label_snxprint(NULL, 0, root_ns, label, 88 : : FLAG_SHOW_MODE | FLAG_VIEW_SUBNS | 89 : : FLAG_HIDDEN_UNCONFINED | FLAG_ABS_ROOT); 90 : 0 : if (len < 0) 91 : : return -ENOMEM; 92 : : 93 : 0 : *seclen = len; 94 : : 95 : 0 : return 0; 96 : : } 97 : : 98 : 0 : int apparmor_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid) 99 : : { 100 : : struct aa_label *label; 101 : : 102 : 0 : label = aa_label_strn_parse(&root_ns->unconfined->label, secdata, 103 : : seclen, GFP_KERNEL, false, false); 104 : 0 : if (IS_ERR(label)) 105 : 0 : return PTR_ERR(label); 106 : 0 : *secid = label->secid; 107 : : 108 : 0 : return 0; 109 : : } 110 : : 111 : 0 : void apparmor_release_secctx(char *secdata, u32 seclen) 112 : : { 113 : 0 : kfree(secdata); 114 : 0 : } 115 : : 116 : : /** 117 : : * aa_alloc_secid - allocate a new secid for a profile 118 : : * @label: the label to allocate a secid for 119 : : * @gfp: memory allocation flags 120 : : * 121 : : * Returns: 0 with @label->secid initialized 122 : : * <0 returns error with @label->secid set to AA_SECID_INVALID 123 : : */ 124 : 0 : int aa_alloc_secid(struct aa_label *label, gfp_t gfp) 125 : : { 126 : : unsigned long flags; 127 : : int ret; 128 : : 129 : 0 : idr_preload(gfp); 130 : 0 : spin_lock_irqsave(&secid_lock, flags); 131 : 0 : ret = idr_alloc(&aa_secids, label, AA_FIRST_SECID, 0, GFP_ATOMIC); 132 : : spin_unlock_irqrestore(&secid_lock, flags); 133 : : idr_preload_end(); 134 : : 135 : 0 : if (ret < 0) { 136 : 0 : label->secid = AA_SECID_INVALID; 137 : 0 : return ret; 138 : : } 139 : : 140 : : AA_BUG(ret == AA_SECID_INVALID); 141 : 0 : label->secid = ret; 142 : 0 : return 0; 143 : : } 144 : : 145 : : /** 146 : : * aa_free_secid - free a secid 147 : : * @secid: secid to free 148 : : */ 149 : 0 : void aa_free_secid(u32 secid) 150 : : { 151 : : unsigned long flags; 152 : : 153 : 0 : spin_lock_irqsave(&secid_lock, flags); 154 : 0 : idr_remove(&aa_secids, secid); 155 : : spin_unlock_irqrestore(&secid_lock, flags); 156 : 0 : } 157 : : 158 : 0 : void aa_secids_init(void) 159 : : { 160 : : idr_init_base(&aa_secids, AA_FIRST_SECID); 161 : 0 : }