Skip to content

Commit

Permalink
Merge tag 'selinux-pr-20200601' of git://git.kernel.org/pub/scm/linux…
Browse files Browse the repository at this point in the history
…/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
  • Loading branch information
torvalds committed Jun 3, 2020
2 parents 9d99b16 + fe5a90b commit f41030a
Show file tree
Hide file tree
Showing 19 changed files with 499 additions and 326 deletions.
2 changes: 1 addition & 1 deletion security/selinux/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ obj-$(CONFIG_SECURITY_SELINUX) := selinux.o
selinux-y := avc.o hooks.o selinuxfs.o netlink.o nlmsgtab.o netif.o \
netnode.o netport.o status.o \
ss/ebitmap.o ss/hashtab.o ss/symtab.o ss/sidtab.o ss/avtab.o \
ss/policydb.o ss/services.o ss/conditional.o ss/mls.o
ss/policydb.o ss/services.o ss/conditional.o ss/mls.o ss/context.o

selinux-$(CONFIG_SECURITY_NETWORK_XFRM) += xfrm.o

Expand Down
6 changes: 0 additions & 6 deletions security/selinux/include/netlabel.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,6 @@ static inline int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
return 0;
}

static inline int selinux_netlbl_conn_setsid(struct sock *sk,
struct sockaddr *addr)
{
return 0;
}

static inline int selinux_netlbl_sctp_assoc_request(struct sctp_endpoint *ep,
struct sk_buff *skb)
{
Expand Down
3 changes: 2 additions & 1 deletion security/selinux/include/security.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,11 @@
#define POLICYDB_VERSION_XPERMS_IOCTL 30
#define POLICYDB_VERSION_INFINIBAND 31
#define POLICYDB_VERSION_GLBLUB 32
#define POLICYDB_VERSION_COMP_FTRANS 33 /* compressed filename transitions */

/* Range of policy versions we understand*/
#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
#define POLICYDB_VERSION_MAX POLICYDB_VERSION_GLBLUB
#define POLICYDB_VERSION_MAX POLICYDB_VERSION_COMP_FTRANS

/* Mask for just the mount related flags */
#define SE_MNTMASK 0x0f
Expand Down
32 changes: 32 additions & 0 deletions security/selinux/ss/context.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Implementations of the security context functions.
*
* Author: Ondrej Mosnacek <[email protected]>
* Copyright (C) 2020 Red Hat, Inc.
*/

#include <linux/jhash.h>

#include "context.h"
#include "mls.h"

u32 context_compute_hash(const struct context *c)
{
u32 hash = 0;

/*
* If a context is invalid, it will always be represented by a
* context struct with only the len & str set (and vice versa)
* under a given policy. Since context structs from different
* policies should never meet, it is safe to hash valid and
* invalid contexts differently. The context_cmp() function
* already operates under the same assumption.
*/
if (c->len)
return full_name_hash(NULL, c->str, c->len);

hash = jhash_3words(c->user, c->role, c->type, hash);
hash = mls_range_hash(&c->range, hash);
return hash;
}
11 changes: 2 additions & 9 deletions security/selinux/ss/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ struct context {
u32 len; /* length of string in bytes */
struct mls_range range;
char *str; /* string representation if context cannot be mapped. */
u32 hash; /* a hash of the string representation */
};

static inline void mls_context_init(struct context *c)
Expand Down Expand Up @@ -169,13 +168,12 @@ static inline int context_cpy(struct context *dst, struct context *src)
kfree(dst->str);
return rc;
}
dst->hash = src->hash;
return 0;
}

static inline void context_destroy(struct context *c)
{
c->user = c->role = c->type = c->hash = 0;
c->user = c->role = c->type = 0;
kfree(c->str);
c->str = NULL;
c->len = 0;
Expand All @@ -184,8 +182,6 @@ static inline void context_destroy(struct context *c)

static inline int context_cmp(struct context *c1, struct context *c2)
{
if (c1->hash && c2->hash && (c1->hash != c2->hash))
return 0;
if (c1->len && c2->len)
return (c1->len == c2->len && !strcmp(c1->str, c2->str));
if (c1->len || c2->len)
Expand All @@ -196,10 +192,7 @@ static inline int context_cmp(struct context *c1, struct context *c2)
mls_context_cmp(c1, c2));
}

