@@ -106,6 +106,9 @@
/* SECMARK reference count */
static atomic_t selinux_secmark_refcount = ATOMIC_INIT(0);
+/* Sequential namespace id */
+static atomic64_t selinux_namespace_id = ATOMIC_INIT(0);
+
#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
static int selinux_enforcing_boot __initdata;
@@ -812,6 +815,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
goto out;
root_isec->sid = rootcontext_sid;
+ root_isec->namespace_id = current_selinux_state->id;
root_isec->initialized = LABEL_INITIALIZED;
}
@@ -1556,6 +1560,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
isec->initialized = LABEL_INITIALIZED;
isec->sid = sid;
+ isec->namespace_id = current_selinux_state->id;
}
out_unlock:
@@ -2588,7 +2593,7 @@ sbsec_alloc(struct superblock_security_head *sbsech)
sbsec->sid = SECINITSID_UNLABELED;
sbsec->def_sid = SECINITSID_FILE;
sbsec->mntpoint_sid = SECINITSID_UNLABELED;
- sbsec->state = get_selinux_state(current_selinux_state);
+ sbsec->namespace_id = current_selinux_state->id;
return sbsec;
}
@@ -2599,12 +2604,12 @@ find_sbsec(struct superblock_security_head *sbsech)
struct superblock_security_struct *cur, *new;
cur = container_of(sbsech->head.next, struct superblock_security_struct, sbsec_list);
- if (cur->state == current_selinux_state)
+ if (cur->namespace_id == current_selinux_state->id)
return cur;
spin_lock(&sbsech->lock);
list_for_each_entry(cur, &sbsech->head, sbsec_list) {
- if (cur->state == current_selinux_state)
+ if (cur->namespace_id == current_selinux_state->id)
goto unlock;
}
spin_unlock(&sbsech->lock);
@@ -2617,7 +2622,7 @@ find_sbsec(struct superblock_security_head *sbsech)
spin_lock(&sbsech->lock);
list_for_each_entry(cur, &sbsech->head, sbsec_list) {
- if (cur->state == current_selinux_state)
+ if (cur->namespace_id == current_selinux_state->id)
goto unlock;
}
list_add(&new->sbsec_list, &sbsech->head);
@@ -2649,7 +2654,6 @@ static void selinux_sb_free_security(struct super_block *sb)
struct superblock_security_head *sbsech = selinux_head_of_superblock(sb);
list_for_each_entry_safe(entry, tmp, &sbsech->head, sbsec_list) {
- put_selinux_state(entry->state);
kfree(entry);
}
}
@@ -2911,6 +2915,7 @@ static int selinux_inode_alloc_security(struct inode *inode)
isec->sclass = SECCLASS_FILE;
isec->task_sid = sid;
isec->initialized = LABEL_INVALID;
+ isec->namespace_id = current_selinux_state->id;
return 0;
}
@@ -2985,6 +2990,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
struct inode_security_struct *isec = selinux_inode(inode);
isec->sclass = inode_mode_to_security_class(inode->i_mode);
isec->sid = newsid;
+ isec->namespace_id = current_selinux_state->id;
isec->initialized = LABEL_INITIALIZED;
}
@@ -3320,6 +3326,7 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
spin_lock(&isec->lock);
isec->sclass = inode_mode_to_security_class(inode->i_mode);
isec->sid = newsid;
+ isec->namespace_id = current_selinux_state->id;
isec->initialized = LABEL_INITIALIZED;
spin_unlock(&isec->lock);
@@ -3479,6 +3486,7 @@ static int selinux_inode_setsecurity(struct inode *inode, const char *name,
spin_lock(&isec->lock);
isec->sclass = inode_mode_to_security_class(inode->i_mode);
isec->sid = newsid;
+ isec->namespace_id = current_selinux_state->id;
isec->initialized = LABEL_INITIALIZED;
spin_unlock(&isec->lock);
return 0;
@@ -3636,6 +3644,7 @@ static int selinux_file_alloc_security(struct file *file)
fsec->sid = sid;
fsec->fown_sid = sid;
+ fsec->namespace_id = current_selinux_state->id;
return 0;
}
@@ -3950,6 +3959,7 @@ static int selinux_file_open(struct file *file)
*/
fsec->isid = isec->sid;
fsec->pseqno = avc_policy_seqno(current_selinux_state);
+ fsec->namespace_id = current_selinux_state->id;
/*
* Since the inode label or policy seqno may have changed
* between the selinux_inode_permission check and the saving
@@ -4268,6 +4278,7 @@ static void selinux_task_to_inode(struct task_struct *p,
spin_lock(&isec->lock);
isec->sclass = inode_mode_to_security_class(inode->i_mode);
isec->sid = sid;
+ isec->namespace_id = current_selinux_state->id;
isec->initialized = LABEL_INITIALIZED;
spin_unlock(&isec->lock);
}
@@ -4634,6 +4645,7 @@ static int selinux_socket_post_create(struct socket *sock, int family,
isec->sclass = sclass;
isec->sid = sid;
+ isec->namespace_id = current_selinux_state->id;
isec->initialized = LABEL_INITIALIZED;
if (sock->sk) {
@@ -4930,6 +4942,7 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
newisec = inode_security_novalidate(SOCK_INODE(newsock));
newisec->sclass = sclass;
newisec->sid = sid;
+ newisec->namespace_id = current_selinux_state->id;
newisec->initialized = LABEL_INITIALIZED;
return 0;
@@ -7332,6 +7345,11 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
static void selinux_state_free(struct work_struct *work);
+u64 selinux_new_state_id(void)
+{
+ return atomic64_fetch_add(1, &selinux_namespace_id);
+}
+
int selinux_state_create(struct selinux_state *parent, struct selinux_state **state)
{
struct selinux_state *newstate;
@@ -7341,6 +7359,7 @@ int selinux_state_create(struct selinux_state *parent, struct selinux_state **st
if (!newstate)
return -ENOMEM;
+ newstate->id = selinux_new_state_id();
refcount_set(&newstate->count, 1);
INIT_WORK(&newstate->work, selinux_state_free);
@@ -42,6 +42,7 @@ struct inode_security_struct {
u16 sclass; /* security class of this object */
unsigned char initialized; /* initialization flag */
spinlock_t lock;
+ u64 namespace_id; /* pointer to selinux_state */
};
struct file_security_struct {
@@ -49,6 +50,7 @@ struct file_security_struct {
u32 fown_sid; /* SID of file owner (for SIGIO) */
u32 isid; /* SID of inode at the time of file open */
u32 pseqno; /* Policy seqno at the time of file open */
+ u64 namespace_id;
};
struct superblock_security_head {
@@ -66,7 +68,7 @@ struct superblock_security_struct {
struct mutex lock;
struct list_head isec_head;
spinlock_t isec_lock;
- struct selinux_state *state; /* pointer to selinux_state */
+ u64 namespace_id; /* id of selinux_state */
struct list_head sbsec_list;
};
@@ -111,8 +111,10 @@ struct selinux_state {
struct selinux_policy __rcu *policy;
struct mutex policy_mutex;
struct selinux_state *parent;
+ u64 id;
} __randomize_layout;
+u64 selinux_new_state_id(void);
int selinux_state_create(struct selinux_state *parent, struct selinux_state **state);
void __put_selinux_state(struct selinux_state *state);
All the objects which in the original patchset kept a pointer to their namespace now store its identifier. It's needed only to determine whether an object belongs to our (in the current context) namespace or not. The aim of this change is to reduce the height of the Babel tower of pointers. Signed-off-by: Igor Baranov <igor.baranov@huawei.com> --- security/selinux/hooks.c | 29 ++++++++++++++++++++++++----- security/selinux/include/objsec.h | 4 +++- security/selinux/include/security.h | 2 ++ 3 files changed, 29 insertions(+), 6 deletions(-)