summaryrefslogtreecommitdiff
path: root/security/selinux
diff options
context:
space:
mode:
Diffstat (limited to 'security/selinux')
-rw-r--r--security/selinux/hooks.c14
-rw-r--r--security/selinux/include/netif.h2
-rw-r--r--security/selinux/include/netnode.h2
-rw-r--r--security/selinux/include/netport.h2
-rw-r--r--security/selinux/include/security.h3
-rw-r--r--security/selinux/netif.c15
-rw-r--r--security/selinux/netnode.c15
-rw-r--r--security/selinux/netport.c15
-rw-r--r--security/selinux/ss/conditional.c11
-rw-r--r--security/selinux/ss/ebitmap.c133
-rw-r--r--security/selinux/ss/ebitmap.h8
-rw-r--r--security/selinux/ss/policydb.c141
-rw-r--r--security/selinux/ss/services.c41
13 files changed, 157 insertions, 245 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 83d06db34d03..b0e940497e23 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -161,6 +161,17 @@ static int selinux_peerlbl_enabled(void)
return (selinux_policycap_alwaysnetwork || netlbl_enabled() || selinux_xfrm_enabled());
}
+static int selinux_netcache_avc_callback(u32 event)
+{
+ if (event == AVC_CALLBACK_RESET) {
+ sel_netif_flush();
+ sel_netnode_flush();
+ sel_netport_flush();
+ synchronize_net();
+ }
+ return 0;
+}
+
/*
* initialise the security for the init task
*/
@@ -5993,6 +6004,9 @@ static __init int selinux_init(void)
if (register_security(&selinux_ops))
panic("SELinux: Unable to register with kernel.\n");
+ if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET))
+ panic("SELinux: Unable to register AVC netcache callback\n");
+
if (selinux_enforcing)
printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n");
else
diff --git a/security/selinux/include/netif.h b/security/selinux/include/netif.h
index 43d507242b42..57c6eae81eac 100644
--- a/security/selinux/include/netif.h
+++ b/security/selinux/include/netif.h
@@ -17,6 +17,8 @@
#ifndef _SELINUX_NETIF_H_
#define _SELINUX_NETIF_H_
+void sel_netif_flush(void);
+
int sel_netif_sid(int ifindex, u32 *sid);
#endif /* _SELINUX_NETIF_H_ */
diff --git a/security/selinux/include/netnode.h b/security/selinux/include/netnode.h
index df7a5ed6c694..937668dd3024 100644
--- a/security/selinux/include/netnode.h
+++ b/security/selinux/include/netnode.h
@@ -27,6 +27,8 @@
#ifndef _SELINUX_NETNODE_H
#define _SELINUX_NETNODE_H
+void sel_netnode_flush(void);
+
int sel_netnode_sid(void *addr, u16 family, u32 *sid);
#endif
diff --git a/security/selinux/include/netport.h b/security/selinux/include/netport.h
index 4d965b83d735..d1ce896b2cb0 100644
--- a/security/selinux/include/netport.h
+++ b/security/selinux/include/netport.h
@@ -26,6 +26,8 @@
#ifndef _SELINUX_NETPORT_H
#define _SELINUX_NETPORT_H
+void sel_netport_flush(void);
+
int sel_netport_sid(u8 protocol, u16 pnum, u32 *sid);
#endif
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index ce7852cf526b..d1e0b239b602 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -8,6 +8,7 @@
#ifndef _SELINUX_SECURITY_H_
#define _SELINUX_SECURITY_H_
+#include <linux/compiler.h>
#include <linux/dcache.h>
#include <linux/magic.h>
#include <linux/types.h>
@@ -220,7 +221,7 @@ struct selinux_kernel_status {
/*
* The version > 0 supports above members.
*/
-} __attribute__((packed));
+} __packed;
extern void selinux_status_update_setenforce(int enforcing);
extern void selinux_status_update_policyload(int seqno);
diff --git a/security/selinux/netif.c b/security/selinux/netif.c
index 694e9e43855f..3c3de4ca0ebc 100644
--- a/security/selinux/netif.c
+++ b/security/selinux/netif.c
@@ -240,7 +240,7 @@ static void sel_netif_kill(int ifindex)
* Remove all entries from the network interface table.
*
*/
-static void sel_netif_flush(void)
+void sel_netif_flush(void)
{
int idx;
struct sel_netif *netif;
@@ -252,15 +252,6 @@ static void sel_netif_flush(void)
spin_unlock_bh(&sel_netif_lock);
}
-static int sel_netif_avc_callback(u32 event)
-{
- if (event == AVC_CALLBACK_RESET) {
- sel_netif_flush();
- synchronize_net();
- }
- return 0;
-}
-
static int sel_netif_netdev_notifier_handler(struct notifier_block *this,
unsigned long event, void *ptr)
{
@@ -291,10 +282,6 @@ static __init int sel_netif_init(void)
register_netdevice_notifier(&sel_netif_netdev_notifier);
- err = avc_add_callback(sel_netif_avc_callback, AVC_CALLBACK_RESET);
- if (err)
- panic("avc_add_callback() failed, error %d\n", err);
-
return err;
}
diff --git a/security/selinux/netnode.c b/security/selinux/netnode.c
index 03a72c32afd7..ddf315260839 100644
--- a/security/selinux/netnode.c
+++ b/security/selinux/netnode.c
@@ -283,7 +283,7 @@ int sel_netnode_sid(void *addr, u16 family, u32 *sid)
* Remove all entries from the network address table.
*
*/
-static void sel_netnode_flush(void)
+void sel_netnode_flush(void)
{
unsigned int idx;
struct sel_netnode *node, *node_tmp;
@@ -300,15 +300,6 @@ static void sel_netnode_flush(void)
spin_unlock_bh(&sel_netnode_lock);
}
-static int sel_netnode_avc_callback(u32 event)
-{
- if (event == AVC_CALLBACK_RESET) {
- sel_netnode_flush();
- synchronize_net();
- }
- return 0;
-}
-
static __init int sel_netnode_init(void)
{
int iter;
@@ -322,10 +313,6 @@ static __init int sel_netnode_init(void)
sel_netnode_hash[iter].size = 0;
}
- ret = avc_add_callback(sel_netnode_avc_callback, AVC_CALLBACK_RESET);
- if (ret != 0)
- panic("avc_add_callback() failed, error %d\n", ret);
-
return ret;
}
diff --git a/security/selinux/netport.c b/security/selinux/netport.c
index d35379781c2c..73ac6784d091 100644
--- a/security/selinux/netport.c
+++ b/security/selinux/netport.c
@@ -217,7 +217,7 @@ int sel_netport_sid(u8 protocol, u16 pnum, u32 *sid)
* Remove all entries from the network address table.
*
*/
-static void sel_netport_flush(void)
+void sel_netport_flush(void)
{
unsigned int idx;
struct sel_netport *port, *port_tmp;
@@ -234,15 +234,6 @@ static void sel_netport_flush(void)
spin_unlock_bh(&sel_netport_lock);
}
-static int sel_netport_avc_callback(u32 event)
-{
- if (event == AVC_CALLBACK_RESET) {
- sel_netport_flush();
- synchronize_net();
- }
- return 0;
-}
-
static __init int sel_netport_init(void)
{
int iter;
@@ -256,10 +247,6 @@ static __init int sel_netport_init(void)
sel_netport_hash[iter].size = 0;
}
- ret = avc_add_callback(sel_netport_avc_callback, AVC_CALLBACK_RESET);
- if (ret != 0)
- panic("avc_add_callback() failed, error %d\n", ret);
-
return ret;
}
diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c
index 377d148e7157..62c6773be0b7 100644
--- a/security/selinux/ss/conditional.c
+++ b/security/selinux/ss/conditional.c
@@ -402,19 +402,14 @@ static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp)
int rc;
struct cond_expr *expr = NULL, *last = NULL;
- rc = next_entry(buf, fp, sizeof(u32));
+ rc = next_entry(buf, fp, sizeof(u32) * 2);
if (rc)
- return rc;
+ goto err;
node->cur_state = le32_to_cpu(buf[0]);
- len = 0;
- rc = next_entry(buf, fp, sizeof(u32));
- if (rc)
- return rc;
-
/* expr */
- len = le32_to_cpu(buf[0]);
+ len = le32_to_cpu(buf[1]);
for (i = 0; i < len; i++) {
rc = next_entry(buf, fp, sizeof(u32) * 2);
diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c
index 820313a04d49..afe6a269ec17 100644
--- a/security/selinux/ss/ebitmap.c
+++ b/security/selinux/ss/ebitmap.c
@@ -86,51 +86,36 @@ int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src)
*
*/
int ebitmap_netlbl_export(struct ebitmap *ebmap,
- struct netlbl_lsm_secattr_catmap **catmap)
+ struct netlbl_lsm_catmap **catmap)
{
struct ebitmap_node *e_iter = ebmap->node;
- struct netlbl_lsm_secattr_catmap *c_iter;
- u32 cmap_idx, cmap_sft;
- int i;
-
- /* NetLabel's NETLBL_CATMAP_MAPTYPE is defined as an array of u64,
- * however, it is not always compatible with an array of unsigned long
- * in ebitmap_node.
- * In addition, you should pay attention the following implementation
- * assumes unsigned long has a width equal with or less than 64-bit.
- */
+ unsigned long e_map;
+ u32 offset;
+ unsigned int iter;
+ int rc;
if (e_iter == NULL) {
*catmap = NULL;
return 0;
}
- 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);
+ if (*catmap != NULL)
+ netlbl_catmap_free(*catmap);
+ *catmap = NULL;
while (e_iter) {
- for (i = 0; i < EBITMAP_UNIT_NUMS; i++) {
- unsigned int delta, e_startbit, c_endbit;
-
- e_startbit = e_iter->startbit + i * EBITMAP_UNIT_SIZE;
- c_endbit = c_iter->startbit + NETLBL_CATMAP_SIZE;
- if (e_startbit >= c_endbit) {
- c_iter->next
- = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
- if (c_iter->next == NULL)
+ offset = e_iter->startbit;
+ for (iter = 0; iter < EBITMAP_UNIT_NUMS; iter++) {
+ e_map = e_iter->maps[iter];
+ if (e_map != 0) {
+ rc = netlbl_catmap_setlong(catmap,
+ offset,
+ e_map,
+ GFP_ATOMIC);
+ if (rc != 0)
goto netlbl_export_failure;
- c_iter = c_iter->next;
- c_iter->startbit
- = e_startbit & ~(NETLBL_CATMAP_SIZE - 1);
}
- delta = e_startbit - c_iter->startbit;
- cmap_idx = delta / NETLBL_CATMAP_MAPSIZE;
- cmap_sft = delta % NETLBL_CATMAP_MAPSIZE;
- c_iter->bitmap[cmap_idx]
- |= e_iter->maps[i] << cmap_sft;
+ offset += EBITMAP_UNIT_SIZE;
}
e_iter = e_iter->next;
}
@@ -138,7 +123,7 @@ int ebitmap_netlbl_export(struct ebitmap *ebmap,
return 0;
netlbl_export_failure:
- netlbl_secattr_catmap_free(*catmap);
+ netlbl_catmap_free(*catmap);
return -ENOMEM;
}
@@ -153,58 +138,44 @@ netlbl_export_failure:
*
*/
int ebitmap_netlbl_import(struct ebitmap *ebmap,
- struct netlbl_lsm_secattr_catmap *catmap)
+ struct netlbl_lsm_catmap *catmap)
{
+ int rc;
struct ebitmap_node *e_iter = NULL;
- struct ebitmap_node *emap_prev = NULL;
- struct netlbl_lsm_secattr_catmap *c_iter = catmap;
- u32 c_idx, c_pos, e_idx, e_sft;
-
- /* NetLabel's NETLBL_CATMAP_MAPTYPE is defined as an array of u64,
- * however, it is not always compatible with an array of unsigned long
- * in ebitmap_node.
- * In addition, you should pay attention the following implementation
- * assumes unsigned long has a width equal with or less than 64-bit.
- */
-
- do {
- for (c_idx = 0; c_idx < NETLBL_CATMAP_MAPCNT; c_idx++) {
- unsigned int delta;
- u64 map = c_iter->bitmap[c_idx];
-
- if (!map)
- continue;
+ struct ebitmap_node *e_prev = NULL;
+ u32 offset = 0, idx;
+ unsigned long bitmap;
+
+ for (;;) {
+ rc = netlbl_catmap_getlong(catmap, &offset, &bitmap);
+ if (rc < 0)
+ goto netlbl_import_failure;
+ if (offset == (u32)-1)
+ return 0;
- c_pos = c_iter->startbit
- + c_idx * NETLBL_CATMAP_MAPSIZE;
- if (!e_iter
- || c_pos >= e_iter->startbit + EBITMAP_SIZE) {
- e_iter = kzalloc(sizeof(*e_iter), GFP_ATOMIC);
- if (!e_iter)
- goto netlbl_import_failure;
- e_iter->startbit
- = c_pos - (c_pos % EBITMAP_SIZE);
- if (emap_prev == NULL)
- ebmap->node = e_iter;
- else
- emap_prev->next = e_iter;
- emap_prev = e_iter;
- }
- delta = c_pos - e_iter->startbit;
- e_idx = delta / EBITMAP_UNIT_SIZE;
- e_sft = delta % EBITMAP_UNIT_SIZE;
- while (map) {
- e_iter->maps[e_idx++] |= map & (-1UL);
- map = EBITMAP_SHIFT_UNIT_SIZE(map);
- }
+ if (e_iter == NULL ||
+ offset >= e_iter->startbit + EBITMAP_SIZE) {
+ e_prev = e_iter;
+ e_iter = kzalloc(sizeof(*e_iter), GFP_ATOMIC);
+ if (e_iter == NULL)
+ goto netlbl_import_failure;
+ e_iter->startbit = offset & ~(EBITMAP_SIZE - 1);
+ if (e_prev == NULL)
+ ebmap->node = e_iter;
+ else
+ e_prev->next = e_iter;
+ ebmap->highbit = e_iter->startbit + EBITMAP_SIZE;
}
- c_iter = c_iter->next;
- } while (c_iter);
- if (e_iter != NULL)
- ebmap->highbit = e_iter->startbit + EBITMAP_SIZE;
- else
- ebitmap_destroy(ebmap);
+ /* offset will always be aligned to an unsigned long */
+ idx = EBITMAP_NODE_INDEX(e_iter, offset);
+ e_iter->maps[idx] = bitmap;
+
+ /* next */
+ offset += EBITMAP_UNIT_SIZE;
+ }
+
+ /* NOTE: we should never reach this return */
return 0;
netlbl_import_failure:
diff --git a/security/selinux/ss/ebitmap.h b/security/selinux/ss/ebitmap.h
index 712c8a7b8e8b..9637b8c71085 100644
--- a/security/selinux/ss/ebitmap.h
+++ b/security/selinux/ss/ebitmap.h
@@ -132,17 +132,17 @@ int ebitmap_write(struct ebitmap *e, void *fp);
#ifdef CONFIG_NETLABEL
int ebitmap_netlbl_export(struct ebitmap *ebmap,
- struct netlbl_lsm_secattr_catmap **catmap);
+ struct netlbl_lsm_catmap **catmap);
int ebitmap_netlbl_import(struct ebitmap *ebmap,
- struct netlbl_lsm_secattr_catmap *catmap);
+ struct netlbl_lsm_catmap *catmap);
#else
static inline int ebitmap_netlbl_export(struct ebitmap *ebmap,
- struct netlbl_lsm_secattr_catmap **catmap)
+ struct netlbl_lsm_catmap **catmap)
{
return -ENOMEM;
}
static inline int ebitmap_netlbl_import(struct ebitmap *ebmap,
- struct netlbl_lsm_secattr_catmap *catmap)
+ struct netlbl_lsm_catmap *catmap)
{
return -ENOMEM;
}
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index 9c5cdc2caaef..bc2a586f095c 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -1080,6 +1080,26 @@ out:
* binary representation file.
*/
+static int str_read(char **strp, gfp_t flags, void *fp, u32 len)
+{
+ int rc;
+ char *str;
+
+ str = kmalloc(len + 1, flags);
+ if (!str)
+ return -ENOMEM;
+
+ /* it's expected the caller should free the str */
+ *strp = str;
+
+ rc = next_entry(str, fp, len);
+ if (rc)
+ return rc;
+
+ str[len] = '\0';
+ return 0;
+}
+
static int perm_read(struct policydb *p, struct hashtab *h, void *fp)
{
char *key = NULL;
@@ -1100,15 +1120,9 @@ static int perm_read(struct policydb *p, struct hashtab *h, void *fp)
len = le32_to_cpu(buf[0]);
perdatum->value = le32_to_cpu(buf[1]);
- rc = -ENOMEM;
- key = kmalloc(len + 1, GFP_KERNEL);
- if (!key)
- goto bad;
-
- rc = next_entry(key, fp, len);
+ rc = str_read(&key, GFP_KERNEL, fp, len);
if (rc)
goto bad;
- key[len] = '\0';
rc = hashtab_insert(h, key, perdatum);
if (rc)
@@ -1146,15 +1160,9 @@ static int common_read(struct policydb *p, struct hashtab *h, void *fp)
comdatum->permissions.nprim = le32_to_cpu(buf[2]);
nel = le32_to_cpu(buf[3]);
- rc = -ENOMEM;
- key = kmalloc(len + 1, GFP_KERNEL);
- if (!key)
- goto bad;
-
- rc = next_entry(key, fp, len);
+ rc = str_read(&key, GFP_KERNEL, fp, len);
if (rc)
goto bad;
- key[len] = '\0';
for (i = 0; i < nel; i++) {
rc = perm_read(p, comdatum->permissions.table, fp);
@@ -1321,25 +1329,14 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp)
ncons = le32_to_cpu(buf[5]);
- rc = -ENOMEM;
- key = kmalloc(len + 1, GFP_KERNEL);
- if (!key)
- goto bad;
-
- rc = next_entry(key, fp, len);
+ rc = str_read(&key, GFP_KERNEL, fp, len);
if (rc)
goto bad;
- key[len] = '\0';
if (len2) {
- rc = -ENOMEM;
- cladatum->comkey = kmalloc(len2 + 1, GFP_KERNEL);
- if (!cladatum->comkey)
- goto bad;
- rc = next_entry(cladatum->comkey, fp, len2);
+ rc = str_read(&cladatum->comkey, GFP_KERNEL, fp, len2);
if (rc)
goto bad;
- cladatum->comkey[len2] = '\0';
rc = -EINVAL;
cladatum->comdatum = hashtab_search(p->p_commons.table, cladatum->comkey);
@@ -1422,15 +1419,9 @@ static int role_read(struct policydb *p, struct hashtab *h, void *fp)
if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
role->bounds = le32_to_cpu(buf[2]);
- rc = -ENOMEM;
- key = kmalloc(len + 1, GFP_KERNEL);
- if (!key)
- goto bad;
-
- rc = next_entry(key, fp, len);
+ rc = str_read(&key, GFP_KERNEL, fp, len);
if (rc)
goto bad;
- key[len] = '\0';
rc = ebitmap_read(&role->dominates, fp);
if (rc)
@@ -1495,14 +1486,9 @@ static int type_read(struct policydb *p, struct hashtab *h, void *fp)
typdatum->primary = le32_to_cpu(buf[2]);
}
- rc = -ENOMEM;
- key = kmalloc(len + 1, GFP_KERNEL);
- if (!key)
- goto bad;
- rc = next_entry(key, fp, len);
+ rc = str_read(&key, GFP_KERNEL, fp, len);
if (rc)
goto bad;
- key[len] = '\0';
rc = hashtab_insert(h, key, typdatum);
if (rc)
@@ -1565,14 +1551,9 @@ static int user_read(struct policydb *p, struct hashtab *h, void *fp)
if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
usrdatum->bounds = le32_to_cpu(buf[2]);
- rc = -ENOMEM;
- key = kmalloc(len + 1, GFP_KERNEL);
- if (!key)
- goto bad;
- rc = next_entry(key, fp, len);
+ rc = str_read(&key, GFP_KERNEL, fp, len);
if (rc)
goto bad;
- key[len] = '\0';
rc = ebitmap_read(&usrdatum->roles, fp);
if (rc)
@@ -1616,14 +1597,9 @@ static int sens_read(struct policydb *p, struct hashtab *h, void *fp)
len = le32_to_cpu(buf[0]);
levdatum->isalias = le32_to_cpu(buf[1]);
- rc = -ENOMEM;
- key = kmalloc(len + 1, GFP_ATOMIC);
- if (!key)
- goto bad;
- rc = next_entry(key, fp, len);
+ rc = str_read(&key, GFP_ATOMIC, fp, len);
if (rc)
goto bad;
- key[len] = '\0';
rc = -ENOMEM;
levdatum->level = kmalloc(sizeof(struct mls_level), GFP_ATOMIC);
@@ -1664,14 +1640,9 @@ static int cat_read(struct policydb *p, struct hashtab *h, void *fp)
catdatum->value = le32_to_cpu(buf[1]);
catdatum->isalias = le32_to_cpu(buf[2]);
- rc = -ENOMEM;
- key = kmalloc(len + 1, GFP_ATOMIC);
- if (!key)
- goto bad;
- rc = next_entry(key, fp, len);
+ rc = str_read(&key, GFP_ATOMIC, fp, len);
if (rc)
goto bad;
- key[len] = '\0';
rc = hashtab_insert(h, key, catdatum);
if (rc)
@@ -1968,18 +1939,12 @@ static int filename_trans_read(struct policydb *p, void *fp)
goto out;
len = le32_to_cpu(buf[0]);
- rc = -ENOMEM;
- name = kmalloc(len + 1, GFP_KERNEL);
- if (!name)
- goto out;
-
- ft->name = name;
-
/* path component string */
- rc = next_entry(name, fp, len);
+ rc = str_read(&name, GFP_KERNEL, fp, len);
if (rc)
goto out;
- name[len] = 0;
+
+ ft->name = name;
rc = next_entry(buf, fp, sizeof(u32) * 4);
if (rc)
@@ -2045,17 +2010,10 @@ static int genfs_read(struct policydb *p, void *fp)
if (!newgenfs)
goto out;
- rc = -ENOMEM;
- newgenfs->fstype = kmalloc(len + 1, GFP_KERNEL);
- if (!newgenfs->fstype)
- goto out;
-
- rc = next_entry(newgenfs->fstype, fp, len);
+ rc = str_read(&newgenfs->fstype, GFP_KERNEL, fp, len);
if (rc)
goto out;
- newgenfs->fstype[len] = 0;
-
for (genfs_p = NULL, genfs = p->genfs; genfs;
genfs_p = genfs, genfs = genfs->next) {
rc = -EINVAL;
@@ -2091,15 +2049,9 @@ static int genfs_read(struct policydb *p, void *fp)
if (!newc)
goto out;
- rc = -ENOMEM;
- newc->u.name = kmalloc(len + 1, GFP_KERNEL);
- if (!newc->u.name)
- goto out;
-
- rc = next_entry(newc->u.name, fp, len);
+ rc = str_read(&newc->u.name, GFP_KERNEL, fp, len);
if (rc)
goto out;
- newc->u.name[len] = 0;
rc = next_entry(buf, fp, sizeof(u32));
if (rc)
@@ -2189,16 +2141,10 @@ static int ocontext_read(struct policydb *p, struct policydb_compat_info *info,
goto out;
len = le32_to_cpu(buf[0]);
- rc = -ENOMEM;
- c->u.name = kmalloc(len + 1, GFP_KERNEL);
- if (!c->u.name)
- goto out;
-
- rc = next_entry(c->u.name, fp, len);
+ rc = str_read(&c->u.name, GFP_KERNEL, fp, len);
if (rc)
goto out;
- c->u.name[len] = 0;
rc = context_read_and_validate(&c->context[0], p, fp);
if (rc)
goto out;
@@ -2240,16 +2186,11 @@ static int ocontext_read(struct policydb *p, struct policydb_compat_info *info,
if (c->v.behavior > SECURITY_FS_USE_MAX)
goto out;
- rc = -ENOMEM;
len = le32_to_cpu(buf[1]);
- c->u.name = kmalloc(len + 1, GFP_KERNEL);
- if (!c->u.name)
- goto out;
-
- rc = next_entry(c->u.name, fp, len);
+ rc = str_read(&c->u.name, GFP_KERNEL, fp, len);
if (rc)
goto out;
- c->u.name[len] = 0;
+
rc = context_read_and_validate(&c->context[0], p, fp);
if (rc)
goto out;
@@ -2608,7 +2549,7 @@ static int mls_write_range_helper(struct mls_range *r, void *fp)
if (!eq)
buf[2] = cpu_to_le32(r->level[1].sens);
- BUG_ON(items > (sizeof(buf)/sizeof(buf[0])));
+ BUG_ON(items > ARRAY_SIZE(buf));
rc = put_entry(buf, sizeof(u32), items, fp);
if (rc)
@@ -2990,7 +2931,7 @@ static int role_write(void *vkey, void *datum, void *ptr)
if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
buf[items++] = cpu_to_le32(role->bounds);
- BUG_ON(items > (sizeof(buf)/sizeof(buf[0])));
+ BUG_ON(items > ARRAY_SIZE(buf));
rc = put_entry(buf, sizeof(u32), items, fp);
if (rc)
@@ -3040,7 +2981,7 @@ static int type_write(void *vkey, void *datum, void *ptr)
} else {
buf[items++] = cpu_to_le32(typdatum->primary);
}
- BUG_ON(items > (sizeof(buf) / sizeof(buf[0])));
+ BUG_ON(items > ARRAY_SIZE(buf));
rc = put_entry(buf, sizeof(u32), items, fp);
if (rc)
return rc;
@@ -3069,7 +3010,7 @@ static int user_write(void *vkey, void *datum, void *ptr)
buf[items++] = cpu_to_le32(usrdatum->value);
if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
buf[items++] = cpu_to_le32(usrdatum->bounds);
- BUG_ON(items > (sizeof(buf) / sizeof(buf[0])));
+ BUG_ON(items > ARRAY_SIZE(buf));
rc = put_entry(buf, sizeof(u32), items, fp);
if (rc)
return rc;
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 4bca49414a40..2aa9d172dc7e 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -2277,7 +2277,7 @@ out:
}
/**
- * security_genfs_sid - Obtain a SID for a file in a filesystem
+ * __security_genfs_sid - Helper to obtain a SID for a file in a filesystem
* @fstype: filesystem type
* @path: path from root of mount
* @sclass: file security class
@@ -2286,11 +2286,13 @@ out:
* Obtain a SID to use for a file in a filesystem that
* cannot support xattr or use a fixed labeling behavior like
* transition SIDs or task SIDs.
+ *
+ * The caller must acquire the policy_rwlock before calling this function.
*/
-int security_genfs_sid(const char *fstype,
- char *path,
- u16 orig_sclass,
- u32 *sid)
+static inline int __security_genfs_sid(const char *fstype,
+ char *path,
+ u16 orig_sclass,
+ u32 *sid)
{
int len;
u16 sclass;
@@ -2301,8 +2303,6 @@ int security_genfs_sid(const char *fstype,
while (path[0] == '/' && path[1] == '/')
path++;
- read_lock(&policy_rwlock);
-
sclass = unmap_class(orig_sclass);
*sid = SECINITSID_UNLABELED;
@@ -2336,11 +2336,33 @@ int security_genfs_sid(const char *fstype,
*sid = c->sid[0];
rc = 0;
out:
- read_unlock(&policy_rwlock);
return rc;
}
/**
+ * security_genfs_sid - Obtain a SID for a file in a filesystem
+ * @fstype: filesystem type
+ * @path: path from root of mount
+ * @sclass: file security class
+ * @sid: SID for path
+ *
+ * Acquire policy_rwlock before calling __security_genfs_sid() and release
+ * it afterward.
+ */
+int security_genfs_sid(const char *fstype,
+ char *path,
+ u16 orig_sclass,
+ u32 *sid)
+{
+ int retval;
+
+ read_lock(&policy_rwlock);
+ retval = __security_genfs_sid(fstype, path, orig_sclass, sid);
+ read_unlock(&policy_rwlock);
+ return retval;
+}
+
+/**
* security_fs_use - Determine how to handle labeling for a filesystem.
* @sb: superblock in question
*/
@@ -2370,7 +2392,8 @@ int security_fs_use(struct super_block *sb)
}
sbsec->sid = c->sid[0];
} else {
- rc = security_genfs_sid(fstype, "/", SECCLASS_DIR, &sbsec->sid);
+ rc = __security_genfs_sid(fstype, "/", SECCLASS_DIR,
+ &sbsec->sid);
if (rc) {
sbsec->behavior = SECURITY_FS_USE_NONE;
rc = 0;