static inline unsigned int context_compute_hash(const char *s)
{
return full_name_hash(NULL, s, strlen(s));
}
u32 context_compute_hash(const struct context *c);

#endif /* _SS_CONTEXT_H_ */

14 changes: 14 additions & 0 deletions security/selinux/ss/ebitmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/jhash.h>
#include <net/netlabel.h>
#include "ebitmap.h"
#include "policydb.h"
Expand Down Expand Up @@ -542,6 +543,19 @@ int ebitmap_write(struct ebitmap *e, void *fp)
return 0;
}

u32 ebitmap_hash(const struct ebitmap *e, u32 hash)
{
struct ebitmap_node *node;

/* need to change hash even if ebitmap is empty */
hash = jhash_1word(e->highbit, hash);
for (node = e->node; node; node = node->next) {
hash = jhash_1word(node->startbit, hash);
hash = jhash(node->maps, sizeof(node->maps), hash);
}
return hash;
}

void __init ebitmap_cache_init(void)
{
ebitmap_node_cachep = kmem_cache_create("ebitmap_node",
Expand Down
1 change: 1 addition & 0 deletions security/selinux/ss/ebitmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value);
void ebitmap_destroy(struct ebitmap *e);
int ebitmap_read(struct ebitmap *e, void *fp);
int ebitmap_write(struct ebitmap *e, void *fp);
u32 ebitmap_hash(const struct ebitmap *e, u32 hash);

#ifdef CONFIG_NETLABEL
int ebitmap_netlbl_export(struct ebitmap *ebmap,
Expand Down
51 changes: 15 additions & 36 deletions security/selinux/ss/hashtab.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,34 +29,21 @@ static u32 hashtab_compute_size(u32 nel)
return nel == 0 ? 0 : roundup_pow_of_two(nel);
}

struct hashtab *hashtab_create(u32 (*hash_value)(struct hashtab *h, const void *key),
int (*keycmp)(struct hashtab *h, const void *key1, const void *key2),
u32 nel_hint)
int hashtab_init(struct hashtab *h,
u32 (*hash_value)(struct hashtab *h, const void *key),
int (*keycmp)(struct hashtab *h, const void *key1,
const void *key2),
u32 nel_hint)
{
struct hashtab *p;
u32 i, size = hashtab_compute_size(nel_hint);

p = kzalloc(sizeof(*p), GFP_KERNEL);
if (!p)
return p;

p->size = size;
p->nel = 0;
p->hash_value = hash_value;
p->keycmp = keycmp;
if (!size)
return p;

p->htable = kmalloc_array(size, sizeof(*p->htable), GFP_KERNEL);
if (!p->htable) {
kfree(p);
return NULL;
}

for (i = 0; i < size; i++)
p->htable[i] = NULL;
h->size = hashtab_compute_size(nel_hint);
h->nel = 0;
h->hash_value = hash_value;
h->keycmp = keycmp;
if (!h->size)
return 0;

return p;
h->htable = kcalloc(h->size, sizeof(*h->htable), GFP_KERNEL);
return h->htable ? 0 : -ENOMEM;
}

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

cond_resched();

if (!h || !h->size || h->nel == HASHTAB_MAX_NODES)
if (!h->size || h->nel == HASHTAB_MAX_NODES)
return -EINVAL;

hvalue = h->hash_value(h, key);
Expand Down Expand Up @@ -102,7 +89,7 @@ void *hashtab_search(struct hashtab *h, const void *key)
u32 hvalue;
struct hashtab_node *cur;

if (!h || !h->size)
if (!h->size)
return NULL;

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

if (!h)
return;

for (i = 0; i < h->size; i++) {
cur = h->htable[i];
while (cur) {
Expand All @@ -136,8 +120,6 @@ void hashtab_destroy(struct hashtab *h)

kfree(h->htable);
h->htable = NULL;

kfree(h);
}

int hashtab_map(struct hashtab *h,
Expand All @@ -148,9 +130,6 @@ int hashtab_map(struct hashtab *h,
int ret;
struct hashtab_node *cur;

if (!h)
return 0;

for (i = 0; i < h->size; i++) {
cur = h->htable[i];
while (cur) {
Expand Down
13 changes: 7 additions & 6 deletions security/selinux/ss/hashtab.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,15 @@ struct hashtab_info {
};

/*
* Creates a new hash table with the specified characteristics.
* Initializes a new hash table with the specified characteristics.
*
* Returns NULL if insufficent space is available or
* the new hash table otherwise.
* Returns -ENOMEM if insufficient space is available or 0 otherwise.
*/
struct hashtab *hashtab_create(u32 (*hash_value)(struct hashtab *h, const void *key),
int (*keycmp)(struct hashtab *h, const void *key1, const void *key2),
u32 nel_hint);
int hashtab_init(struct hashtab *h,
u32 (*hash_value)(struct hashtab *h, const void *key),
int (*keycmp)(struct hashtab *h, const void *key1,
const void *key2),
u32 nel_hint);

/*
* Inserts the specified (key, datum) pair into the specified hash table.
Expand Down
16 changes: 8 additions & 8 deletions security/selinux/ss/mls.c
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ int mls_level_isvalid(struct policydb *p, struct mls_level *l)

if (!l->sens || l->sens > p->p_levels.nprim)
return 0;
levdatum = hashtab_search(p->p_levels.table,
levdatum = hashtab_search(&p->p_levels.table,
sym_name(p, SYM_LEVELS, l->sens - 1));
if (!levdatum)
return 0;
Expand Down Expand Up @@ -293,7 +293,7 @@ int mls_context_to_sid(struct policydb *pol,
*(next_cat++) = '\0';

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

catdatum = hashtab_search(pol->p_cats.table, cur_cat);
catdatum = hashtab_search(&pol->p_cats.table, cur_cat);
if (!catdatum)
return -EINVAL;

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

rngdatum = hashtab_search(pol->p_cats.table, rngptr);
rngdatum = hashtab_search(&pol->p_cats.table, rngptr);
if (!rngdatum)
return -EINVAL;

Expand Down Expand Up @@ -458,7 +458,7 @@ int mls_convert_context(struct policydb *oldp,
return 0;

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

Expand All @@ -470,7 +470,7 @@ int mls_convert_context(struct policydb *oldp,
node, i) {
int rc;

catdatum = hashtab_search(newp->p_cats.table,
catdatum = hashtab_search(&newp->p_cats.table,
sym_name(oldp, SYM_CATS, i));
if (!catdatum)
return -EINVAL;
Expand Down Expand Up @@ -506,7 +506,7 @@ int mls_compute_sid(struct policydb *p,
rtr.source_type = scontext->type;
rtr.target_type = tcontext->type;
rtr.target_class = tclass;
r = hashtab_search(p->range_tr, &rtr);
r = hashtab_search(&p->range_tr, &rtr);
if (r)
return mls_range_set(newcontext, r);

Expand Down Expand Up @@ -536,7 +536,7 @@ int mls_compute_sid(struct policydb *p,

/* Fallthrough */
case AVTAB_CHANGE:
if ((tclass == p->process_class) || (sock == true))
if ((tclass == p->process_class) || sock)
/* Use the process MLS attributes. */
return mls_context_cpy(newcontext, scontext);
else
Expand Down
11 changes: 11 additions & 0 deletions security/selinux/ss/mls.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@
#ifndef _SS_MLS_H_
#define _SS_MLS_H_

#include <linux/jhash.h>

#include "context.h"
#include "ebitmap.h"
#include "policydb.h"

int mls_compute_context_len(struct policydb *p, struct context *context);
Expand Down Expand Up @@ -101,5 +104,13 @@ static inline int mls_import_netlbl_cat(struct policydb *p,
}
#endif

static inline u32 mls_range_hash(const struct mls_range *r, u32 hash)
{
hash = jhash_2words(r->level[0].sens, r->level[1].sens, hash);
hash = ebitmap_hash(&r->level[0].cat, hash);
hash = ebitmap_hash(&r->level[1].cat, hash);
return hash;
}

#endif /* _SS_MLS_H */

Loading

0 comments on commit f41030a

Please sign in to comment.