Commit 701a90ba authored by Paul Moore's avatar Paul Moore Committed by David S. Miller

NetLabel: make netlbl_lsm_secattr struct easier/quicker to understand

The existing netlbl_lsm_secattr struct required the LSM to check all of the
fields to determine if any security attributes were present resulting in a lot
of work in the common case of no attributes.  This patch adds a 'flags' field
which is used to indicate which attributes are present in the structure; this
should allow the LSM to do a quick comparison to determine if the structure
holds any security attributes.

Example:

 if (netlbl_lsm_secattr->flags)
	/* security attributes present */
 else
	/* NO security attributes present */
Signed-off-by: default avatarPaul Moore <paul.moore@hp.com>
Signed-off-by: default avatarJames Morris <jmorris@namei.org>
parent c6fa82a9
...@@ -111,11 +111,17 @@ struct netlbl_lsm_cache { ...@@ -111,11 +111,17 @@ struct netlbl_lsm_cache {
void (*free) (const void *data); void (*free) (const void *data);
void *data; void *data;
}; };
#define NETLBL_SECATTR_NONE 0x00000000
#define NETLBL_SECATTR_DOMAIN 0x00000001
#define NETLBL_SECATTR_CACHE 0x00000002
#define NETLBL_SECATTR_MLS_LVL 0x00000004
#define NETLBL_SECATTR_MLS_CAT 0x00000008
struct netlbl_lsm_secattr { struct netlbl_lsm_secattr {
u32 flags;
char *domain; char *domain;
u32 mls_lvl; u32 mls_lvl;
u32 mls_lvl_vld;
unsigned char *mls_cat; unsigned char *mls_cat;
size_t mls_cat_len; size_t mls_cat_len;
...@@ -174,7 +180,10 @@ static inline void netlbl_secattr_cache_free(struct netlbl_lsm_cache *cache) ...@@ -174,7 +180,10 @@ static inline void netlbl_secattr_cache_free(struct netlbl_lsm_cache *cache)
*/ */
static inline void netlbl_secattr_init(struct netlbl_lsm_secattr *secattr) static inline void netlbl_secattr_init(struct netlbl_lsm_secattr *secattr)
{ {
memset(secattr, 0, sizeof(*secattr)); secattr->flags = 0;
secattr->domain = NULL;
secattr->mls_cat = NULL;
secattr->cache = NULL;
} }
/** /**
......
...@@ -319,6 +319,7 @@ static int cipso_v4_cache_check(const unsigned char *key, ...@@ -319,6 +319,7 @@ static int cipso_v4_cache_check(const unsigned char *key,
entry->activity += 1; entry->activity += 1;
atomic_inc(&entry->lsm_data->refcount); atomic_inc(&entry->lsm_data->refcount);
secattr->cache = entry->lsm_data; secattr->cache = entry->lsm_data;
secattr->flags |= NETLBL_SECATTR_CACHE;
if (prev_entry == NULL) { if (prev_entry == NULL) {
spin_unlock_bh(&cipso_v4_cache[bkt].lock); spin_unlock_bh(&cipso_v4_cache[bkt].lock);
return 0; return 0;
...@@ -991,12 +992,15 @@ static int cipso_v4_gentag_rbm(const struct cipso_v4_doi *doi_def, ...@@ -991,12 +992,15 @@ static int cipso_v4_gentag_rbm(const struct cipso_v4_doi *doi_def,
unsigned char **buffer, unsigned char **buffer,
u32 *buffer_len) u32 *buffer_len)
{ {
int ret_val = -EPERM; int ret_val;
unsigned char *buf = NULL; unsigned char *buf = NULL;
u32 buf_len; u32 buf_len;
u32 level; u32 level;
if (secattr->mls_cat) { if ((secattr->flags & NETLBL_SECATTR_MLS_LVL) == 0)
return -EPERM;
if (secattr->flags & NETLBL_SECATTR_MLS_CAT) {
buf = kzalloc(CIPSO_V4_HDR_LEN + 4 + CIPSO_V4_TAG1_CAT_LEN, buf = kzalloc(CIPSO_V4_HDR_LEN + 4 + CIPSO_V4_TAG1_CAT_LEN,
GFP_ATOMIC); GFP_ATOMIC);
if (buf == NULL) if (buf == NULL)
...@@ -1013,10 +1017,10 @@ static int cipso_v4_gentag_rbm(const struct cipso_v4_doi *doi_def, ...@@ -1013,10 +1017,10 @@ static int cipso_v4_gentag_rbm(const struct cipso_v4_doi *doi_def,
/* This will send packets using the "optimized" format when /* This will send packets using the "optimized" format when
* possibile as specified in section 3.4.2.6 of the * possibile as specified in section 3.4.2.6 of the
* CIPSO draft. */ * CIPSO draft. */
if (cipso_v4_rbm_optfmt && (ret_val > 0 && ret_val < 10)) if (cipso_v4_rbm_optfmt && ret_val > 0 && ret_val <= 10)
ret_val = 10; buf_len = 14;
else
buf_len = 4 + ret_val; buf_len = 4 + ret_val;
} else { } else {
buf = kzalloc(CIPSO_V4_HDR_LEN + 4, GFP_ATOMIC); buf = kzalloc(CIPSO_V4_HDR_LEN + 4, GFP_ATOMIC);
if (buf == NULL) if (buf == NULL)
...@@ -1070,7 +1074,7 @@ static int cipso_v4_parsetag_rbm(const struct cipso_v4_doi *doi_def, ...@@ -1070,7 +1074,7 @@ static int cipso_v4_parsetag_rbm(const struct cipso_v4_doi *doi_def,
if (ret_val != 0) if (ret_val != 0)
return ret_val; return ret_val;
secattr->mls_lvl = level; secattr->mls_lvl = level;
secattr->mls_lvl_vld = 1; secattr->flags |= NETLBL_SECATTR_MLS_LVL;
if (tag_len > 4) { if (tag_len > 4) {
switch (doi_def->type) { switch (doi_def->type) {
...@@ -1094,8 +1098,10 @@ static int cipso_v4_parsetag_rbm(const struct cipso_v4_doi *doi_def, ...@@ -1094,8 +1098,10 @@ static int cipso_v4_parsetag_rbm(const struct cipso_v4_doi *doi_def,
if (ret_val < 0) { if (ret_val < 0) {
kfree(secattr->mls_cat); kfree(secattr->mls_cat);
return ret_val; return ret_val;
} else if (ret_val > 0) {
secattr->mls_cat_len = ret_val;
secattr->flags |= NETLBL_SECATTR_MLS_CAT;
} }
secattr->mls_cat_len = ret_val;
} }
return 0; return 0;
......
...@@ -62,6 +62,9 @@ int netlbl_socket_setattr(const struct socket *sock, ...@@ -62,6 +62,9 @@ int netlbl_socket_setattr(const struct socket *sock,
int ret_val = -ENOENT; int ret_val = -ENOENT;
struct netlbl_dom_map *dom_entry; struct netlbl_dom_map *dom_entry;
if ((secattr->flags & NETLBL_SECATTR_DOMAIN) == 0)
return -ENOENT;
rcu_read_lock(); rcu_read_lock();
dom_entry = netlbl_domhsh_getentry(secattr->domain); dom_entry = netlbl_domhsh_getentry(secattr->domain);
if (dom_entry == NULL) if (dom_entry == NULL)
...@@ -200,7 +203,7 @@ void netlbl_cache_invalidate(void) ...@@ -200,7 +203,7 @@ void netlbl_cache_invalidate(void)
int netlbl_cache_add(const struct sk_buff *skb, int netlbl_cache_add(const struct sk_buff *skb,
const struct netlbl_lsm_secattr *secattr) const struct netlbl_lsm_secattr *secattr)
{ {
if (secattr->cache == NULL) if ((secattr->flags & NETLBL_SECATTR_CACHE) == 0)
return -ENOMSG; return -ENOMSG;
if (CIPSO_V4_OPTEXIST(skb)) if (CIPSO_V4_OPTEXIST(skb))
......
...@@ -2254,8 +2254,6 @@ static void selinux_netlbl_cache_add(struct sk_buff *skb, struct context *ctx) ...@@ -2254,8 +2254,6 @@ static void selinux_netlbl_cache_add(struct sk_buff *skb, struct context *ctx)
cache = kzalloc(sizeof(*cache), GFP_ATOMIC); cache = kzalloc(sizeof(*cache), GFP_ATOMIC);
if (cache == NULL) if (cache == NULL)
goto netlbl_cache_add_return; goto netlbl_cache_add_return;
secattr.cache->free = selinux_netlbl_cache_free;
secattr.cache->data = (void *)cache;
cache->type = NETLBL_CACHE_T_MLS; cache->type = NETLBL_CACHE_T_MLS;
if (ebitmap_cpy(&cache->data.mls_label.level[0].cat, if (ebitmap_cpy(&cache->data.mls_label.level[0].cat,
...@@ -2268,6 +2266,10 @@ static void selinux_netlbl_cache_add(struct sk_buff *skb, struct context *ctx) ...@@ -2268,6 +2266,10 @@ static void selinux_netlbl_cache_add(struct sk_buff *skb, struct context *ctx)
cache->data.mls_label.level[0].sens = ctx->range.level[0].sens; cache->data.mls_label.level[0].sens = ctx->range.level[0].sens;
cache->data.mls_label.level[1].sens = ctx->range.level[0].sens; cache->data.mls_label.level[1].sens = ctx->range.level[0].sens;
secattr.cache->free = selinux_netlbl_cache_free;
secattr.cache->data = (void *)cache;
secattr.flags = NETLBL_SECATTR_CACHE;
netlbl_cache_add(skb, &secattr); netlbl_cache_add(skb, &secattr);
netlbl_cache_add_return: netlbl_cache_add_return:
...@@ -2313,7 +2315,7 @@ static int selinux_netlbl_secattr_to_sid(struct sk_buff *skb, ...@@ -2313,7 +2315,7 @@ static int selinux_netlbl_secattr_to_sid(struct sk_buff *skb,
POLICY_RDLOCK; POLICY_RDLOCK;
if (secattr->cache) { if (secattr->flags & NETLBL_SECATTR_CACHE) {
cache = NETLBL_CACHE(secattr->cache->data); cache = NETLBL_CACHE(secattr->cache->data);
switch (cache->type) { switch (cache->type) {
case NETLBL_CACHE_T_SID: case NETLBL_CACHE_T_SID:
...@@ -2346,7 +2348,7 @@ static int selinux_netlbl_secattr_to_sid(struct sk_buff *skb, ...@@ -2346,7 +2348,7 @@ static int selinux_netlbl_secattr_to_sid(struct sk_buff *skb,
default: default:
goto netlbl_secattr_to_sid_return; goto netlbl_secattr_to_sid_return;
} }
} else if (secattr->mls_lvl_vld) { } else if (secattr->flags & NETLBL_SECATTR_MLS_LVL) {
ctx = sidtab_search(&sidtab, base_sid); ctx = sidtab_search(&sidtab, base_sid);
if (ctx == NULL) if (ctx == NULL)
goto netlbl_secattr_to_sid_return; goto netlbl_secattr_to_sid_return;
...@@ -2355,7 +2357,7 @@ static int selinux_netlbl_secattr_to_sid(struct sk_buff *skb, ...@@ -2355,7 +2357,7 @@ static int selinux_netlbl_secattr_to_sid(struct sk_buff *skb,
ctx_new.role = ctx->role; ctx_new.role = ctx->role;
ctx_new.type = ctx->type; ctx_new.type = ctx->type;
mls_import_lvl(&ctx_new, secattr->mls_lvl, secattr->mls_lvl); mls_import_lvl(&ctx_new, secattr->mls_lvl, secattr->mls_lvl);
if (secattr->mls_cat) { if (secattr->flags & NETLBL_SECATTR_MLS_CAT) {
if (mls_import_cat(&ctx_new, if (mls_import_cat(&ctx_new,
secattr->mls_cat, secattr->mls_cat,
secattr->mls_cat_len, secattr->mls_cat_len,
...@@ -2414,11 +2416,13 @@ static int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, ...@@ -2414,11 +2416,13 @@ static int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
netlbl_secattr_init(&secattr); netlbl_secattr_init(&secattr);
rc = netlbl_skbuff_getattr(skb, &secattr); rc = netlbl_skbuff_getattr(skb, &secattr);
if (rc == 0) if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE)
rc = selinux_netlbl_secattr_to_sid(skb, rc = selinux_netlbl_secattr_to_sid(skb,
&secattr, &secattr,
base_sid, base_sid,
sid); sid);
else
*sid = SECSID_NULL;
netlbl_secattr_destroy(&secattr); netlbl_secattr_destroy(&secattr);
return rc; return rc;
...@@ -2455,7 +2459,6 @@ static int selinux_netlbl_socket_setsid(struct socket *sock, u32 sid) ...@@ -2455,7 +2459,6 @@ static int selinux_netlbl_socket_setsid(struct socket *sock, u32 sid)
secattr.domain = kstrdup(policydb.p_type_val_to_name[ctx->type - 1], secattr.domain = kstrdup(policydb.p_type_val_to_name[ctx->type - 1],
GFP_ATOMIC); GFP_ATOMIC);
mls_export_lvl(ctx, &secattr.mls_lvl, NULL); mls_export_lvl(ctx, &secattr.mls_lvl, NULL);
secattr.mls_lvl_vld = 1;
rc = mls_export_cat(ctx, rc = mls_export_cat(ctx,
&secattr.mls_cat, &secattr.mls_cat,
&secattr.mls_cat_len, &secattr.mls_cat_len,
...@@ -2464,6 +2467,10 @@ static int selinux_netlbl_socket_setsid(struct socket *sock, u32 sid) ...@@ -2464,6 +2467,10 @@ static int selinux_netlbl_socket_setsid(struct socket *sock, u32 sid)
if (rc != 0) if (rc != 0)
goto netlbl_socket_setsid_return; goto netlbl_socket_setsid_return;
secattr.flags |= NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL;
if (secattr.mls_cat)
secattr.flags |= NETLBL_SECATTR_MLS_CAT;
rc = netlbl_socket_setattr(sock, &secattr); rc = netlbl_socket_setattr(sock, &secattr);
if (rc == 0) if (rc == 0)
sksec->nlbl_state = NLBL_LABELED; sksec->nlbl_state = NLBL_LABELED;
...@@ -2564,6 +2571,7 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock) ...@@ -2564,6 +2571,7 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
netlbl_secattr_init(&secattr); netlbl_secattr_init(&secattr);
if (netlbl_sock_getattr(sk, &secattr) == 0 && if (netlbl_sock_getattr(sk, &secattr) == 0 &&
secattr.flags != NETLBL_SECATTR_NONE &&
selinux_netlbl_secattr_to_sid(NULL, selinux_netlbl_secattr_to_sid(NULL,
&secattr, &secattr,
SECINITSID_UNLABELED, SECINITSID_UNLABELED,
...@@ -2756,7 +2764,7 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock, ...@@ -2756,7 +2764,7 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock,
sksec->nlbl_state == NLBL_LABELED) { sksec->nlbl_state == NLBL_LABELED) {
netlbl_secattr_init(&secattr); netlbl_secattr_init(&secattr);
rc = netlbl_socket_getattr(sock, &secattr); rc = netlbl_socket_getattr(sock, &secattr);
if (rc == 0 && (secattr.cache || secattr.mls_lvl_vld)) if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE)
rc = -EACCES; rc = -EACCES;
netlbl_secattr_destroy(&secattr); netlbl_secattr_destroy(&secattr);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment