Skip to content

Commit

Permalink
SELinux: Allow NetLabel to directly cache SIDs
Browse files Browse the repository at this point in the history
Now that the SELinux NetLabel "base SID" is always the netmsg initial SID we
can do a big optimization - caching the SID and not just the MLS attributes.
This not only saves a lot of per-packet memory allocations and copies but it
has a nice side effect of removing a chunk of code.

Signed-off-by: Paul Moore <paul.moore@hp.com>
Signed-off-by: James Morris <jmorris@namei.org>
  • Loading branch information
Paul Moore authored and James Morris committed Jan 29, 2008
1 parent d621d35 commit 5dbe1eb
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 134 deletions.
6 changes: 1 addition & 5 deletions security/selinux/hooks.c
Original file line number Diff line number Diff line change
Expand Up @@ -3468,11 +3468,7 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
u32 nlbl_type;

selinux_skb_xfrm_sid(skb, &xfrm_sid);
selinux_netlbl_skbuff_getsid(skb,
family,
SECINITSID_NETMSG,
&nlbl_type,
&nlbl_sid);
selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);

if (security_net_peersid_resolve(nlbl_sid, nlbl_type,
xfrm_sid,
Expand Down
2 changes: 0 additions & 2 deletions security/selinux/include/netlabel.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec,

int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
u16 family,
u32 base_sid,
u32 *type,
u32 *sid);

Expand Down Expand Up @@ -89,7 +88,6 @@ static inline void selinux_netlbl_sk_security_clone(

static inline int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
u16 family,
u32 base_sid,
u32 *type,
u32 *sid)
{
Expand Down
2 changes: 0 additions & 2 deletions security/selinux/include/security.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,15 +124,13 @@ int security_genfs_sid(const char *fstype, char *name, u16 sclass,

#ifdef CONFIG_NETLABEL
int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
u32 base_sid,
u32 *sid);

int security_netlbl_sid_to_secattr(u32 sid,
struct netlbl_lsm_secattr *secattr);
#else
static inline int security_netlbl_secattr_to_sid(
struct netlbl_lsm_secattr *secattr,
u32 base_sid,
u32 *sid)
{
return -EIDRM;
Expand Down
55 changes: 34 additions & 21 deletions security/selinux/netlabel.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,33 @@
#include "objsec.h"
#include "security.h"

/**
* selinux_netlbl_sidlookup_cached - Cache a SID lookup
* @skb: the packet
* @secattr: the NetLabel security attributes
* @sid: the SID
*
* Description:
* Query the SELinux security server to lookup the correct SID for the given
* security attributes. If the query is successful, cache the result to speed
* up future lookups. Returns zero on success, negative values on failure.
*
*/
static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb,
struct netlbl_lsm_secattr *secattr,
u32 *sid)
{
int rc;

rc = security_netlbl_secattr_to_sid(secattr, sid);
if (rc == 0 &&
(secattr->flags & NETLBL_SECATTR_CACHEABLE) &&
(secattr->flags & NETLBL_SECATTR_CACHE))
netlbl_cache_add(skb, secattr);

return rc;
}

/**
* selinux_netlbl_sock_setsid - Label a socket using the NetLabel mechanism
* @sk: the socket to label
Expand Down Expand Up @@ -144,7 +171,6 @@ void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec,
* selinux_netlbl_skbuff_getsid - Get the sid of a packet using NetLabel
* @skb: the packet
* @family: protocol family
* @base_sid: the SELinux SID to use as a context for MLS only attributes
* @type: NetLabel labeling protocol type
* @sid: the SID
*
Expand All @@ -156,7 +182,6 @@ void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec,
*/
int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
u16 family,
u32 base_sid,
u32 *type,
u32 *sid)
{
Expand All @@ -170,13 +195,9 @@ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,

netlbl_secattr_init(&secattr);
rc = netlbl_skbuff_getattr(skb, family, &secattr);
if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE) {
rc = security_netlbl_secattr_to_sid(&secattr, base_sid, sid);
if (rc == 0 &&
(secattr.flags & NETLBL_SECATTR_CACHEABLE) &&
(secattr.flags & NETLBL_SECATTR_CACHE))
netlbl_cache_add(skb, &secattr);
} else
if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE)
rc = selinux_netlbl_sidlookup_cached(skb, &secattr, sid);
else
*sid = SECSID_NULL;
*type = secattr.type;
netlbl_secattr_destroy(&secattr);
Expand Down Expand Up @@ -210,9 +231,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 &&
security_netlbl_secattr_to_sid(&secattr,
SECINITSID_NETMSG,
&nlbl_peer_sid) == 0)
security_netlbl_secattr_to_sid(&secattr, &nlbl_peer_sid) == 0)
sksec->peer_sid = nlbl_peer_sid;
netlbl_secattr_destroy(&secattr);

