Skip to content

Commit f41030a

Browse files
committed
Merge tag 'selinux-pr-20200601' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux
Pull SELinux updates from Paul Moore: "The highlights: - A number of improvements to various SELinux internal data structures to help improve performance. We move the role transitions into a hash table. In the content structure we shift from hashing the content string (aka SELinux label) to the structure itself, when it is valid. This last change not only offers a speedup, but it helps us simplify the code some as well. - Add a new SELinux policy version which allows for a more space efficient way of storing the filename transitions in the binary policy. Given the default Fedora SELinux policy with the unconfined module enabled, this change drops the policy size from ~7.6MB to ~3.3MB. The kernel policy load time dropped as well. - Some fixes to the error handling code in the policy parser to properly return error codes when things go wrong" * tag 'selinux-pr-20200601' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux: selinux: netlabel: Remove unused inline function selinux: do not allocate hashtabs dynamically selinux: fix return value on error in policydb_read() selinux: simplify range_write() selinux: fix error return code in policydb_read() selinux: don't produce incorrect filename_trans_count selinux: implement new format of filename transitions selinux: move context hashing under sidtab selinux: hash context structure directly selinux: store role transitions in a hash table selinux: drop unnecessary smp_load_acquire() call selinux: fix warning Comparison to bool
2 parents 9d99b16 + fe5a90b commit f41030a

File tree

19 files changed

+499
-326
lines changed

19 files changed

+499
-326
lines changed

security/selinux/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ obj-$(CONFIG_SECURITY_SELINUX) := selinux.o
88
selinux-y := avc.o hooks.o selinuxfs.o netlink.o nlmsgtab.o netif.o \
99
netnode.o netport.o status.o \
1010
ss/ebitmap.o ss/hashtab.o ss/symtab.o ss/sidtab.o ss/avtab.o \
11-
ss/policydb.o ss/services.o ss/conditional.o ss/mls.o
11+
ss/policydb.o ss/services.o ss/conditional.o ss/mls.o ss/context.o
1212

1313
selinux-$(CONFIG_SECURITY_NETWORK_XFRM) += xfrm.o
1414

security/selinux/include/netlabel.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -98,12 +98,6 @@ static inline int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
9898
return 0;
9999
}
100100

101-
static inline int selinux_netlbl_conn_setsid(struct sock *sk,
102-
struct sockaddr *addr)
103-
{
104-
return 0;
105-
}
106-
107101
static inline int selinux_netlbl_sctp_assoc_request(struct sctp_endpoint *ep,
108102
struct sk_buff *skb)
109103
{

security/selinux/include/security.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,11 @@
4141
#define POLICYDB_VERSION_XPERMS_IOCTL 30
4242
#define POLICYDB_VERSION_INFINIBAND 31
4343
#define POLICYDB_VERSION_GLBLUB 32
44+
#define POLICYDB_VERSION_COMP_FTRANS 33 /* compressed filename transitions */
4445

4546
/* Range of policy versions we understand*/
4647
#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
47-
#define POLICYDB_VERSION_MAX POLICYDB_VERSION_GLBLUB
48+
#define POLICYDB_VERSION_MAX POLICYDB_VERSION_COMP_FTRANS
4849

4950
/* Mask for just the mount related flags */
5051
#define SE_MNTMASK 0x0f

security/selinux/ss/context.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* Implementations of the security context functions.
4+
*
5+
* Author: Ondrej Mosnacek <[email protected]>
6+
* Copyright (C) 2020 Red Hat, Inc.
7+
*/
8+
9+
#include <linux/jhash.h>
10+
11+
#include "context.h"
12+
#include "mls.h"
13+
14+
u32 context_compute_hash(const struct context *c)
15+
{
16+
u32 hash = 0;
17+
18+
/*
19+
* If a context is invalid, it will always be represented by a
20+
* context struct with only the len & str set (and vice versa)
21+
* under a given policy. Since context structs from different
22+
* policies should never meet, it is safe to hash valid and
23+
* invalid contexts differently. The context_cmp() function
24+
* already operates under the same assumption.
25+
*/
26+
if (c->len)
27+
return full_name_hash(NULL, c->str, c->len);
28+
29+
hash = jhash_3words(c->user, c->role, c->type, hash);
30+
hash = mls_range_hash(&c->range, hash);
31+
return hash;
32+
}

security/selinux/ss/context.h

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ struct context {
3131
u32 len; /* length of string in bytes */
3232
struct mls_range range;
3333
char *str; /* string representation if context cannot be mapped. */
34-
u32 hash; /* a hash of the string representation */
3534
};
3635

3736
static inline void mls_context_init(struct context *c)
@@ -169,13 +168,12 @@ static inline int context_cpy(struct context *dst, struct context *src)
169168
kfree(dst->str);
170169
return rc;
171170
}
172-
dst->hash = src->hash;
173171
return 0;
174172
}
175173

