From: Paul Moore Date: Fri, 17 Nov 2006 22:38:46 +0000 (-0500) Subject: NetLabel: make netlbl_lsm_secattr struct easier/quicker to understand X-Git-Tag: v2.6.20-rc1~34^2~40^2~280 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=701a90bad99b8081a824cca52c178c8fc8f46bb2;p=linux-2.6 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: Paul Moore Signed-off-by: James Morris --- diff --git a/include/net/netlabel.h b/include/net/netlabel.h index 4e223aa25e..d605d79540 100644 --- a/include/net/netlabel.h +++ b/include/net/netlabel.h @@ -111,11 +111,17 @@ struct netlbl_lsm_cache { void (*free) (const 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 { + u32 flags; + char *domain; u32 mls_lvl; - u32 mls_lvl_vld; unsigned char *mls_cat; size_t mls_cat_len; @@ -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) { - memset(secattr, 0, sizeof(*secattr)); + secattr->flags = 0; + secattr->domain = NULL; + secattr->mls_cat = NULL; + secattr->cache = NULL; } /** diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index 095038ad72..f0a0785047 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c @@ -319,6 +319,7 @@ static int cipso_v4_cache_check(const unsigned char *key, entry->activity += 1; atomic_inc(&entry->lsm_data->refcount); secattr->cache = entry->lsm_data; + secattr->flags |= NETLBL_SECATTR_CACHE; if (prev_entry == NULL) { spin_unlock_bh(&cipso_v4_cache[bkt].lock); return 0; @@ -991,12 +992,15 @@ static int cipso_v4_gentag_rbm(const struct cipso_v4_doi *doi_def, unsigned char **buffer, u32 *buffer_len) { - int ret_val = -EPERM; + int ret_val; unsigned char *buf = NULL; u32 buf_len; 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, GFP_ATOMIC); if (buf == NULL) @@ -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 * possibile as specified in section 3.4.2.6 of the * CIPSO draft. */ - if (cipso_v4_rbm_optfmt && (ret_val > 0 && ret_val < 10)) - ret_val = 10; - - buf_len = 4 + ret_val; + if (cipso_v4_rbm_optfmt && ret_val > 0 && ret_val <= 10) + buf_len = 14; + else + buf_len = 4 + ret_val; } else { buf = kzalloc(CIPSO_V4_HDR_LEN + 4, GFP_ATOMIC); if (buf == NULL) @@ -1070,7 +1074,7 @@ static int cipso_v4_parsetag_rbm(const struct cipso_v4_doi *doi_def, if (ret_val != 0) return ret_val; secattr->mls_lvl = level; - secattr->mls_lvl_vld = 1; + secattr->flags |= NETLBL_SECATTR_MLS_LVL; if (tag_len > 4) { switch (doi_def->type) { @@ -1094,8 +1098,10 @@ static int cipso_v4_parsetag_rbm(const struct cipso_v4_doi *doi_def, if (ret_val < 0) { kfree(secattr->mls_cat); 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; diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index ff971103fd..da2f1975a0 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c @@ -62,6 +62,9 @@ int netlbl_socket_setattr(const struct socket *sock, int ret_val = -ENOENT; struct netlbl_dom_map *dom_entry; + if ((secattr->flags & NETLBL_SECATTR_DOMAIN) == 0) + return -ENOENT; + rcu_read_lock(); dom_entry = netlbl_domhsh_getentry(secattr->domain); if (dom_entry == NULL) @@ -200,7 +203,7 @@ void netlbl_cache_invalidate(void) int netlbl_cache_add(const struct sk_buff *skb, const struct netlbl_lsm_secattr *secattr) { - if (secattr->cache == NULL) + if ((secattr->flags & NETLBL_SECATTR_CACHE) == 0) return -ENOMSG; if (CIPSO_V4_OPTEXIST(skb)) diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 408820486a..1f5bbb246d 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -2254,8 +2254,6 @@ static void selinux_netlbl_cache_add(struct sk_buff *skb, struct context *ctx) cache = kzalloc(sizeof(*cache), GFP_ATOMIC); if (cache == NULL) goto netlbl_cache_add_return; - secattr.cache->free = selinux_netlbl_cache_free; - secattr.cache->data = (void *)cache; cache->type = NETLBL_CACHE_T_MLS; 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) cache->data.mls_label.level[0].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_return: @@ -2313,7 +2315,7 @@ static int selinux_netlbl_secattr_to_sid(struct sk_buff *skb, POLICY_RDLOCK; - if (secattr->cache) { + if (secattr->flags & NETLBL_SECATTR_CACHE) { cache = NETLBL_CACHE(secattr->cache->data); switch (cache->type) { case NETLBL_CACHE_T_SID: @@ -2346,7 +2348,7 @@ static int selinux_netlbl_secattr_to_sid(struct sk_buff *skb, default: 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); if (ctx == NULL) goto netlbl_secattr_to_sid_return; @@ -2355,7 +2357,7 @@ static int selinux_netlbl_secattr_to_sid(struct sk_buff *skb, ctx_new.role = ctx->role; ctx_new.type = ctx->type; 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, secattr->mls_cat, secattr->mls_cat_len, @@ -2414,11 +2416,13 @@ static int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, netlbl_secattr_init(&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, &secattr, base_sid, sid); + else + *sid = SECSID_NULL; netlbl_secattr_destroy(&secattr); return rc; @@ -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], GFP_ATOMIC); mls_export_lvl(ctx, &secattr.mls_lvl, NULL); - secattr.mls_lvl_vld = 1; rc = mls_export_cat(ctx, &secattr.mls_cat, &secattr.mls_cat_len, @@ -2464,6 +2467,10 @@ static int selinux_netlbl_socket_setsid(struct socket *sock, u32 sid) if (rc != 0) 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); if (rc == 0) sksec->nlbl_state = NLBL_LABELED; @@ -2564,6 +2571,7 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock) netlbl_secattr_init(&secattr); if (netlbl_sock_getattr(sk, &secattr) == 0 && + secattr.flags != NETLBL_SECATTR_NONE && selinux_netlbl_secattr_to_sid(NULL, &secattr, SECINITSID_UNLABELED, @@ -2756,7 +2764,7 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock, sksec->nlbl_state == NLBL_LABELED) { netlbl_secattr_init(&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; netlbl_secattr_destroy(&secattr); }