Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+11 −2
Original line number Diff line number Diff line
@@ -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;
}

/**
+14 −8
Original line number Diff line number Diff line
@@ -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,9 +1017,9 @@ 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;

		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);
@@ -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;
		}
	}

	return 0;
+4 −1
Original line number Diff line number Diff line
@@ -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))
+16 −8
Original line number Diff line number Diff line
@@ -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);
	}