176174
static inline void context_destroy(struct context *c)
177175
{
178-
c->user = c->role = c->type = c->hash = 0;
176+
c->user = c->role = c->type = 0;
179177
kfree(c->str);
180178
c->str = NULL;
181179
c->len = 0;
@@ -184,8 +182,6 @@ static inline void context_destroy(struct context *c)
184182

185183
static inline int context_cmp(struct context *c1, struct context *c2)
186184
{
187-
if (c1->hash && c2->hash && (c1->hash != c2->hash))
188-
return 0;
189185
if (c1->len && c2->len)
190186
return (c1->len == c2->len && !strcmp(c1->str, c2->str));
191187
if (c1->len || c2->len)
@@ -196,10 +192,7 @@ static inline int context_cmp(struct context *c1, struct context *c2)
196192
mls_context_cmp(c1, c2));
197193
}
198194

199-
static inline unsigned int context_compute_hash(const char *s)
200-
{
201-
return full_name_hash(NULL, s, strlen(s));
202-
}
195+
u32 context_compute_hash(const struct context *c);
203196

204197
#endif /* _SS_CONTEXT_H_ */
205198

security/selinux/ss/ebitmap.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <linux/kernel.h>
2020
#include <linux/slab.h>
2121
#include <linux/errno.h>
22+
#include <linux/jhash.h>
2223
#include <net/netlabel.h>
2324
#include "ebitmap.h"
2425
#include "policydb.h"
@@ -542,6 +543,19 @@ int ebitmap_write(struct ebitmap *e, void *fp)
542543
return 0;
543544
}
544545

