From 5dbe1eb0cfc144a2b0cb1466e22bcb6fc34229a8 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Tue, 29 Jan 2008 08:44:18 -0500 Subject: 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 Signed-off-by: James Morris --- security/selinux/hooks.c | 6 +- security/selinux/include/netlabel.h | 2 - security/selinux/include/security.h | 2 - security/selinux/netlabel.c | 55 ++++++++++------ security/selinux/ss/services.c | 124 ++++++------------------------------ 5 files changed, 55 insertions(+), 134 deletions(-) (limited to 'security/selinux') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 6156241c8770..c90e865a8603 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -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, diff --git a/security/selinux/include/netlabel.h b/security/selinux/include/netlabel.h index c8c05a6f298c..00a2809c8506 100644 --- a/security/selinux/include/netlabel.h +++ b/security/selinux/include/netlabel.h @@ -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); @@ -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) { diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 9347e2daa8d4..23137c17f917 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -124,7 +124,6 @@ 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, @@ -132,7 +131,6 @@ int security_netlbl_sid_to_secattr(u32 sid, #else static inline int security_netlbl_secattr_to_sid( struct netlbl_lsm_secattr *secattr, - u32 base_sid, u32 *sid) { return -EIDRM; diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index b54d28fd3b5d..0fa2be4149e8 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c @@ -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 @@ -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 * @@ -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) { @@ -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); @@ -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); @@ -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) diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 7f0ee1b91e1d..f96dec1f9258 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -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 @@ -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; @@ -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; @@ -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 { -- cgit v1.2.3