aboutsummaryrefslogtreecommitdiff
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/selinux/ss/ebitmap.c198
-rw-r--r--security/selinux/ss/ebitmap.h26
-rw-r--r--security/selinux/ss/mls.c156
-rw-r--r--security/selinux/ss/mls.h46
-rw-r--r--security/selinux/ss/services.c23
5 files changed, 199 insertions, 250 deletions
diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c
index d539346ab3a..ce492a6b38e 100644
--- a/security/selinux/ss/ebitmap.c
+++ b/security/selinux/ss/ebitmap.c
@@ -6,7 +6,7 @@
/*
* Updated: Hewlett-Packard <paul.moore@hp.com>
*
- * Added ebitmap_export() and ebitmap_import()
+ * Added support to import/export the NetLabel category bitmap
*
* (c) Copyright Hewlett-Packard Development Company, L.P., 2006
*/
@@ -14,6 +14,7 @@
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/errno.h>
+#include <net/netlabel.h>
#include "ebitmap.h"
#include "policydb.h"
@@ -67,141 +68,120 @@ int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src)
return 0;
}
+#ifdef CONFIG_NETLABEL
/**
- * ebitmap_export - Export an ebitmap to a unsigned char bitmap string
- * @src: the ebitmap to export
- * @dst: the resulting bitmap string
- * @dst_len: length of dst in bytes
+ * ebitmap_netlbl_export - Export an ebitmap into a NetLabel category bitmap
+ * @ebmap: the ebitmap to export
+ * @catmap: the NetLabel category bitmap
*
* Description:
- * Allocate a buffer at least src->highbit bits long and export the extensible
- * bitmap into the buffer. The bitmap string will be in little endian format,
- * i.e. LSB first. The value returned in dst_len may not the true size of the
- * buffer as the length of the buffer is rounded up to a multiple of MAPTYPE.
- * The caller must free the buffer when finished. Returns zero on success,
- * negative values on failure.
+ * Export a SELinux extensibile bitmap into a NetLabel category bitmap.
+ * Returns zero on success, negative values on error.
*
*/
-int ebitmap_export(const struct ebitmap *src,
- unsigned char **dst,
- size_t *dst_len)
+int ebitmap_netlbl_export(struct ebitmap *ebmap,
+ struct netlbl_lsm_secattr_catmap **catmap)
{
- size_t bitmap_len;
- unsigned char *bitmap;
- struct ebitmap_node *iter_node;
- MAPTYPE node_val;
- size_t bitmap_byte;
- unsigned char bitmask;
-
- if (src->highbit == 0) {
- *dst = NULL;
- *dst_len = 0;
+ struct ebitmap_node *e_iter = ebmap->node;
+ struct netlbl_lsm_secattr_catmap *c_iter;
+ u32 cmap_idx;
+
+ /* This function is a much simpler because SELinux's MAPTYPE happens
+ * to be the same as NetLabel's NETLBL_CATMAP_MAPTYPE, if MAPTYPE is
+ * changed from a u64 this function will most likely need to be changed
+ * as well. It's not ideal but I think the tradeoff in terms of
+ * neatness and speed is worth it. */
+
+ if (e_iter == NULL) {
+ *catmap = NULL;
return 0;
}
- bitmap_len = src->highbit / 8;
- if (src->highbit % 7)
- bitmap_len += 1;
-
- bitmap = kzalloc((bitmap_len & ~(sizeof(MAPTYPE) - 1)) +
- sizeof(MAPTYPE),
- GFP_ATOMIC);
- if (bitmap == NULL)
+ c_iter = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
+ if (c_iter == NULL)
return -ENOMEM;
+ *catmap = c_iter;
+ c_iter->startbit = e_iter->startbit & ~(NETLBL_CATMAP_SIZE - 1);
+
+ while (e_iter != NULL) {
+ if (e_iter->startbit >=
+ (c_iter->startbit + NETLBL_CATMAP_SIZE)) {
+ c_iter->next = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
+ if (c_iter->next == NULL)
+ goto netlbl_export_failure;
+ c_iter = c_iter->next;
+ c_iter->startbit = e_iter->startbit &
+ ~(NETLBL_CATMAP_SIZE - 1);
+ }
+ cmap_idx = (e_iter->startbit - c_iter->startbit) /
+ NETLBL_CATMAP_MAPSIZE;
+ c_iter->bitmap[cmap_idx] = e_iter->map;
+ e_iter = e_iter->next;
+ }
- iter_node = src->node;
- do {
- bitmap_byte = iter_node->startbit / 8;
- bitmask = 0x80;
- node_val = iter_node->map;
- do {
- if (bitmask == 0) {
- bitmap_byte++;
- bitmask = 0x80;
- }
- if (node_val & (MAPTYPE)0x01)
- bitmap[bitmap_byte] |= bitmask;
- node_val >>= 1;
- bitmask >>= 1;
- } while (node_val > 0);
- iter_node = iter_node->next;
- } while (iter_node);
-
- *dst = bitmap;
- *dst_len = bitmap_len;
return 0;
+
+netlbl_export_failure:
+ netlbl_secattr_catmap_free(*catmap);
+ return -ENOMEM;
}
/**
- * ebitmap_import - Import an unsigned char bitmap string into an ebitmap
- * @src: the bitmap string
- * @src_len: the bitmap length in bytes
- * @dst: the empty ebitmap
+ * ebitmap_netlbl_import - Import a NetLabel category bitmap into an ebitmap
+ * @ebmap: the ebitmap to export
+ * @catmap: the NetLabel category bitmap
*
* Description:
- * This function takes a little endian bitmap string in src and imports it into
- * the ebitmap pointed to by dst. Returns zero on success, negative values on
- * failure.
+ * Import a NetLabel category bitmap into a SELinux extensibile bitmap.
+ * Returns zero on success, negative values on error.
*
*/
-int ebitmap_import(const unsigned char *src,
- size_t src_len,
- struct ebitmap *dst)
+int ebitmap_netlbl_import(struct ebitmap *ebmap,
+ struct netlbl_lsm_secattr_catmap *catmap)
{
- size_t src_off = 0;
- size_t node_limit;
- struct ebitmap_node *node_new;
- struct ebitmap_node *node_last = NULL;
- u32 i_byte;
- u32 i_bit;
- unsigned char src_byte;
-
- while (src_off < src_len) {
- if (src_len - src_off >= sizeof(MAPTYPE)) {
- if (*(MAPTYPE *)&src[src_off] == 0) {
- src_off += sizeof(MAPTYPE);
- continue;
- }
- node_limit = sizeof(MAPTYPE);
- } else {
- for (src_byte = 0, i_byte = src_off;
- i_byte < src_len && src_byte == 0;
- i_byte++)
- src_byte |= src[i_byte];
- if (src_byte == 0)
- break;
- node_limit = src_len - src_off;
- }
+ struct ebitmap_node *e_iter = NULL;
+ struct ebitmap_node *emap_prev = NULL;
+ struct netlbl_lsm_secattr_catmap *c_iter = catmap;
+ u32 c_idx;
- node_new = kzalloc(sizeof(*node_new), GFP_ATOMIC);
- if (unlikely(node_new == NULL)) {
- ebitmap_destroy(dst);
- return -ENOMEM;
- }
- node_new->startbit = src_off * 8;
- for (i_byte = 0; i_byte < node_limit; i_byte++) {
- src_byte = src[src_off++];
- for (i_bit = i_byte * 8; src_byte != 0; i_bit++) {
- if (src_byte & 0x80)
- node_new->map |= MAPBIT << i_bit;
- src_byte <<= 1;
- }
- }
+ /* This function is a much simpler because SELinux's MAPTYPE happens
+ * to be the same as NetLabel's NETLBL_CATMAP_MAPTYPE, if MAPTYPE is
+ * changed from a u64 this function will most likely need to be changed
+ * as well. It's not ideal but I think the tradeoff in terms of
+ * neatness and speed is worth it. */
- if (node_last != NULL)
- node_last->next = node_new;
- else
- dst->node = node_new;
- node_last = node_new;
- }
+ do {
+ for (c_idx = 0; c_idx < NETLBL_CATMAP_MAPCNT; c_idx++) {
+ if (c_iter->bitmap[c_idx] == 0)
+ continue;
+
+ e_iter = kzalloc(sizeof(*e_iter), GFP_ATOMIC);
+ if (e_iter == NULL)
+ goto netlbl_import_failure;
+ if (emap_prev == NULL)
+ ebmap->node = e_iter;
+ else
+ emap_prev->next = e_iter;
+ emap_prev = e_iter;
- if (likely(node_last != NULL))
- dst->highbit = node_last->startbit + MAPSIZE;
+ e_iter->startbit = c_iter->startbit +
+ NETLBL_CATMAP_MAPSIZE * c_idx;
+ e_iter->map = c_iter->bitmap[c_idx];
+ }
+ c_iter = c_iter->next;
+ } while (c_iter != NULL);
+ if (e_iter != NULL)
+ ebmap->highbit = e_iter->startbit + MAPSIZE;
else
- ebitmap_init(dst);
+ ebitmap_destroy(ebmap);
return 0;
+
+netlbl_import_failure:
+ ebitmap_destroy(ebmap);
+ return -ENOMEM;
}
+#endif /* CONFIG_NETLABEL */
int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2)
{
diff --git a/security/selinux/ss/ebitmap.h b/security/selinux/ss/ebitmap.h
index da2d4651b10..1270e34b61c 100644
--- a/security/selinux/ss/ebitmap.h
+++ b/security/selinux/ss/ebitmap.h
@@ -14,6 +14,8 @@
#ifndef _SS_EBITMAP_H_
#define _SS_EBITMAP_H_
+#include <net/netlabel.h>
+
#define MAPTYPE u64 /* portion of bitmap in each node */
#define MAPSIZE (sizeof(MAPTYPE) * 8) /* number of bits in node bitmap */
#define MAPBIT 1ULL /* a bit in the node bitmap */
@@ -69,16 +71,28 @@ static inline int ebitmap_node_get_bit(struct ebitmap_node * n,
int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2);
int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src);
-int ebitmap_export(const struct ebitmap *src,
- unsigned char **dst,
- size_t *dst_len);
-int ebitmap_import(const unsigned char *src,
- size_t src_len,
- struct ebitmap *dst);
int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2);
int ebitmap_get_bit(struct ebitmap *e, unsigned long bit);
int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value);
void ebitmap_destroy(struct ebitmap *e);
int ebitmap_read(struct ebitmap *e, void *fp);
+#ifdef CONFIG_NETLABEL
+int ebitmap_netlbl_export(struct ebitmap *ebmap,
+ struct netlbl_lsm_secattr_catmap **catmap);
+int ebitmap_netlbl_import(struct ebitmap *ebmap,
+ struct netlbl_lsm_secattr_catmap *catmap);
+#else
+static inline int ebitmap_netlbl_export(struct ebitmap *ebmap,
+ struct netlbl_lsm_secattr_catmap **catmap)
+{
+ return -ENOMEM;
+}
+static inline int ebitmap_netlbl_import(struct ebitmap *ebmap,
+ struct netlbl_lsm_secattr_catmap *catmap)
+{
+ return -ENOMEM;
+}
+#endif
+
#endif /* _SS_EBITMAP_H_ */
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
index 2cca8e25162..b4f682dc13f 100644
--- a/security/selinux/ss/mls.c
+++ b/security/selinux/ss/mls.c
@@ -13,7 +13,7 @@
/*
* Updated: Hewlett-Packard <paul.moore@hp.com>
*
- * Added support to import/export the MLS label
+ * Added support to import/export the MLS label from NetLabel
*
* (c) Copyright Hewlett-Packard Development Company, L.P., 2006
*/
@@ -22,6 +22,7 @@
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/errno.h>
+#include <net/netlabel.h>
#include "sidtab.h"
#include "mls.h"
#include "policydb.h"
@@ -571,163 +572,108 @@ int mls_compute_sid(struct context *scontext,
return -EINVAL;
}
+#ifdef CONFIG_NETLABEL
/**
- * mls_export_lvl - Export the MLS sensitivity levels
+ * mls_export_netlbl_lvl - Export the MLS sensitivity levels to NetLabel
* @context: the security context
- * @low: the low sensitivity level
- * @high: the high sensitivity level
+ * @secattr: the NetLabel security attributes
*
* Description:
- * Given the security context copy the low MLS sensitivity level into lvl_low
- * and the high sensitivity level in lvl_high. The MLS levels are only
- * exported if the pointers are not NULL, if they are NULL then that level is
- * not exported.
+ * Given the security context copy the low MLS sensitivity level into the
+ * NetLabel MLS sensitivity level field.
*
*/
-void mls_export_lvl(const struct context *context, u32 *low, u32 *high)
+void mls_export_netlbl_lvl(struct context *context,
+ struct netlbl_lsm_secattr *secattr)
{
if (!selinux_mls_enabled)
return;
- if (low != NULL)
- *low = context->range.level[0].sens - 1;
- if (high != NULL)
- *high = context->range.level[1].sens - 1;
+ secattr->mls_lvl = context->range.level[0].sens - 1;
+ secattr->flags |= NETLBL_SECATTR_MLS_LVL;
}
/**
- * mls_import_lvl - Import the MLS sensitivity levels
+ * mls_import_netlbl_lvl - Import the NetLabel MLS sensitivity levels
* @context: the security context
- * @low: the low sensitivity level
- * @high: the high sensitivity level
+ * @secattr: the NetLabel security attributes
*
* Description:
- * Given the security context and the two sensitivty levels, set the MLS levels
- * in the context according the two given as parameters. Returns zero on
- * success, negative values on failure.
+ * Given the security context and the NetLabel security attributes, copy the
+ * NetLabel MLS sensitivity level into the context.
*
*/
-void mls_import_lvl(struct context *context, u32 low, u32 high)
+void mls_import_netlbl_lvl(struct context *context,
+ struct netlbl_lsm_secattr *secattr)
{
if (!selinux_mls_enabled)
return;
- context->range.level[0].sens = low + 1;
- context->range.level[1].sens = high + 1;
+ context->range.level[0].sens = secattr->mls_lvl + 1;
+ context->range.level[1].sens = context->range.level[0].sens;
}
/**
- * mls_export_cat - Export the MLS categories
+ * mls_export_netlbl_cat - Export the MLS categories to NetLabel
* @context: the security context
- * @low: the low category
- * @low_len: length of the cat_low bitmap in bytes
- * @high: the high category
- * @high_len: length of the cat_high bitmap in bytes
+ * @secattr: the NetLabel security attributes
*
* Description:
- * Given the security context export the low MLS category bitmap into cat_low
- * and the high category bitmap into cat_high. The MLS categories are only
- * exported if the pointers are not NULL, if they are NULL then that level is
- * not exported. The caller is responsibile for freeing the memory when
- * finished. Returns zero on success, negative values on failure.
+ * Given the security context copy the low MLS categories into the NetLabel
+ * MLS category field. Returns zero on success, negative values on failure.
*
*/
-int mls_export_cat(const struct context *context,
- unsigned char **low,
- size_t *low_len,
- unsigned char **high,
- size_t *high_len)
+int mls_export_netlbl_cat(struct context *context,
+ struct netlbl_lsm_secattr *secattr)
{
- int rc = -EPERM;
+ int rc;
- if (!selinux_mls_enabled) {
- *low = NULL;
- *low_len = 0;
- *high = NULL;
- *high_len = 0;
+ if (!selinux_mls_enabled)
return 0;
- }
- if (low != NULL) {
- rc = ebitmap_export(&context->range.level[0].cat,
- low,
- low_len);
- if (rc != 0)
- goto export_cat_failure;
- }
- if (high != NULL) {
- rc = ebitmap_export(&context->range.level[1].cat,
- high,
- high_len);
- if (rc != 0)
- goto export_cat_failure;
- }
-
- return 0;
+ rc = ebitmap_netlbl_export(&context->range.level[0].cat,
+ &secattr->mls_cat);
+ if (rc == 0 && secattr->mls_cat != NULL)
+ secattr->flags |= NETLBL_SECATTR_MLS_CAT;
-export_cat_failure:
- if (low != NULL) {
- kfree(*low);
- *low = NULL;
- *low_len = 0;
- }
- if (high != NULL) {
- kfree(*high);
- *high = NULL;
- *high_len = 0;
- }
return rc;
}
/**
- * mls_import_cat - Import the MLS categories
+ * mls_import_netlbl_cat - Import the MLS categories from NetLabel
* @context: the security context
- * @low: the low category
- * @low_len: length of the cat_low bitmap in bytes
- * @high: the high category
- * @high_len: length of the cat_high bitmap in bytes
+ * @secattr: the NetLabel security attributes
*
* Description:
- * Given the security context and the two category bitmap strings import the
- * categories into the security context. The MLS categories are only imported
- * if the pointers are not NULL, if they are NULL they are skipped. Returns
- * zero on success, negative values on failure.
+ * Copy the NetLabel security attributes into the SELinux context; since the
+ * NetLabel security attribute only contains a single MLS category use it for
+ * both the low and high categories of the context. Returns zero on success,
+ * negative values on failure.
*
*/
-int mls_import_cat(struct context *context,
- const unsigned char *low,
- size_t low_len,
- const unsigned char *high,
- size_t high_len)
+int mls_import_netlbl_cat(struct context *context,
+ struct netlbl_lsm_secattr *secattr)
{
- int rc = -EPERM;
+ int rc;
if (!selinux_mls_enabled)
return 0;
- if (low != NULL) {
- rc = ebitmap_import(low,
- low_len,
- &context->range.level[0].cat);
- if (rc != 0)
- goto import_cat_failure;
- }
- if (high != NULL) {
- if (high == low)
- rc = ebitmap_cpy(&context->range.level[1].cat,
- &context->range.level[0].cat);
- else
- rc = ebitmap_import(high,
- high_len,
- &context->range.level[1].cat);
- if (rc != 0)
- goto import_cat_failure;
- }
+ rc = ebitmap_netlbl_import(&context->range.level[0].cat,
+ secattr->mls_cat);
+ if (rc != 0)
+ goto import_netlbl_cat_failure;
+
+ rc = ebitmap_cpy(&context->range.level[1].cat,
+ &context->range.level[0].cat);
+ if (rc != 0)
+ goto import_netlbl_cat_failure;
return 0;
-import_cat_failure:
+import_netlbl_cat_failure:
ebitmap_destroy(&context->range.level[0].cat);
ebitmap_destroy(&context->range.level[1].cat);
return rc;
}
+#endif /* CONFIG_NETLABEL */
diff --git a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h
index df6032c6d49..661d6fc7696 100644
--- a/security/selinux/ss/mls.h
+++ b/security/selinux/ss/mls.h
@@ -13,7 +13,7 @@
/*
* Updated: Hewlett-Packard <paul.moore@hp.com>
*
- * Added support to import/export the MLS label
+ * Added support to import/export the MLS label from NetLabel
*
* (c) Copyright Hewlett-Packard Development Company, L.P., 2006
*/
@@ -69,19 +69,37 @@ int mls_compute_sid(struct context *scontext,
int mls_setup_user_range(struct context *fromcon, struct user_datum *user,
struct context *usercon);
-void mls_export_lvl(const struct context *context, u32 *low, u32 *high);
-void mls_import_lvl(struct context *context, u32 low, u32 high);
-
-int mls_export_cat(const struct context *context,
- unsigned char **low,
- size_t *low_len,
- unsigned char **high,
- size_t *high_len);
-int mls_import_cat(struct context *context,
- const unsigned char *low,
- size_t low_len,
- const unsigned char *high,
- size_t high_len);
+#ifdef CONFIG_NETLABEL
+void mls_export_netlbl_lvl(struct context *context,
+ struct netlbl_lsm_secattr *secattr);
+void mls_import_netlbl_lvl(struct context *context,
+ struct netlbl_lsm_secattr *secattr);
+int mls_export_netlbl_cat(struct context *context,
+ struct netlbl_lsm_secattr *secattr);
+int mls_import_netlbl_cat(struct context *context,
+ struct netlbl_lsm_secattr *secattr);
+#else
+static inline void mls_export_netlbl_lvl(struct context *context,
+ struct netlbl_lsm_secattr *secattr)
+{
+ return;
+}
+static inline void mls_import_netlbl_lvl(struct context *context,
+ struct netlbl_lsm_secattr *secattr)
+{
+ return;
+}
+static inline int mls_export_netlbl_cat(struct context *context,
+ struct netlbl_lsm_secattr *secattr)
+{
+ return -ENOMEM;
+}
+static inline int mls_import_netlbl_cat(struct context *context,
+ struct netlbl_lsm_secattr *secattr)
+{
+ return -ENOMEM;
+}
+#endif
#endif /* _SS_MLS_H */
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index b43dd803fd5..bdb7070dd3d 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -55,6 +55,7 @@
#include "objsec.h"
#include "selinux_netlabel.h"
#include "xfrm.h"
+#include "ebitmap.h"
extern void selnl_notify_policyload(u32 seqno);
unsigned int policydb_loaded_version;
@@ -2384,13 +2385,10 @@ static int selinux_netlbl_secattr_to_sid(struct sk_buff *skb,
ctx_new.user = ctx->user;
ctx_new.role = ctx->role;
ctx_new.type = ctx->type;
- mls_import_lvl(&ctx_new, secattr->mls_lvl, secattr->mls_lvl);
+ mls_import_netlbl_lvl(&ctx_new, secattr);
if (secattr->flags & NETLBL_SECATTR_MLS_CAT) {
- if (mls_import_cat(&ctx_new,
- secattr->mls_cat,
- secattr->mls_cat_len,
- NULL,
- 0) != 0)
+ if (ebitmap_netlbl_import(&ctx_new.range.level[0].cat,
+ secattr->mls_cat) != 0)
goto netlbl_secattr_to_sid_return;
ctx_new.range.level[1].cat.highbit =
ctx_new.range.level[0].cat.highbit;
@@ -2486,19 +2484,12 @@ 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);
- rc = mls_export_cat(ctx,
- &secattr.mls_cat,
- &secattr.mls_cat_len,
- NULL,
- NULL);
+ secattr.flags |= NETLBL_SECATTR_DOMAIN;
+ mls_export_netlbl_lvl(ctx, &secattr);
+ rc = mls_export_netlbl_cat(ctx, &secattr);
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) {
spin_lock(&sksec->nlbl_lock);