2003-08-14 19:30:00

by Stephen Smalley

[permalink] [raw]
Subject: [PATCH] SELinux inode security init

This patch against 2.6.0-test3-bk reworks the SELinux module code that
handles inodes initialized before the policy is initially loaded to also
cover the case where a pseudo filesystem such as selinuxfs or nfsd
directly populate themselves. The list of inode security structures
is split into per-superblock lists associated with each superblock
security structure, and the initialization is performed by superblock_doinit.

security/selinux/hooks.c | 62 +++++++++++++++++++-------------------
security/selinux/include/objsec.h | 2 +
2 files changed, 34 insertions(+), 30 deletions(-)

Index: linux-2.6/security/selinux/hooks.c
diff -u linux-2.6/security/selinux/hooks.c:1.67 linux-2.6/security/selinux/hooks.c:1.68
--- linux-2.6/security/selinux/hooks.c:1.67 Tue Aug 12 14:29:53 2003
+++ linux-2.6/security/selinux/hooks.c Wed Aug 13 14:12:19 2003
@@ -84,9 +84,6 @@

/* Lists of inode and superblock security structures initialized
before the policy was loaded. */
-static LIST_HEAD(inode_security_head);
-static spinlock_t inode_security_lock = SPIN_LOCK_UNLOCKED;
-
static LIST_HEAD(superblock_security_head);
static spinlock_t sb_security_lock = SPIN_LOCK_UNLOCKED;

@@ -148,14 +145,15 @@
static void inode_free_security(struct inode *inode)
{
struct inode_security_struct *isec = inode->i_security;
+ struct superblock_security_struct *sbsec = inode->i_sb->s_security;

if (!isec || isec->magic != SELINUX_MAGIC)
return;

- spin_lock(&inode_security_lock);
+ spin_lock(&sbsec->isec_lock);
if (!list_empty(&isec->list))
list_del_init(&isec->list);
- spin_unlock(&inode_security_lock);
+ spin_unlock(&sbsec->isec_lock);

inode->i_security = NULL;
kfree(isec);
@@ -207,6 +205,8 @@
memset(sbsec, 0, sizeof(struct superblock_security_struct));
init_MUTEX(&sbsec->sem);
INIT_LIST_HEAD(&sbsec->list);
+ INIT_LIST_HEAD(&sbsec->isec_head);
+ spin_lock_init(&sbsec->isec_lock);
sbsec->magic = SELINUX_MAGIC;
sbsec->sb = sb;
sbsec->sid = SECINITSID_UNLABELED;
@@ -325,6 +325,29 @@

/* Initialize the root inode. */
rc = inode_doinit_with_dentry(sb->s_root->d_inode, sb->s_root);
+
+ /* Initialize any other inodes associated with the superblock, e.g.
+ inodes created prior to initial policy load or inodes created
+ during get_sb by a pseudo filesystem that directly
+ populates itself. */
+ spin_lock(&sbsec->isec_lock);
+next_inode:
+ if (!list_empty(&sbsec->isec_head)) {
+ struct inode_security_struct *isec =
+ list_entry(sbsec->isec_head.next,
+ struct inode_security_struct, list);
+ struct inode *inode = isec->inode;
+ spin_unlock(&sbsec->isec_lock);
+ inode = igrab(inode);
+ if (inode) {
+ inode_doinit(inode);
+ iput(inode);
+ }
+ spin_lock(&sbsec->isec_lock);
+ list_del_init(&isec->list);
+ goto next_inode;
+ }
+ spin_unlock(&sbsec->isec_lock);
out:
up(&sbsec->sem);
return rc;
@@ -447,14 +470,14 @@
goto out;

sbsec = inode->i_sb->s_security;
- if (!sbsec || !sbsec->initialized) {
+ if (!sbsec->initialized) {
/* Defer initialization until selinux_complete_init,
after the initial policy is loaded and the security
server is ready to handle calls. */
- spin_lock(&inode_security_lock);
+ spin_lock(&sbsec->isec_lock);
if (list_empty(&isec->list))
- list_add(&isec->list, &inode_security_head);
- spin_unlock(&inode_security_lock);
+ list_add(&isec->list, &sbsec->isec_head);
+ spin_unlock(&sbsec->isec_lock);
goto out;
}

@@ -3382,27 +3405,6 @@
goto next_sb;
}
spin_unlock(&sb_security_lock);
-
- /* Set up any inodes initialized prior to the policy load. */
- printk(KERN_INFO "SELinux: Setting up existing inodes.\n");
- spin_lock(&inode_security_lock);
-next_inode:
- if (!list_empty(&inode_security_head)) {
- struct inode_security_struct *isec =
- list_entry(inode_security_head.next,
- struct inode_security_struct, list);
- struct inode *inode = isec->inode;
- spin_unlock(&inode_security_lock);
- inode = igrab(inode);
- if (inode) {
- inode_doinit(inode);
- iput(inode);
- }
- spin_lock(&inode_security_lock);
- list_del_init(&isec->list);
- goto next_inode;
- }
- spin_unlock(&inode_security_lock);
}

/* SELinux requires early initialization in order to label
Index: linux-2.6/security/selinux/include/objsec.h
diff -u linux-2.6/security/selinux/include/objsec.h:1.1.1.1 linux-2.6/security/selinux/include/objsec.h:1.10
--- linux-2.6/security/selinux/include/objsec.h:1.1.1.1 Tue Aug 12 09:05:09 2003
+++ linux-2.6/security/selinux/include/objsec.h Wed Aug 13 14:12:23 2003
@@ -66,6 +66,8 @@
unsigned char initialized; /* initialization flag */
unsigned char proc; /* proc fs */
struct semaphore sem;
+ struct list_head isec_head;
+ spinlock_t isec_lock;
};

struct msg_security_struct {


--
Stephen Smalley <[email protected]>
National Security Agency