Expand Down Expand Up @@ -316,15 +335,9 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,

netlbl_secattr_init(&secattr);
rc = netlbl_skbuff_getattr(skb, family, &secattr);
if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE) {
rc = security_netlbl_secattr_to_sid(&secattr,
SECINITSID_NETMSG,
&nlbl_sid);
if (rc == 0 &&
(secattr.flags & NETLBL_SECATTR_CACHEABLE) &&
(secattr.flags & NETLBL_SECATTR_CACHE))
netlbl_cache_add(skb, &secattr);
} else
if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE)
rc = selinux_netlbl_sidlookup_cached(skb, &secattr, &nlbl_sid);
else
nlbl_sid = SECINITSID_UNLABELED;
netlbl_secattr_destroy(&secattr);
if (rc != 0)
Expand Down
124 changes: 20 additions & 104 deletions security/selinux/ss/services.c
Original file line number Diff line number Diff line change
Expand Up @@ -2547,50 +2547,10 @@ void selinux_audit_set_callback(int (*callback)(void))
}

#ifdef CONFIG_NETLABEL
/*
* NetLabel cache structure
*/
#define NETLBL_CACHE(x) ((struct selinux_netlbl_cache *)(x))
#define NETLBL_CACHE_T_NONE 0
#define NETLBL_CACHE_T_SID 1
#define NETLBL_CACHE_T_MLS 2
struct selinux_netlbl_cache {
u32 type;
union {
u32 sid;
struct mls_range mls_label;
} data;
};

/**
* security_netlbl_cache_free - Free the NetLabel cached data
* @data: the data to free
*
* Description:
* This function is intended to be used as the free() callback inside the
* netlbl_lsm_cache structure.
*
*/
static void security_netlbl_cache_free(const void *data)
{
struct selinux_netlbl_cache *cache;

if (data == NULL)
return;

cache = NETLBL_CACHE(data);
switch (cache->type) {
case NETLBL_CACHE_T_MLS:
ebitmap_destroy(&cache->data.mls_label.level[0].cat);
break;
}
kfree(data);
}

