SELinux: Allow NetLabel to directly cache SIDs
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>
This commit is contained in:
@@ -3468,11 +3468,7 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
|
|||||||
u32 nlbl_type;
|
u32 nlbl_type;
|
||||||
|
|
||||||
selinux_skb_xfrm_sid(skb, &xfrm_sid);
|
selinux_skb_xfrm_sid(skb, &xfrm_sid);
|
||||||
selinux_netlbl_skbuff_getsid(skb,
|
selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
|
||||||
family,
|
|
||||||
SECINITSID_NETMSG,
|
|
||||||
&nlbl_type,
|
|
||||||
&nlbl_sid);
|
|
||||||
|
|
||||||
if (security_net_peersid_resolve(nlbl_sid, nlbl_type,
|
if (security_net_peersid_resolve(nlbl_sid, nlbl_type,
|
||||||
xfrm_sid,
|
xfrm_sid,
|
||||||
|
@@ -48,7 +48,6 @@ void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec,
|
|||||||
|
|
||||||
int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
|
int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
|
||||||
u16 family,
|
u16 family,
|
||||||
u32 base_sid,
|
|
||||||
u32 *type,
|
u32 *type,
|
||||||
u32 *sid);
|
u32 *sid);
|
||||||
|
|
||||||
@@ -89,7 +88,6 @@ static inline void selinux_netlbl_sk_security_clone(
|
|||||||
|
|
||||||
static inline int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
|
static inline int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
|
||||||
u16 family,
|
u16 family,
|
||||||
u32 base_sid,
|
|
||||||
u32 *type,
|
u32 *type,
|
||||||
u32 *sid)
|
u32 *sid)
|
||||||
{
|
{
|
||||||
|
@@ -124,7 +124,6 @@ int security_genfs_sid(const char *fstype, char *name, u16 sclass,
|
|||||||
|
|
||||||
#ifdef CONFIG_NETLABEL
|
#ifdef CONFIG_NETLABEL
|
||||||
int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
|
int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
|
||||||
u32 base_sid,
|
|
||||||
u32 *sid);
|
u32 *sid);
|
||||||
|
|
||||||
int security_netlbl_sid_to_secattr(u32 sid,
|
int security_netlbl_sid_to_secattr(u32 sid,
|
||||||
@@ -132,7 +131,6 @@ int security_netlbl_sid_to_secattr(u32 sid,
|
|||||||
#else
|
#else
|
||||||
static inline int security_netlbl_secattr_to_sid(
|
static inline int security_netlbl_secattr_to_sid(
|
||||||
struct netlbl_lsm_secattr *secattr,
|
struct netlbl_lsm_secattr *secattr,
|
||||||
u32 base_sid,
|
|
||||||
u32 *sid)
|
u32 *sid)
|
||||||
{
|
{
|
||||||
return -EIDRM;
|
return -EIDRM;
|
||||||
|
@@ -35,6 +35,33 @@
|
|||||||
#include "objsec.h"
|
#include "objsec.h"
|
||||||
#include "security.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
|
* selinux_netlbl_sock_setsid - Label a socket using the NetLabel mechanism
|
||||||
* @sk: the socket to label
|
* @sk: the socket to label
|
||||||
@@ -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
|
* selinux_netlbl_skbuff_getsid - Get the sid of a packet using NetLabel
|
||||||
* @skb: the packet
|
* @skb: the packet
|
||||||
* @family: protocol family
|
* @family: protocol family
|
||||||
* @base_sid: the SELinux SID to use as a context for MLS only attributes
|
|
||||||
* @type: NetLabel labeling protocol type
|
* @type: NetLabel labeling protocol type
|
||||||
* @sid: the SID
|
* @sid: the SID
|
||||||
*
|
*
|
||||||
@@ -156,7 +182,6 @@ void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec,
|
|||||||
*/
|
*/
|
||||||
int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
|
int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
|
||||||
u16 family,
|
u16 family,
|
||||||
u32 base_sid,
|
|
||||||
u32 *type,
|
u32 *type,
|
||||||
u32 *sid)
|
u32 *sid)
|
||||||
{
|
{
|
||||||
@@ -170,13 +195,9 @@ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
|
|||||||
|
|
||||||
netlbl_secattr_init(&secattr);
|
netlbl_secattr_init(&secattr);
|
||||||
rc = netlbl_skbuff_getattr(skb, family, &secattr);
|
rc = netlbl_skbuff_getattr(skb, family, &secattr);
|
||||||
if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE) {
|
if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE)
|
||||||
rc = security_netlbl_secattr_to_sid(&secattr, base_sid, sid);
|
rc = selinux_netlbl_sidlookup_cached(skb, &secattr, sid);
|
||||||
if (rc == 0 &&
|
else
|
||||||
(secattr.flags & NETLBL_SECATTR_CACHEABLE) &&
|
|
||||||
(secattr.flags & NETLBL_SECATTR_CACHE))
|
|
||||||
netlbl_cache_add(skb, &secattr);
|
|
||||||
} else
|
|
||||||
*sid = SECSID_NULL;
|
*sid = SECSID_NULL;
|
||||||
*type = secattr.type;
|
*type = secattr.type;
|
||||||
netlbl_secattr_destroy(&secattr);
|
netlbl_secattr_destroy(&secattr);
|
||||||
@@ -210,9 +231,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 &&
|
secattr.flags != NETLBL_SECATTR_NONE &&
|
||||||
security_netlbl_secattr_to_sid(&secattr,
|
security_netlbl_secattr_to_sid(&secattr, &nlbl_peer_sid) == 0)
|
||||||
SECINITSID_NETMSG,
|
|
||||||
&nlbl_peer_sid) == 0)
|
|
||||||
sksec->peer_sid = nlbl_peer_sid;
|
sksec->peer_sid = nlbl_peer_sid;
|
||||||
netlbl_secattr_destroy(&secattr);
|
netlbl_secattr_destroy(&secattr);
|
||||||
|
|
||||||
@@ -316,15 +335,9 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
|
|||||||
|
|
||||||
netlbl_secattr_init(&secattr);
|
netlbl_secattr_init(&secattr);
|
||||||
rc = netlbl_skbuff_getattr(skb, family, &secattr);
|
rc = netlbl_skbuff_getattr(skb, family, &secattr);
|
||||||
if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE) {
|
if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE)
|
||||||
rc = security_netlbl_secattr_to_sid(&secattr,
|
rc = selinux_netlbl_sidlookup_cached(skb, &secattr, &nlbl_sid);
|
||||||
SECINITSID_NETMSG,
|
else
|
||||||
&nlbl_sid);
|
|
||||||
if (rc == 0 &&
|
|
||||||
(secattr.flags & NETLBL_SECATTR_CACHEABLE) &&
|
|
||||||
(secattr.flags & NETLBL_SECATTR_CACHE))
|
|
||||||
netlbl_cache_add(skb, &secattr);
|
|
||||||
} else
|
|
||||||
nlbl_sid = SECINITSID_UNLABELED;
|
nlbl_sid = SECINITSID_UNLABELED;
|
||||||
netlbl_secattr_destroy(&secattr);
|
netlbl_secattr_destroy(&secattr);
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
|
@@ -2547,50 +2547,10 @@ void selinux_audit_set_callback(int (*callback)(void))
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_NETLABEL
|
#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
|
* security_netlbl_cache_add - Add an entry to the NetLabel cache
|
||||||
* @secattr: the NetLabel packet security attributes
|
* @secattr: the NetLabel packet security attributes
|
||||||
* @ctx: the SELinux context
|
* @sid: the SELinux SID
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Attempt to cache the context in @ctx, which was derived from the packet in
|
* Attempt to cache the context in @ctx, which was derived from the packet in
|
||||||
@@ -2599,60 +2559,46 @@ static void security_netlbl_cache_free(const void *data)
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static void security_netlbl_cache_add(struct netlbl_lsm_secattr *secattr,
|
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;
|
||||||
|
|
||||||
|
sid_cache = kmalloc(sizeof(*sid_cache), GFP_ATOMIC);
|
||||||
|
if (sid_cache == NULL)
|
||||||
|
return;
|
||||||
secattr->cache = netlbl_secattr_cache_alloc(GFP_ATOMIC);
|
secattr->cache = netlbl_secattr_cache_alloc(GFP_ATOMIC);
|
||||||
if (secattr->cache == NULL)
|
if (secattr->cache == NULL) {
|
||||||
return;
|
kfree(sid_cache);
|
||||||
|
|
||||||
cache = kzalloc(sizeof(*cache), GFP_ATOMIC);
|
|
||||||
if (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);
|
|
||||||
return;
|
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;
|
*sid_cache = sid;
|
||||||
secattr->cache->data = (void *)cache;
|
secattr->cache->free = kfree;
|
||||||
|
secattr->cache->data = sid_cache;
|
||||||
secattr->flags |= NETLBL_SECATTR_CACHE;
|
secattr->flags |= NETLBL_SECATTR_CACHE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* security_netlbl_secattr_to_sid - Convert a NetLabel secattr to a SELinux SID
|
* security_netlbl_secattr_to_sid - Convert a NetLabel secattr to a SELinux SID
|
||||||
* @secattr: the NetLabel packet security attributes
|
* @secattr: the NetLabel packet security attributes
|
||||||
* @base_sid: the SELinux SID to use as a context for MLS only attributes
|
|
||||||
* @sid: the SELinux SID
|
* @sid: the SELinux SID
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Convert the given NetLabel security attributes in @secattr into a
|
* Convert the given NetLabel security attributes in @secattr into a
|
||||||
* SELinux SID. If the @secattr field does not contain a full SELinux
|
* 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
|
* SID/context then use SECINITSID_NETMSG as the foundation. If possibile the
|
||||||
* possibile the 'cache' field of @secattr is set and the CACHE flag is set;
|
* 'cache' field of @secattr is set and the CACHE flag is set; this is to
|
||||||
* this is to allow the @secattr to be used by NetLabel to cache the secattr to
|
* allow the @secattr to be used by NetLabel to cache the secattr to SID
|
||||||
* SID conversion for future lookups. Returns zero on success, negative
|
* conversion for future lookups. Returns zero on success, negative values on
|
||||||
* values on failure.
|
* failure.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
|
int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
|
||||||
u32 base_sid,
|
|
||||||
u32 *sid)
|
u32 *sid)
|
||||||
{
|
{
|
||||||
int rc = -EIDRM;
|
int rc = -EIDRM;
|
||||||
struct context *ctx;
|
struct context *ctx;
|
||||||
struct context ctx_new;
|
struct context ctx_new;
|
||||||
struct selinux_netlbl_cache *cache;
|
|
||||||
|
|
||||||
if (!ss_initialized) {
|
if (!ss_initialized) {
|
||||||
*sid = SECSID_NULL;
|
*sid = SECSID_NULL;
|
||||||
@@ -2662,43 +2608,13 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
|
|||||||
POLICY_RDLOCK;
|
POLICY_RDLOCK;
|
||||||
|
|
||||||
if (secattr->flags & NETLBL_SECATTR_CACHE) {
|
if (secattr->flags & NETLBL_SECATTR_CACHE) {
|
||||||
cache = NETLBL_CACHE(secattr->cache->data);
|
*sid = *(u32 *)secattr->cache->data;
|
||||||
switch (cache->type) {
|
rc = 0;
|
||||||
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;
|
|
||||||
}
|
|
||||||
} else if (secattr->flags & NETLBL_SECATTR_SECID) {
|
} else if (secattr->flags & NETLBL_SECATTR_SECID) {
|
||||||
*sid = secattr->attr.secid;
|
*sid = secattr->attr.secid;
|
||||||
rc = 0;
|
rc = 0;
|
||||||
} else if (secattr->flags & NETLBL_SECATTR_MLS_LVL) {
|
} else if (secattr->flags & NETLBL_SECATTR_MLS_LVL) {
|
||||||
ctx = sidtab_search(&sidtab, base_sid);
|
ctx = sidtab_search(&sidtab, SECINITSID_NETMSG);
|
||||||
if (ctx == NULL)
|
if (ctx == NULL)
|
||||||
goto netlbl_secattr_to_sid_return;
|
goto netlbl_secattr_to_sid_return;
|
||||||
|
|
||||||
@@ -2725,7 +2641,7 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
|
|||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
goto netlbl_secattr_to_sid_return_cleanup;
|
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);
|
ebitmap_destroy(&ctx_new.range.level[0].cat);
|
||||||
} else {
|
} else {
|
||||||
|
Reference in New Issue
Block a user