546+
u32 ebitmap_hash(const struct ebitmap *e, u32 hash)
547+
{
548+
struct ebitmap_node *node;
549+
550+
/* need to change hash even if ebitmap is empty */
551+
hash = jhash_1word(e->highbit, hash);
552+
for (node = e->node; node; node = node->next) {
553+
hash = jhash_1word(node->startbit, hash);
554+
hash = jhash(node->maps, sizeof(node->maps), hash);
555+
}
556+
return hash;
557+
}
558+
545559
void __init ebitmap_cache_init(void)
546560
{
547561
ebitmap_node_cachep = kmem_cache_create("ebitmap_node",

security/selinux/ss/ebitmap.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value);
131131
void ebitmap_destroy(struct ebitmap *e);
132132
int ebitmap_read(struct ebitmap *e, void *fp);
133133
int ebitmap_write(struct ebitmap *e, void *fp);
134+
u32 ebitmap_hash(const struct ebitmap *e, u32 hash);
134135

135136
#ifdef CONFIG_NETLABEL
136137
int ebitmap_netlbl_export(struct ebitmap *ebmap,

security/selinux/ss/hashtab.c

Lines changed: 15 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -29,34 +29,21 @@ static u32 hashtab_compute_size(u32 nel)
2929
return nel == 0 ? 0 : roundup_pow_of_two(nel);
3030
}
3131

32-
struct hashtab *hashtab_create(u32 (*hash_value)(struct hashtab *h, const void *key),
33-
int (*keycmp)(struct hashtab *h, const void *key1, const void *key2),
34-
u32 nel_hint)
32+
int hashtab_init(struct hashtab *h,
33+
u32 (*hash_value)(struct hashtab *h, const void *key),
34+
int (*keycmp)(struct hashtab *h, const void *key1,
35+
const void *key2),
36+
u32 nel_hint)
3537
{
36-
struct hashtab *p;
37-
u32 i, size = hashtab_compute_size(nel_hint);
38-
39-
p = kzalloc(sizeof(*p), GFP_KERNEL);
40-
if (!p)
41-
return p;
42-
43-
p->size = size;
44-
p->nel = 0;
45-
p->hash_value = hash_value;
46-
p->keycmp = keycmp;
47-
if (!size)
48-
return p;
49-
50-
p->htable = kmalloc_array(size, sizeof(*p->htable), GFP_KERNEL);
51-
if (!p->htable) {
52-
kfree(p);
53-
return NULL;
54-
}
55-
56-
for (i = 0; i < size; i++)
57-
p->htable[i] = NULL;
38+
h->size = hashtab_compute_size(nel_hint);
39+
h->nel = 0;
40+
h->hash_value = hash_value;
41+
h->keycmp = keycmp;
42+
if (!h->size)
43+
return 0;
5844

59-
return p;
45+
h->htable = kcalloc(h->size, sizeof(*h->htable), GFP_KERNEL);
46+
return h->htable ? 0 : -ENOMEM;
6047
}
6148

6249
int hashtab_insert(struct hashtab *h, void *key, void *datum)
@@ -66,7 +53,7 @@ int hashtab_insert(struct hashtab *h, void *key, void *datum)
6653

6754
cond_resched();
6855

69-
if (!h || !h->size || h->nel == HASHTAB_MAX_NODES)
56+
if (!h->size || h->nel == HASHTAB_MAX_NODES)
7057
return -EINVAL;
7158

7259
hvalue = h->hash_value(h, key);
@@ -102,7 +89,7 @@ void *hashtab_search(struct hashtab *h, const void *key)
10289
u32 hvalue;
10390
struct hashtab_node *cur;
10491

105-
if (!h || !h->size)
92+
if (!h->size)
10693
return NULL;
10794

10895
hvalue = h->hash_value(h, key);
@@ -121,9 +108,6 @@ void hashtab_destroy(struct hashtab *h)
121108
u32 i;
122109
struct hashtab_node *cur, *temp;
123110

124-
if (!h)
125-
return;
126-
127111
for (i = 0; i < h->size; i++) {
128112
cur = h->htable[i];
129113
while (cur) {
@@ -136,8 +120,6 @@ void hashtab_destroy(struct hashtab *h)
136120

137121
kfree(h->htable);
138122
h->htable = NULL;
139-
140-
kfree(h);
141123
}
142124

143125
int hashtab_map(struct hashtab *h,
@@ -148,9 +130,6 @@ int hashtab_map(struct hashtab *h,
148130
int ret;
149131
struct hashtab_node *cur;
150132

151-
if (!h)
152-
return 0;
153-
154133
for (i = 0; i < h->size; i++) {
155134
cur = h->htable[i];
156135
while (cur) {

security/selinux/ss/hashtab.h

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,15 @@ struct hashtab_info {
3535
};
3636

3737
/*
38-
* Creates a new hash table with the specified characteristics.
38+
* Initializes a new hash table with the specified characteristics.
3939
*
40-
* Returns NULL if insufficent space is available or
41-
* the new hash table otherwise.
40+
* Returns -ENOMEM if insufficient space is available or 0 otherwise.
4241
*/
43-
struct hashtab *hashtab_create(u32 (*hash_value)(struct hashtab *h, const void *key),
44-
int (*keycmp)(struct hashtab *h, const void *key1, const void *key2),
45-
u32 nel_hint);
42+
int hashtab_init(struct hashtab *h,
43+
u32 (*hash_value)(struct hashtab *h, const void *key),
44+
int (*keycmp)(struct hashtab *h, const void *key1,
45+
const void *key2),
46+
u32 nel_hint);
4647

4748
/*
4849
* Inserts the specified (key, datum) pair into the specified hash table.

security/selinux/ss/mls.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ int mls_level_isvalid(struct policydb *p, struct mls_level *l)
165165

166166
if (!l->sens || l->sens > p->p_levels.nprim)
167167
return 0;
168-
levdatum = hashtab_search(p->p_levels.table,
168+
levdatum = hashtab_search(&p->p_levels.table,
169169
sym_name(p, SYM_LEVELS, l->sens - 1));
170170
if (!levdatum)
171171
return 0;
@@ -293,7 +293,7 @@ int mls_context_to_sid(struct policydb *pol,
293293
*(next_cat++) = '\0';
294294

295295
/* Parse sensitivity. */
296-
levdatum = hashtab_search(pol->p_levels.table, sensitivity);
296+
levdatum = hashtab_search(&pol->p_levels.table, sensitivity);
297297
if (!levdatum)
298298
return -EINVAL;
299299
context->range.level[l].sens = levdatum->level->sens;
@@ -312,7 +312,7 @@ int mls_context_to_sid(struct policydb *pol,
312312
*rngptr++ = '\0';
313313
}
314314

315-
catdatum = hashtab_search(pol->p_cats.table, cur_cat);
315+
catdatum = hashtab_search(&pol->p_cats.table, cur_cat);
316316
if (!catdatum)
317317
return -EINVAL;
318318

@@ -325,7 +325,7 @@ int mls_context_to_sid(struct policydb *pol,
325325
if (rngptr == NULL)
326326
continue;
327327

328-
rngdatum = hashtab_search(pol->p_cats.table, rngptr);
328+
rngdatum = hashtab_search(&pol->p_cats.table, rngptr);
329329
if (!rngdatum)
330330
return -EINVAL;
331331

@@ -458,7 +458,7 @@ int mls_convert_context(struct policydb *oldp,
458458
return 0;
459459

460460
for (l = 0; l < 2; l++) {
461-
levdatum = hashtab_search(newp->p_levels.table,
461+
levdatum = hashtab_search(&newp->p_levels.table,
462462
sym_name(oldp, SYM_LEVELS,
463463
oldc->range.level[l].sens - 1));
464464

@@ -470,7 +470,7 @@ int mls_convert_context(struct policydb *oldp,
470470
node, i) {
471471
int rc;
472472

473-
catdatum = hashtab_search(newp->p_cats.table,
473+
catdatum = hashtab_search(&newp->p_cats.table,
474474
sym_name(oldp, SYM_CATS, i));
475475
if (!catdatum)
476476
return -EINVAL;
@@ -506,7 +506,7 @@ int mls_compute_sid(struct policydb *p,
506506
rtr.source_type = scontext->type;
507507
rtr.target_type = tcontext->type;
508508
rtr.target_class = tclass;
509-
r = hashtab_search(p->range_tr, &rtr);
509+
r = hashtab_search(&p->range_tr, &rtr);
510510
if (r)
511511
return mls_range_set(newcontext, r);
512512

@@ -536,7 +536,7 @@ int mls_compute_sid(struct policydb *p,
536536

537537
/* Fallthrough */
538538
case AVTAB_CHANGE:
539-
if ((tclass == p->process_class) || (sock == true))
539+
if ((tclass == p->process_class) || sock)
540540
/* Use the process MLS attributes. */
541541
return mls_context_cpy(newcontext, scontext);
542542
else

0 commit comments

Comments
 (0)