/**
* security_netlbl_cache_add - Add an entry to the NetLabel cache
* @secattr: the NetLabel packet security attributes
* @ctx: the SELinux context
* @sid: the SELinux SID
*
* Description:
* Attempt to cache the context in @ctx, which was derived from the packet in
Expand All @@ -2599,60 +2559,46 @@ static void security_netlbl_cache_free(const void *data)
*
*/
static void security_netlbl_cache_add(struct netlbl_lsm_secattr *secattr,
struct context *ctx)
u32 sid)
{
struct selinux_netlbl_cache *cache = NULL;
u32 *sid_cache;

secattr->cache = netlbl_secattr_cache_alloc(GFP_ATOMIC);
if (secattr->cache == NULL)
return;

cache = kzalloc(sizeof(*cache), GFP_ATOMIC);
if (cache == NULL)
sid_cache = kmalloc(sizeof(*sid_cache), GFP_ATOMIC);
if (sid_cache == NULL)
return;

cache->type = NETLBL_CACHE_T_MLS;
if (ebitmap_cpy(&cache->data.mls_label.level[0].cat,
&ctx->range.level[0].cat) != 0) {
kfree(cache);
secattr->cache = netlbl_secattr_cache_alloc(GFP_ATOMIC);
if (secattr->cache == NULL) {
kfree(sid_cache);
return;
}
cache->data.mls_label.level[1].cat.highbit =
cache->data.mls_label.level[0].cat.highbit;
cache->data.mls_label.level[1].cat.node =
cache->data.mls_label.level[0].cat.node;
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 = security_netlbl_cache_free;
secattr->cache->data = (void *)cache;
*sid_cache = sid;
secattr->cache->free = kfree;
secattr->cache->data = sid_cache;
secattr->flags |= NETLBL_SECATTR_CACHE;
}

/**
* security_netlbl_secattr_to_sid - Convert a NetLabel secattr to a SELinux SID
* @secattr: the NetLabel packet security attributes
* @base_sid: the SELinux SID to use as a context for MLS only attributes
* @sid: the SELinux SID
*
* Description:
* Convert the given NetLabel security attributes in @secattr into a
* SELinux SID. If the @secattr field does not contain a full SELinux
* SID/context then use the context in @base_sid as the foundation. If
* possibile the 'cache' field of @secattr is set and the CACHE flag is set;
* this is to allow the @secattr to be used by NetLabel to cache the secattr to
* SID conversion for future lookups. Returns zero on success, negative
* values on failure.
* SID/context then use SECINITSID_NETMSG as the foundation. If possibile the
* 'cache' field of @secattr is set and the CACHE flag is set; this is to
* allow the @secattr to be used by NetLabel to cache the secattr to SID
* conversion for future lookups. Returns zero on success, negative values on
* failure.
*
*/
int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
u32 base_sid,
u32 *sid)
{
int rc = -EIDRM;
struct context *ctx;
struct context ctx_new;
struct selinux_netlbl_cache *cache;

if (!ss_initialized) {
*sid = SECSID_NULL;
Expand All @@ -2662,43 +2608,13 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
POLICY_RDLOCK;

if (secattr->flags & NETLBL_SECATTR_CACHE) {
cache = NETLBL_CACHE(secattr->cache->data);
switch (cache->type) {
case NETLBL_CACHE_T_SID:
*sid = cache->data.sid;
rc = 0;
break;
case NETLBL_CACHE_T_MLS:
ctx = sidtab_search(&sidtab, base_sid);
if (ctx == NULL)
goto netlbl_secattr_to_sid_return;

ctx_new.user = ctx->user;
ctx_new.role = ctx->role;
ctx_new.type = ctx->type;
ctx_new.range.level[0].sens =
cache->data.mls_label.level[0].sens;
ctx_new.range.level[0].cat.highbit =
cache->data.mls_label.level[0].cat.highbit;
ctx_new.range.level[0].cat.node =
cache->data.mls_label.level[0].cat.node;
ctx_new.range.level[1].sens =
cache->data.mls_label.level[1].sens;
ctx_new.range.level[1].cat.highbit =
cache->data.mls_label.level[1].cat.highbit;
ctx_new.range.level[1].cat.node =
cache->data.mls_label.level[1].cat.node;

rc = sidtab_context_to_sid(&sidtab, &ctx_new, sid);
break;
default:
goto netlbl_secattr_to_sid_return;
}
*sid = *(u32 *)secattr->cache->data;
rc = 0;
} else if (secattr->flags & NETLBL_SECATTR_SECID) {
*sid = secattr->attr.secid;
rc = 0;
} else if (secattr->flags & NETLBL_SECATTR_MLS_LVL) {
ctx = sidtab_search(&sidtab, base_sid);
ctx = sidtab_search(&sidtab, SECINITSID_NETMSG);
if (ctx == NULL)
goto netlbl_secattr_to_sid_return;

Expand All @@ -2725,7 +2641,7 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
if (rc != 0)
goto netlbl_secattr_to_sid_return_cleanup;

security_netlbl_cache_add(secattr, &ctx_new);
security_netlbl_cache_add(secattr, *sid);

ebitmap_destroy(&ctx_new.range.level[0].cat);
} else {
Expand Down

0 comments on commit 5dbe1eb

Please sign in to comment.