blob: ce545f99259e5291ef6c99142e3e2ffccf19cde4 [file] [log] [blame]
Thomas Gleixnerb886d83c2019-06-01 10:08:55 +02001// SPDX-License-Identifier: GPL-2.0-only
John Johansen121d4a92017-01-16 00:42:17 -08002/*
3 * AppArmor security module
4 *
5 * This file contains AppArmor security identifier (secid) manipulation fns
6 *
John Johansenc0929212017-07-31 17:36:45 -07007 * Copyright 2009-2017 Canonical Ltd.
John Johansen121d4a92017-01-16 00:42:17 -08008 *
John Johansenc0929212017-07-31 17:36:45 -07009 * 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.
John Johansen121d4a92017-01-16 00:42:17 -080011 */
12
John Johansen121d4a92017-01-16 00:42:17 -080013#include <linux/errno.h>
14#include <linux/err.h>
John Johansenc0929212017-07-31 17:36:45 -070015#include <linux/gfp.h>
Matthew Wilcox99cc45e2018-05-22 02:32:59 -070016#include <linux/idr.h>
John Johansenc0929212017-07-31 17:36:45 -070017#include <linux/slab.h>
18#include <linux/spinlock.h>
John Johansen121d4a92017-01-16 00:42:17 -080019
John Johansenc0929212017-07-31 17:36:45 -070020#include "include/cred.h"
21#include "include/lib.h"
John Johansen121d4a92017-01-16 00:42:17 -080022#include "include/secid.h"
John Johansenc0929212017-07-31 17:36:45 -070023#include "include/label.h"
24#include "include/policy_ns.h"
John Johansen121d4a92017-01-16 00:42:17 -080025
John Johansenc0929212017-07-31 17:36:45 -070026/*
27 * secids - do not pin labels with a refcount. They rely on the label
28 * properly updating/freeing them
John Johansenc0929212017-07-31 17:36:45 -070029 */
Matthew Garrett617a6292018-05-24 13:27:45 -070030#define AA_FIRST_SECID 2
John Johansena4c3f892018-06-04 19:44:59 -070031
Matthew Wilcox99cc45e2018-05-22 02:32:59 -070032static DEFINE_IDR(aa_secids);
John Johansen121d4a92017-01-16 00:42:17 -080033static DEFINE_SPINLOCK(secid_lock);
34
John Johansenc0929212017-07-31 17:36:45 -070035/*
36 * TODO: allow policy to reserve a secid range?
37 * TODO: add secid pinning
38 * TODO: use secid_update in label replace
39 */
40
John Johansenc0929212017-07-31 17:36:45 -070041/**
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 */
46void aa_secid_update(u32 secid, struct aa_label *label)
47{
John Johansenc0929212017-07-31 17:36:45 -070048 unsigned long flags;
49
50 spin_lock_irqsave(&secid_lock, flags);
Matthew Wilcox99cc45e2018-05-22 02:32:59 -070051 idr_replace(&aa_secids, label, secid);
John Johansenc0929212017-07-31 17:36:45 -070052 spin_unlock_irqrestore(&secid_lock, flags);
53}
54
55/**
56 *
57 * see label for inverse aa_label_to_secid
58 */
59struct aa_label *aa_secid_to_label(u32 secid)
60{
61 struct aa_label *label;
62
63 rcu_read_lock();
Matthew Wilcox99cc45e2018-05-22 02:32:59 -070064 label = idr_find(&aa_secids, secid);
John Johansenc0929212017-07-31 17:36:45 -070065 rcu_read_unlock();
66
67 return label;
68}
69
70int 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);
John Johansen52e7128e2018-05-04 01:57:47 -070074 int len;
John Johansenc0929212017-07-31 17:36:45 -070075
John Johansenc0929212017-07-31 17:36:45 -070076 AA_BUG(!seclen);
77
78 if (!label)
79 return -EINVAL;
80
81 if (secdata)
John Johansen52e7128e2018-05-04 01:57:47 -070082 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);
John Johansenc0929212017-07-31 17:36:45 -070086 else
John Johansen52e7128e2018-05-04 01:57:47 -070087 len = aa_label_snxprint(NULL, 0, root_ns, label,
88 FLAG_SHOW_MODE | FLAG_VIEW_SUBNS |
89 FLAG_HIDDEN_UNCONFINED | FLAG_ABS_ROOT);
90 if (len < 0)
John Johansenc0929212017-07-31 17:36:45 -070091 return -ENOMEM;
92
John Johansen52e7128e2018-05-04 01:57:47 -070093 *seclen = len;
94
John Johansenc0929212017-07-31 17:36:45 -070095 return 0;
96}
97
John Johansenc0929212017-07-31 17:36:45 -070098int apparmor_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
99{
100 struct aa_label *label;
101
102 label = aa_label_strn_parse(&root_ns->unconfined->label, secdata,
103 seclen, GFP_KERNEL, false, false);
104 if (IS_ERR(label))
105 return PTR_ERR(label);
106 *secid = label->secid;
107
108 return 0;
109}
110
111void apparmor_release_secctx(char *secdata, u32 seclen)
112{
113 kfree(secdata);
114}
115
John Johansen121d4a92017-01-16 00:42:17 -0800116/**
117 * aa_alloc_secid - allocate a new secid for a profile
John Johansena4c3f892018-06-04 19:44:59 -0700118 * @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
John Johansen121d4a92017-01-16 00:42:17 -0800123 */
John Johansena4c3f892018-06-04 19:44:59 -0700124int aa_alloc_secid(struct aa_label *label, gfp_t gfp)
John Johansen121d4a92017-01-16 00:42:17 -0800125{
John Johansenc0929212017-07-31 17:36:45 -0700126 unsigned long flags;
John Johansena4c3f892018-06-04 19:44:59 -0700127 int ret;
John Johansen121d4a92017-01-16 00:42:17 -0800128
Matthew Wilcox99cc45e2018-05-22 02:32:59 -0700129 idr_preload(gfp);
130 spin_lock_irqsave(&secid_lock, flags);
John Johansena4c3f892018-06-04 19:44:59 -0700131 ret = idr_alloc(&aa_secids, label, AA_FIRST_SECID, 0, GFP_ATOMIC);
Matthew Wilcox99cc45e2018-05-22 02:32:59 -0700132 spin_unlock_irqrestore(&secid_lock, flags);
133 idr_preload_end();
John Johansenc0929212017-07-31 17:36:45 -0700134
John Johansena4c3f892018-06-04 19:44:59 -0700135 if (ret < 0) {
136 label->secid = AA_SECID_INVALID;
137 return ret;
138 }
139
140 AA_BUG(ret == AA_SECID_INVALID);
141 label->secid = ret;
142 return 0;
John Johansen121d4a92017-01-16 00:42:17 -0800143}
144
145/**
146 * aa_free_secid - free a secid
147 * @secid: secid to free
148 */
149void aa_free_secid(u32 secid)
150{
John Johansenc0929212017-07-31 17:36:45 -0700151 unsigned long flags;
152
153 spin_lock_irqsave(&secid_lock, flags);
Matthew Wilcox99cc45e2018-05-22 02:32:59 -0700154 idr_remove(&aa_secids, secid);
John Johansenc0929212017-07-31 17:36:45 -0700155 spin_unlock_irqrestore(&secid_lock, flags);
John Johansen121d4a92017-01-16 00:42:17 -0800156}
John Johansena4c3f892018-06-04 19:44:59 -0700157
158void aa_secids_init(void)
159{
160 idr_init_base(&aa_secids, AA_FIRST_SECID);
161}