Skip to content

Commit 99cc45e

Browse files
Matthew Wilcoxjrjohansen
authored andcommitted
apparmor: Use an IDR to allocate apparmor secids
Replace the custom usage of the radix tree to store a list of free IDs with the IDR. Signed-off-by: Matthew Wilcox <mawilcox@microsoft.com> Signed-off-by: John Johansen <john.johansen@canonical.com>
1 parent 52e8c38 commit 99cc45e

1 file changed

Lines changed: 11 additions & 103 deletions

File tree

security/apparmor/secid.c

Lines changed: 11 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <linux/errno.h>
1919
#include <linux/err.h>
2020
#include <linux/gfp.h>
21+
#include <linux/idr.h>
2122
#include <linux/slab.h>
2223
#include <linux/spinlock.h>
2324

@@ -30,96 +31,28 @@
3031
/*
3132
* secids - do not pin labels with a refcount. They rely on the label
3233
* properly updating/freeing them
33-
*
34-
* A singly linked free list is used to track secids that have been
35-
* freed and reuse them before allocating new ones
3634
*/
3735

38-
#define FREE_LIST_HEAD 1
39-
40-
static RADIX_TREE(aa_secids_map, GFP_ATOMIC);
36+
static DEFINE_IDR(aa_secids);
4137
static DEFINE_SPINLOCK(secid_lock);
42-
static u32 alloced_secid = FREE_LIST_HEAD;
43-
static u32 free_list = FREE_LIST_HEAD;
44-
static unsigned long free_count;
4538

4639
/*
4740
* TODO: allow policy to reserve a secid range?
4841
* TODO: add secid pinning
4942
* TODO: use secid_update in label replace
5043
*/
5144

52-
#define SECID_MAX U32_MAX
53-
54-
/* TODO: mark free list as exceptional */
55-
static void *to_ptr(u32 secid)
56-
{
57-
return (void *)
58-
((((unsigned long) secid) << RADIX_TREE_EXCEPTIONAL_SHIFT));
59-
}
60-
61-
static u32 to_secid(void *ptr)
62-
{
63-
return (u32) (((unsigned long) ptr) >> RADIX_TREE_EXCEPTIONAL_SHIFT);
64-
}
65-
66-
67-
/* TODO: tag free_list entries to mark them as different */
68-
static u32 __pop(struct aa_label *label)
69-
{
70-
u32 secid = free_list;
71-
void __rcu **slot;
72-
void *entry;
73-
74-
if (free_list == FREE_LIST_HEAD)
75-
return AA_SECID_INVALID;
76-
77-
slot = radix_tree_lookup_slot(&aa_secids_map, secid);
78-
AA_BUG(!slot);
79-
entry = radix_tree_deref_slot_protected(slot, &secid_lock);
80-
free_list = to_secid(entry);
81-
radix_tree_replace_slot(&aa_secids_map, slot, label);
82-
free_count--;
83-
84-
return secid;
85-
}
86-
87-
static void __push(u32 secid)
88-
{
89-
void __rcu **slot;
90-
91-
slot = radix_tree_lookup_slot(&aa_secids_map, secid);
92-
AA_BUG(!slot);
93-
radix_tree_replace_slot(&aa_secids_map, slot, to_ptr(free_list));
94-
free_list = secid;
95-
free_count++;
96-
}
97-
98-
static struct aa_label * __secid_update(u32 secid, struct aa_label *label)
99-
{
100-
struct aa_label *old;
101-
void __rcu **slot;
102-
103-
slot = radix_tree_lookup_slot(&aa_secids_map, secid);
104-
AA_BUG(!slot);
105-
old = radix_tree_deref_slot_protected(slot, &secid_lock);
106-
radix_tree_replace_slot(&aa_secids_map, slot, label);
107-
108-
return old;
109-
}
110-
11145
/**
11246
* aa_secid_update - update a secid mapping to a new label
11347
* @secid: secid to update
11448
* @label: label the secid will now map to
11549
*/
11650
void aa_secid_update(u32 secid, struct aa_label *label)
11751
{
118-
struct aa_label *old;
11952
unsigned long flags;
12053

12154
spin_lock_irqsave(&secid_lock, flags);
122-
old = __secid_update(secid, label);
55+
idr_replace(&aa_secids, label, secid);
12356
spin_unlock_irqrestore(&secid_lock, flags);
12457
}
12558

@@ -132,7 +65,7 @@ struct aa_label *aa_secid_to_label(u32 secid)
13265
struct aa_label *label;
13366

13467
rcu_read_lock();
135-
label = radix_tree_lookup(&aa_secids_map, secid);
68+
label = idr_find(&aa_secids, secid);
13669
rcu_read_unlock();
13770

13871
return label;
@@ -167,7 +100,6 @@ int apparmor_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
167100
return 0;
168101
}
169102

170-
171103
int apparmor_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
172104
{
173105
struct aa_label *label;
@@ -186,7 +118,6 @@ void apparmor_release_secctx(char *secdata, u32 seclen)
186118
kfree(secdata);
187119
}
188120

189-
190121
/**
191122
* aa_alloc_secid - allocate a new secid for a profile
192123
*/
@@ -195,35 +126,12 @@ u32 aa_alloc_secid(struct aa_label *label, gfp_t gfp)
195126
unsigned long flags;
196127
u32 secid;
197128

198-
/* racey, but at worst causes new allocation instead of reuse */
199-
if (free_list == FREE_LIST_HEAD) {
200-
bool preload = 0;
201-
int res;
202-
203-
retry:
204-
if (gfpflags_allow_blocking(gfp) && !radix_tree_preload(gfp))
205-
preload = 1;
206-
spin_lock_irqsave(&secid_lock, flags);
207-
if (alloced_secid != SECID_MAX) {
208-
secid = ++alloced_secid;
209-
res = radix_tree_insert(&aa_secids_map, secid, label);
210-
AA_BUG(res == -EEXIST);
211-
} else {
212-
secid = AA_SECID_INVALID;
213-
}
214-
spin_unlock_irqrestore(&secid_lock, flags);
215-
if (preload)
216-
radix_tree_preload_end();
217-
} else {
218-
spin_lock_irqsave(&secid_lock, flags);
219-
/* remove entry from free list */
220-
secid = __pop(label);
221-
if (secid == AA_SECID_INVALID) {
222-
spin_unlock_irqrestore(&secid_lock, flags);
223-
goto retry;
224-
}
225-
spin_unlock_irqrestore(&secid_lock, flags);
226-
}
129+
idr_preload(gfp);
130+
spin_lock_irqsave(&secid_lock, flags);
131+
secid = idr_alloc(&aa_secids, label, 0, 0, GFP_ATOMIC);
132+
/* XXX: Can return -ENOMEM */
133+
spin_unlock_irqrestore(&secid_lock, flags);
134+
idr_preload_end();
227135

228136
return secid;
229137
}
@@ -237,6 +145,6 @@ void aa_free_secid(u32 secid)
237145
unsigned long flags;
238146

239147
spin_lock_irqsave(&secid_lock, flags);
240-
__push(secid);
148+
idr_remove(&aa_secids, secid);
241149
spin_unlock_irqrestore(&secid_lock, flags);
242150
}

0 commit comments

Comments
 (0)