Re: [RFC] [PATCH] [5/6] LSM Stacking: SELinux LSM stacking support

From: Serge Hallyn
Date: Thu Nov 04 2004 - 17:25:57 EST


This patch adds stacking support to the SELinux LSM.

Signed-off-by: Serge E. Hallyn <serue@xxxxxxxxxx>

Index: linux-2.6.10-rc1-bk12-stack/security/selinux/hooks.c
===================================================================
--- linux-2.6.10-rc1-bk12-stack.orig/security/selinux/hooks.c 2004-11-02
19:56:04.309432960 -0600
+++ linux-2.6.10-rc1-bk12-stack/security/selinux/hooks.c 2004-11-02
20:08:19.593652768 -0600
@@ -76,6 +76,9 @@
extern int policydb_loaded_version;
extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm);

+int selinux_idx;
+static int secondary;
+
#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
int selinux_enforcing = 0;

@@ -98,15 +101,6 @@
__setup("selinux=", selinux_enabled_setup);
#endif

-/* Original (dummy) security module. */
-static struct security_operations *original_ops = NULL;
-
-/* Minimal support for a secondary security module,
- just to allow the use of the dummy or capability modules.
- The owlsm module can alternatively be used as a secondary
- module as long as CONFIG_OWLSM_FD is not enabled. */
-static struct security_operations *secondary_ops = NULL;
-
/* Lists of inode and superblock security structures initialized
before the policy was loaded. */
static LIST_HEAD(superblock_security_head);
@@ -126,25 +120,25 @@
tsec->magic = SELINUX_MAGIC;
tsec->task = task;
tsec->osid = tsec->sid = tsec->ptrace_sid = SECINITSID_UNLABELED;
- task->security = tsec;
+ task->security[selinux_idx] = tsec;

return 0;
}

static void task_free_security(struct task_struct *task)
{
- struct task_security_struct *tsec = task->security;
+ struct task_security_struct *tsec = task->security[selinux_idx];

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

- task->security = NULL;
+ task->security[selinux_idx] = NULL;
kfree(tsec);
}

static int inode_alloc_security(struct inode *inode)
{
- struct task_security_struct *tsec = current->security;
+ struct task_security_struct *tsec = current->security[selinux_idx];
struct inode_security_struct *isec;

isec = kmalloc(sizeof(struct inode_security_struct), GFP_KERNEL);
@@ -162,15 +156,15 @@
isec->task_sid = tsec->sid;
else
isec->task_sid = SECINITSID_UNLABELED;
- inode->i_security = isec;
+ inode->i_security[selinux_idx] = isec;

return 0;
}

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;
+ struct inode_security_struct *isec = inode->i_security[selinux_idx];
+ struct superblock_security_struct *sbsec =
inode->i_sb->s_security[selinux_idx];

if (!isec || isec->magic != SELINUX_MAGIC)
return;
@@ -180,13 +174,13 @@
list_del_init(&isec->list);
spin_unlock(&sbsec->isec_lock);

- inode->i_security = NULL;
+ inode->i_security[selinux_idx] = NULL;
kfree(isec);
}

static int file_alloc_security(struct file *file)
{
- struct task_security_struct *tsec = current->security;
+ struct task_security_struct *tsec = current->security[selinux_idx];
struct file_security_struct *fsec;

fsec = kmalloc(sizeof(struct file_security_struct), GFP_ATOMIC);
@@ -203,19 +197,19 @@
fsec->sid = SECINITSID_UNLABELED;
fsec->fown_sid = SECINITSID_UNLABELED;
}
- file->f_security = fsec;
+ file->f_security[selinux_idx] = fsec;

return 0;
}

static void file_free_security(struct file *file)
{
- struct file_security_struct *fsec = file->f_security;
+ struct file_security_struct *fsec = file->f_security[selinux_idx];

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

- file->f_security = NULL;
+ file->f_security[selinux_idx] = NULL;
kfree(fsec);
}

@@ -236,14 +230,14 @@
sbsec->sb = sb;
sbsec->sid = SECINITSID_UNLABELED;
sbsec->def_sid = SECINITSID_FILE;
- sb->s_security = sbsec;
+ sb->s_security[selinux_idx] = sbsec;

return 0;
}

static void superblock_free_security(struct super_block *sb)
{
- struct superblock_security_struct *sbsec = sb->s_security;
+ struct superblock_security_struct *sbsec =
sb->s_security[selinux_idx];

if (!sbsec || sbsec->magic != SELINUX_MAGIC)
return;
@@ -253,7 +247,7 @@
list_del_init(&sbsec->list);
spin_unlock(&sb_security_lock);

- sb->s_security = NULL;
+ sb->s_security[selinux_idx] = NULL;
kfree(sbsec);
}

@@ -273,19 +267,19 @@
ssec->magic = SELINUX_MAGIC;
ssec->sk = sk;
ssec->peer_sid = SECINITSID_UNLABELED;
- sk->sk_security = ssec;
+ sk->sk_security[selinux_idx] = ssec;

return 0;
}

static void sk_free_security(struct sock *sk)
{
- struct sk_security_struct *ssec = sk->sk_security;
+ struct sk_security_struct *ssec = sk->sk_security[selinux_idx];

if (sk->sk_family != PF_UNIX || ssec->magic != SELINUX_MAGIC)
return;

- sk->sk_security = NULL;
+ sk->sk_security[selinux_idx] = NULL;
kfree(ssec);
}
#endif /* CONFIG_SECURITY_NETWORK */
@@ -332,8 +326,8 @@
const char *name;
u32 sid;
int alloc = 0, rc = 0, seen = 0;
- struct task_security_struct *tsec = current->security;
- struct superblock_security_struct *sbsec = sb->s_security;
+ struct task_security_struct *tsec = current->security[selinux_idx];
+ struct superblock_security_struct *sbsec =
sb->s_security[selinux_idx];

if (!data)
goto out;
@@ -499,7 +493,7 @@

static int superblock_doinit(struct super_block *sb, void *data)
{
- struct superblock_security_struct *sbsec = sb->s_security;
+ struct superblock_security_struct *sbsec =
sb->s_security[selinux_idx];
struct dentry *root = sb->s_root;
struct inode *inode = root->d_inode;
int rc = 0;
@@ -722,7 +716,7 @@
static int inode_doinit_with_dentry(struct inode *inode, struct dentry
*opt_dentry)
{
struct superblock_security_struct *sbsec = NULL;
- struct inode_security_struct *isec = inode->i_security;
+ struct inode_security_struct *isec = inode->i_security[selinux_idx];
u32 sid;
struct dentry *dentry;
#define INITCONTEXTLEN 255
@@ -739,7 +733,7 @@
if (isec->initialized)
goto out;

- sbsec = inode->i_sb->s_security;
+ sbsec = inode->i_sb->s_security[selinux_idx];
if (!sbsec->initialized) {
/* Defer initialization until selinux_complete_init,
after the initial policy is loaded and the security
@@ -921,8 +915,8 @@
{
struct task_security_struct *tsec1, *tsec2;

- tsec1 = tsk1->security;
- tsec2 = tsk2->security;
+ tsec1 = tsk1->security[selinux_idx];
+ tsec2 = tsk2->security[selinux_idx];
return avc_has_perm(tsec1->sid, tsec2->sid,
SECCLASS_PROCESS, perms, &tsec2->avcr, NULL);
}
@@ -934,7 +928,7 @@
struct task_security_struct *tsec;
struct avc_audit_data ad;

- tsec = tsk->security;
+ tsec = tsk->security[selinux_idx];

AVC_AUDIT_DATA_INIT(&ad,CAP);
ad.tsk = tsk;
@@ -950,7 +944,7 @@
{
struct task_security_struct *tsec;

- tsec = tsk->security;
+ tsec = tsk->security[selinux_idx];

return avc_has_perm(tsec->sid, SECINITSID_KERNEL,
SECCLASS_SYSTEM, perms, NULL, NULL);
@@ -971,8 +965,8 @@
struct inode_security_struct *isec;
struct avc_audit_data ad;

- tsec = tsk->security;
- isec = inode->i_security;
+ tsec = tsk->security[selinux_idx];
+ isec = inode->i_security[selinux_idx];

if (!adp) {
adp = &ad;
@@ -1012,8 +1006,8 @@
struct file *file,
u32 av)
{
- struct task_security_struct *tsec = tsk->security;
- struct file_security_struct *fsec = file->f_security;
+ struct task_security_struct *tsec = tsk->security[selinux_idx];
+ struct file_security_struct *fsec = file->f_security[selinux_idx];
struct vfsmount *mnt = file->f_vfsmnt;
struct dentry *dentry = file->f_dentry;
struct inode *inode = dentry->d_inode;
@@ -1052,9 +1046,9 @@
struct avc_audit_data ad;
int rc;

- tsec = current->security;
- dsec = dir->i_security;
- sbsec = dir->i_sb->s_security;
+ tsec = current->security[selinux_idx];
+ dsec = dir->i_security[selinux_idx];
+ sbsec = dir->i_sb->s_security[selinux_idx];

AVC_AUDIT_DATA_INIT(&ad, FS);
ad.u.fs.dentry = dentry;
@@ -1099,9 +1093,9 @@
u32 av;
int rc;

- tsec = current->security;
- dsec = dir->i_security;
- isec = dentry->d_inode->i_security;
+ tsec = current->security[selinux_idx];
+ dsec = dir->i_security[selinux_idx];
+ isec = dentry->d_inode->i_security[selinux_idx];

AVC_AUDIT_DATA_INIT(&ad, FS);
ad.u.fs.dentry = dentry;
@@ -1145,11 +1139,11 @@
int old_is_dir, new_is_dir;
int rc;

- tsec = current->security;
- old_dsec = old_dir->i_security;
- old_isec = old_dentry->d_inode->i_security;
+ tsec = current->security[selinux_idx];
+ old_dsec = old_dir->i_security[selinux_idx];
+ old_isec = old_dentry->d_inode->i_security[selinux_idx];
old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
- new_dsec = new_dir->i_security;
+ new_dsec = new_dir->i_security[selinux_idx];

AVC_AUDIT_DATA_INIT(&ad, FS);

@@ -1183,7 +1177,7 @@
if (rc)
return rc;
if (new_dentry->d_inode) {
- new_isec = new_dentry->d_inode->i_security;
+ new_isec = new_dentry->d_inode->i_security[selinux_idx];
new_is_dir = S_ISDIR(new_dentry->d_inode->i_mode);
rc = avc_has_perm(tsec->sid, new_isec->sid,
new_isec->sclass,
@@ -1205,8 +1199,8 @@
struct task_security_struct *tsec;
struct superblock_security_struct *sbsec;

- tsec = tsk->security;
- sbsec = sb->s_security;
+ tsec = tsk->security[selinux_idx];
+ sbsec = sb->s_security[selinux_idx];
return avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
perms, NULL, ad);
}
@@ -1259,8 +1253,8 @@
/* Set an inode's SID to a specified value. */
int inode_security_set_sid(struct inode *inode, u32 sid)
{
- struct inode_security_struct *isec = inode->i_security;
- struct superblock_security_struct *sbsec = inode->i_sb->s_security;
+ struct inode_security_struct *isec = inode->i_security[selinux_idx];
+ struct superblock_security_struct *sbsec =
inode->i_sb->s_security[selinux_idx];

if (!sbsec->initialized) {
/* Defer initialization to selinux_complete_init. */
@@ -1289,9 +1283,9 @@
unsigned int len;
int rc;

- tsec = current->security;
- dsec = dir->i_security;
- sbsec = dir->i_sb->s_security;
+ tsec = current->security[selinux_idx];
+ dsec = dir->i_security[selinux_idx];
+ sbsec = dir->i_sb->s_security[selinux_idx];

inode = dentry->d_inode;
if (!inode) {
@@ -1358,14 +1352,10 @@

static int selinux_ptrace(struct task_struct *parent, struct
task_struct *child)
{
- struct task_security_struct *psec = parent->security;
- struct task_security_struct *csec = child->security;
+ struct task_security_struct *psec = parent->security[selinux_idx];
+ struct task_security_struct *csec = child->security[selinux_idx];
int rc;

- rc = secondary_ops->ptrace(parent,child);
- if (rc)
- return rc;
-
rc = task_has_perm(parent, child, PROCESS__PTRACE);
/* Save the SID of the tracing process for later use in apply_creds.
*/
if (!rc)
@@ -1376,47 +1366,17 @@
static int selinux_capget(struct task_struct *target, kernel_cap_t
*effective,
kernel_cap_t *inheritable, kernel_cap_t
*permitted)
{
- int error;
-
- error = task_has_perm(current, target, PROCESS__GETCAP);
- if (error)
- return error;
-
- return secondary_ops->capget(target, effective, inheritable,
permitted);
+ return task_has_perm(current, target, PROCESS__GETCAP);
}

static int selinux_capset_check(struct task_struct *target,
kernel_cap_t *effective,
kernel_cap_t *inheritable, kernel_cap_t
*permitted)
{
- int error;
-
- error = secondary_ops->capset_check(target, effective, inheritable,
permitted);
- if (error)
- return error;
-
return task_has_perm(current, target, PROCESS__SETCAP);
}

-static void selinux_capset_set(struct task_struct *target, kernel_cap_t
*effective,
- kernel_cap_t *inheritable, kernel_cap_t
*permitted)
-{
- int error;
-
- error = task_has_perm(current, target, PROCESS__SETCAP);
- if (error)
- return;
-
- secondary_ops->capset_set(target, effective, inheritable, permitted);
-}
-
static int selinux_capable(struct task_struct *tsk, int cap)
{
- int rc;
-
- rc = secondary_ops->capable(tsk, cap);
- if (rc)
- return rc;
-
return task_has_capability(tsk,cap);
}

@@ -1428,11 +1388,7 @@
u32 tsid;
int rc;

- rc = secondary_ops->sysctl(table, op);
- if (rc)
- return rc;
-
- tsec = current->security;
+ tsec = current->security[selinux_idx];

rc = selinux_proc_get_sid(table->de, (op == 001) ?
SECCLASS_DIR : SECCLASS_FILE, &tsid);
@@ -1500,10 +1456,6 @@
{
int rc;

- rc = secondary_ops->syslog(type);
- if (rc)
- return rc;
-
switch (type) {
case 3: /* Read last kernel messages */
case 10: /* Return size of the log buffer */
@@ -1541,7 +1493,7 @@
{
unsigned long free, allowed;
int rc;
- struct task_security_struct *tsec = current->security;
+ struct task_security_struct *tsec = current->security[selinux_idx];

vm_acct_memory(pages);

@@ -1569,13 +1521,10 @@
* Don't audit the check, as it is applied to all processes
* that allocate mappings.
*/
- rc = secondary_ops->capable(current, CAP_SYS_ADMIN);
- if (!rc) {
- rc = avc_has_perm_noaudit(tsec->sid, tsec->sid,
- SECCLASS_CAPABILITY,
- CAP_TO_MASK(CAP_SYS_ADMIN),
- NULL, NULL);
- }
+ rc = avc_has_perm_noaudit(tsec->sid, tsec->sid,
+ SECCLASS_CAPABILITY,
+ CAP_TO_MASK(CAP_SYS_ADMIN),
+ NULL, NULL);
if (rc)
free -= free / 32;

@@ -1613,7 +1562,7 @@
bsec->sid = SECINITSID_UNLABELED;
bsec->set = 0;

- bprm->security = bsec;
+ bprm->security[selinux_idx] = bsec;
return 0;
}

@@ -1627,17 +1576,13 @@
struct avc_audit_data ad;
int rc;

- rc = secondary_ops->bprm_set_security(bprm);
- if (rc)
- return rc;
-
- bsec = bprm->security;
+ bsec = bprm->security[selinux_idx];

if (bsec->set)
return 0;

- tsec = current->security;
- isec = inode->i_security;
+ tsec = current->security[selinux_idx];
+ isec = inode->i_security[selinux_idx];

/* Default to the current task SID. */
bsec->sid = tsec->sid;
@@ -1696,33 +1641,26 @@
return 0;
}

-static int selinux_bprm_check_security (struct linux_binprm *bprm)
-{
- return secondary_ops->bprm_check_security(bprm);
-}
-
-
static int selinux_bprm_secureexec (struct linux_binprm *bprm)
{
- struct task_security_struct *tsec = current->security;
- int atsecure = 0;
+ struct task_security_struct *tsec = current->security[selinux_idx];

if (tsec->osid != tsec->sid) {
/* Enable secure mode for SIDs transitions unless
the noatsecure permission is granted between
the two SIDs, i.e. ahp returns 0. */
- atsecure = avc_has_perm(tsec->osid, tsec->sid,
+ return avc_has_perm(tsec->osid, tsec->sid,
SECCLASS_PROCESS,
PROCESS__NOATSECURE, NULL, NULL);
}

- return (atsecure || secondary_ops->bprm_secureexec(bprm));
+ return 0;
}

static void selinux_bprm_free_security(struct linux_binprm *bprm)
{
- struct bprm_security_struct *bsec = bprm->security;
- bprm->security = NULL;
+ struct bprm_security_struct *bsec = bprm->security[selinux_idx];
+ bprm->security[selinux_idx] = NULL;
kfree(bsec);
}

@@ -1822,11 +1760,9 @@
struct rlimit *rlim, *initrlim;
int rc, i;

- secondary_ops->bprm_apply_creds(bprm, unsafe);
+ tsec = current->security[selinux_idx];

- tsec = current->security;
-
- bsec = bprm->security;
+ bsec = bprm->security[selinux_idx];
sid = bsec->sid;

tsec->osid = tsec->sid;
@@ -2030,12 +1966,6 @@
unsigned long flags,
void * data)
{
- int rc;
-
- rc = secondary_ops->sb_mount(dev_name, nd, type, flags, data);
- if (rc)
- return rc;
-
if (flags & MS_REMOUNT)
return superblock_has_perm(current, nd->mnt->mnt_sb,
FILESYSTEM__REMOUNT, NULL);
@@ -2046,12 +1976,6 @@

static int selinux_umount(struct vfsmount *mnt, int flags)
{
- int rc;
-
- rc = secondary_ops->sb_umount(mnt, flags);
- if (rc)
- return rc;
-
return superblock_has_perm(current,mnt->mnt_sb,
FILESYSTEM__UNMOUNT,NULL);
}
@@ -2080,11 +2004,6 @@

static int selinux_inode_link(struct dentry *old_dentry, struct inode
*dir, struct dentry *new_dentry)
{
- int rc;
-
- rc = secondary_ops->inode_link(old_dentry,dir,new_dentry);
- if (rc)
- return rc;
return may_link(dir, old_dentry, MAY_LINK);
}

@@ -2095,11 +2014,6 @@

static int selinux_inode_unlink(struct inode *dir, struct dentry
*dentry)
{
- int rc;
-
- rc = secondary_ops->inode_unlink(dir, dentry);
- if (rc)
- return rc;
return may_link(dir, dentry, MAY_UNLINK);
}

@@ -2130,12 +2044,6 @@

static int selinux_inode_mknod(struct inode *dir, struct dentry
*dentry, int mode, dev_t dev)
{
- int rc;
-
- rc = secondary_ops->inode_mknod(dir, dentry, mode, dev);
- if (rc)
- return rc;
-
return may_create(dir, dentry, inode_mode_to_security_class(mode));
}

@@ -2163,23 +2071,12 @@

static int selinux_inode_follow_link(struct dentry *dentry, struct
nameidata *nameidata)
{
- int rc;
-
- rc = secondary_ops->inode_follow_link(dentry,nameidata);
- if (rc)
- return rc;
return dentry_has_perm(current, NULL, dentry, FILE__READ);
}

static int selinux_inode_permission(struct inode *inode, int mask,
struct nameidata *nd)
{
- int rc;
-
- rc = secondary_ops->inode_permission(inode, mask, nd);
- if (rc)
- return rc;
-
if (!mask) {
/* No permission to check. Existence test. */
return 0;
@@ -2191,12 +2088,6 @@

static int selinux_inode_setattr(struct dentry *dentry, struct iattr
*iattr)
{
- int rc;
-
- rc = secondary_ops->inode_setattr(dentry, iattr);
- if (rc)
- return rc;
-
if (iattr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
ATTR_ATIME_SET | ATTR_MTIME_SET))
return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
@@ -2211,9 +2102,9 @@

static int selinux_inode_setxattr(struct dentry *dentry, char *name,
void *value, size_t size, int flags)
{
- struct task_security_struct *tsec = current->security;
+ struct task_security_struct *tsec = current->security[selinux_idx];
struct inode *inode = dentry->d_inode;
- struct inode_security_struct *isec = inode->i_security;
+ struct inode_security_struct *isec = inode->i_security[selinux_idx];
struct superblock_security_struct *sbsec;
struct avc_audit_data ad;
u32 newsid;
@@ -2233,7 +2124,7 @@
return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
}

- sbsec = inode->i_sb->s_security;
+ sbsec = inode->i_sb->s_security[selinux_idx];
if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
return -EOPNOTSUPP;

@@ -2270,7 +2161,7 @@
void *value, size_t size, int
flags)
{
struct inode *inode = dentry->d_inode;
- struct inode_security_struct *isec = inode->i_security;
+ struct inode_security_struct *isec = inode->i_security[selinux_idx];
u32 newsid;
int rc;

@@ -2293,7 +2184,7 @@
static int selinux_inode_getxattr (struct dentry *dentry, char *name)
{
struct inode *inode = dentry->d_inode;
- struct superblock_security_struct *sbsec = inode->i_sb->s_security;
+ struct superblock_security_struct *sbsec =
inode->i_sb->s_security[selinux_idx];

if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
return -EOPNOTSUPP;
@@ -2330,7 +2221,7 @@

static int selinux_inode_getsecurity(struct inode *inode, const char
*name, void *buffer, size_t size)
{
- struct inode_security_struct *isec = inode->i_security;
+ struct inode_security_struct *isec = inode->i_security[selinux_idx];
char *context;
unsigned len;
int rc;
@@ -2360,7 +2251,7 @@
static int selinux_inode_setsecurity(struct inode *inode, const char
*name,
const void *value, size_t size,
int flags)
{
- struct inode_security_struct *isec = inode->i_security;
+ struct inode_security_struct *isec = inode->i_security[selinux_idx];
u32 newsid;
int rc;

@@ -2481,12 +2372,6 @@

static int selinux_file_mmap(struct file *file, unsigned long prot,
unsigned long flags)
{
- int rc;
-
- rc = secondary_ops->file_mmap(file, prot, flags);
- if (rc)
- return rc;
-
return file_map_prot_check(file, prot,
(flags & MAP_TYPE) == MAP_SHARED);
}
@@ -2494,12 +2379,6 @@
static int selinux_file_mprotect(struct vm_area_struct *vma,
unsigned long prot)
{
- int rc;
-
- rc = secondary_ops->file_mprotect(vma, prot);
- if (rc)
- return rc;
-
return file_map_prot_check(vma->vm_file, prot,
vma->vm_flags&VM_SHARED);
}

@@ -2557,8 +2436,8 @@
struct task_security_struct *tsec;
struct file_security_struct *fsec;

- tsec = current->security;
- fsec = file->f_security;
+ tsec = current->security[selinux_idx];
+ fsec = file->f_security[selinux_idx];
fsec->fown_sid = tsec->sid;

return 0;
@@ -2575,8 +2454,8 @@
/* struct fown_struct is never outside the context of a struct file */
file = (struct file *)((long)fown - offsetof(struct
file,f_owner));

- tsec = tsk->security;
- fsec = file->f_security;
+ tsec = tsk->security[selinux_idx];
+ fsec = file->f_security[selinux_idx];

if (!signum)
perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */
@@ -2596,12 +2475,6 @@

static int selinux_task_create(unsigned long clone_flags)
{
- int rc;
-
- rc = secondary_ops->task_create(clone_flags);
- if (rc)
- return rc;
-
return task_has_perm(current, current, PROCESS__FORK);
}

@@ -2610,12 +2483,12 @@
struct task_security_struct *tsec1, *tsec2;
int rc;

- tsec1 = current->security;
+ tsec1 = current->security[selinux_idx];

rc = task_alloc_security(tsk);
if (rc)
return rc;
- tsec2 = tsk->security;
+ tsec2 = tsk->security[selinux_idx];

tsec2->osid = tsec1->osid;
tsec2->sid = tsec1->sid;
@@ -2648,11 +2521,6 @@
return 0;
}

-static int selinux_task_post_setuid(uid_t id0, uid_t id1, uid_t id2,
int flags)
-{
- return secondary_ops->task_post_setuid(id0,id1,id2,flags);
-}
-
static int selinux_task_setgid(gid_t id0, gid_t id1, gid_t id2, int
flags)
{
/* See the comment for setuid above. */
@@ -2682,23 +2550,12 @@

static int selinux_task_setnice(struct task_struct *p, int nice)
{
- int rc;
-
- rc = secondary_ops->task_setnice(p, nice);
- if (rc)
- return rc;
-
return task_has_perm(current,p, PROCESS__SETSCHED);
}

static int selinux_task_setrlimit(unsigned int resource, struct rlimit
*new_rlim)
{
struct rlimit *old_rlim = current->signal->rlim + resource;
- int rc;
-
- rc = secondary_ops->task_setrlimit(resource, new_rlim);
- if (rc)
- return rc;

/* Control the ability to change the hard limit (whether
lowering or raising it), so that the hard limit can
@@ -2714,8 +2571,8 @@
{
struct task_security_struct *tsec1, *tsec2;

- tsec1 = current->security;
- tsec2 = p->security;
+ tsec1 = current->security[selinux_idx];
+ tsec2 = p->security[selinux_idx];

/* No auditing from the setscheduler hook, since the runqueue lock
is held and the system will deadlock if we try to log an audit
@@ -2733,11 +2590,6 @@
static int selinux_task_kill(struct task_struct *p, struct siginfo
*info, int sig)
{
u32 perm;
- int rc;
-
- rc = secondary_ops->task_kill(p, info, sig);
- if (rc)
- return rc;

if (info && ((unsigned long)info == 1 ||
(unsigned long)info == 2 || SI_FROMKERNEL(info)))
@@ -2776,9 +2628,7 @@
{
struct task_security_struct *tsec;

- secondary_ops->task_reparent_to_init(p);
-
- tsec = p->security;
+ tsec = p->security[selinux_idx];
tsec->osid = tsec->sid;
tsec->sid = SECINITSID_KERNEL;
return;
@@ -2787,8 +2637,8 @@
static void selinux_task_to_inode(struct task_struct *p,
struct inode *inode)
{
- struct task_security_struct *tsec = p->security;
- struct inode_security_struct *isec = inode->i_security;
+ struct task_security_struct *tsec = p->security[selinux_idx];
+ struct inode_security_struct *isec = inode->i_security[selinux_idx];

isec->sid = tsec->sid;
isec->initialized = 1;
@@ -2957,8 +2807,8 @@
struct avc_audit_data ad;
int err = 0;

- tsec = task->security;
- isec = SOCK_INODE(sock)->i_security;
+ tsec = task->security[selinux_idx];
+ isec = SOCK_INODE(sock)->i_security[selinux_idx];

if (isec->sid == SECINITSID_KERNEL)
goto out;
@@ -2981,7 +2831,7 @@
if (kern)
goto out;

- tsec = current->security;
+ tsec = current->security[selinux_idx];
err = avc_has_perm(tsec->sid, tsec->sid,
socket_type_to_security_class(family, type,
protocol), SOCKET__CREATE, NULL, NULL);
@@ -3000,9 +2850,9 @@
err = inode_doinit(SOCK_INODE(sock));
if (err < 0)
return;
- isec = SOCK_INODE(sock)->i_security;
+ isec = SOCK_INODE(sock)->i_security[selinux_idx];

- tsec = current->security;
+ tsec = current->security[selinux_idx];
isec->sclass = socket_type_to_security_class(family, type, protocol);
isec->sid = kern ? SECINITSID_KERNEL : tsec->sid;

@@ -3039,8 +2889,8 @@
struct sock *sk = sock->sk;
u32 sid, node_perm, addrlen;

- tsec = current->security;
- isec = SOCK_INODE(sock)->i_security;
+ tsec = current->security[selinux_idx];
+ isec = SOCK_INODE(sock)->i_security[selinux_idx];

if (family == PF_INET) {
addr4 = (struct sockaddr_in *)address;
@@ -3129,9 +2979,9 @@
err = inode_doinit(SOCK_INODE(newsock));
if (err < 0)
return err;
- newisec = SOCK_INODE(newsock)->i_security;
+ newisec = SOCK_INODE(newsock)->i_security[selinux_idx];

- isec = SOCK_INODE(sock)->i_security;
+ isec = SOCK_INODE(sock)->i_security[selinux_idx];
newisec->sclass = isec->sclass;
newisec->sid = isec->sid;

@@ -3186,12 +3036,8 @@
struct avc_audit_data ad;
int err;

- err = secondary_ops->unix_stream_connect(sock, other, newsk);
- if (err)
- return err;
-
- isec = SOCK_INODE(sock)->i_security;
- other_isec = SOCK_INODE(other)->i_security;
+ isec = SOCK_INODE(sock)->i_security[selinux_idx];
+ other_isec = SOCK_INODE(other)->i_security[selinux_idx];

AVC_AUDIT_DATA_INIT(&ad,NET);
ad.u.net.sk = other->sk;
@@ -3204,11 +3050,11 @@
return err;

/* connecting socket */
- ssec = sock->sk->sk_security;
+ ssec = sock->sk->sk_security[selinux_idx];
ssec->peer_sid = other_isec->sid;

/* server child socket */
- ssec = newsk->sk_security;
+ ssec = newsk->sk_security[selinux_idx];
ssec->peer_sid = isec->sid;

return 0;
@@ -3222,8 +3068,8 @@
struct avc_audit_data ad;
int err;

- isec = SOCK_INODE(sock)->i_security;
- other_isec = SOCK_INODE(other)->i_security;
+ isec = SOCK_INODE(sock)->i_security[selinux_idx];
+ other_isec = SOCK_INODE(other)->i_security[selinux_idx];

AVC_AUDIT_DATA_INIT(&ad,NET);
ad.u.net.sk = other->sk;
@@ -3265,7 +3111,7 @@
inode = SOCK_INODE(sock);
if (inode) {
struct inode_security_struct *isec;
- isec = inode->i_security;
+ isec = inode->i_security[selinux_idx];
sock_sid = isec->sid;
sock_class = isec->sclass;
}
@@ -3349,13 +3195,13 @@
struct sk_security_struct *ssec;
struct inode_security_struct *isec;

- isec = SOCK_INODE(sock)->i_security;
+ isec = SOCK_INODE(sock)->i_security[selinux_idx];
if (isec->sclass != SECCLASS_UNIX_STREAM_SOCKET) {
err = -ENOPROTOOPT;
goto out;
}

- ssec = sock->sk->sk_security;
+ ssec = sock->sk->sk_security[selinux_idx];

err = security_sid_to_context(ssec->peer_sid, &scontext,
&scontext_len);
if (err)
@@ -3394,7 +3240,7 @@
u32 perm;
struct nlmsghdr *nlh;
struct socket *sock = sk->sk_socket;
- struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
+ struct inode_security_struct *isec =
SOCK_INODE(sock)->i_security[selinux_idx];

if (skb->len < NLMSG_SPACE(0)) {
err = -EINVAL;
@@ -3451,7 +3297,7 @@
if (err)
goto out;

- isec = inode->i_security;
+ isec = inode->i_security[selinux_idx];

switch (isec->sclass) {
case SECCLASS_UDP_SOCKET:
@@ -3577,7 +3423,7 @@
struct kern_ipc_perm *perm,
u16 sclass)
{
- struct task_security_struct *tsec = task->security;
+ struct task_security_struct *tsec = task->security[selinux_idx];
struct ipc_security_struct *isec;

isec = kmalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
@@ -3593,18 +3439,18 @@
} else {
isec->sid = SECINITSID_UNLABELED;
}
- perm->security = isec;
+ perm->security[selinux_idx] = isec;

return 0;
}

static void ipc_free_security(struct kern_ipc_perm *perm)
{
- struct ipc_security_struct *isec = perm->security;
+ struct ipc_security_struct *isec = perm->security[selinux_idx];
if (!isec || isec->magic != SELINUX_MAGIC)
return;

- perm->security = NULL;
+ perm->security[selinux_idx] = NULL;
kfree(isec);
}

@@ -3620,18 +3466,18 @@
msec->magic = SELINUX_MAGIC;
msec->msg = msg;
msec->sid = SECINITSID_UNLABELED;
- msg->security = msec;
+ msg->security[selinux_idx] = msec;

return 0;
}

static void msg_msg_free_security(struct msg_msg *msg)
{
- struct msg_security_struct *msec = msg->security;
+ struct msg_security_struct *msec = msg->security[selinux_idx];
if (!msec || msec->magic != SELINUX_MAGIC)
return;

- msg->security = NULL;
+ msg->security[selinux_idx] = NULL;
kfree(msec);
}

@@ -3642,8 +3488,8 @@
struct ipc_security_struct *isec;
struct avc_audit_data ad;

- tsec = current->security;
- isec = ipc_perms->security;
+ tsec = current->security[selinux_idx];
+ isec = ipc_perms->security[selinux_idx];

AVC_AUDIT_DATA_INIT(&ad, IPC);
ad.u.ipc_id = ipc_perms->key;
@@ -3674,8 +3520,8 @@
if (rc)
return rc;

- tsec = current->security;
- isec = msq->q_perm.security;
+ tsec = current->security[selinux_idx];
+ isec = msq->q_perm.security[selinux_idx];

AVC_AUDIT_DATA_INIT(&ad, IPC);
ad.u.ipc_id = msq->q_perm.key;
@@ -3700,8 +3546,8 @@
struct ipc_security_struct *isec;
struct avc_audit_data ad;

- tsec = current->security;
- isec = msq->q_perm.security;
+ tsec = current->security[selinux_idx];
+ isec = msq->q_perm.security[selinux_idx];

AVC_AUDIT_DATA_INIT(&ad, IPC);
ad.u.ipc_id = msq->q_perm.key;
@@ -3746,9 +3592,9 @@
struct avc_audit_data ad;
int rc;

- tsec = current->security;
- isec = msq->q_perm.security;
- msec = msg->security;
+ tsec = current->security[selinux_idx];
+ isec = msq->q_perm.security[selinux_idx];
+ msec = msg->security[selinux_idx];

/*
* First time through, need to assign label to the message
@@ -3796,9 +3642,9 @@
struct avc_audit_data ad;
int rc;

- tsec = target->security;
- isec = msq->q_perm.security;
- msec = msg->security;
+ tsec = target->security[selinux_idx];
+ isec = msq->q_perm.security[selinux_idx];
+ msec = msg->security[selinux_idx];

AVC_AUDIT_DATA_INIT(&ad, IPC);
ad.u.ipc_id = msq->q_perm.key;
@@ -3825,8 +3671,8 @@
if (rc)
return rc;

- tsec = current->security;
- isec = shp->shm_perm.security;
+ tsec = current->security[selinux_idx];
+ isec = shp->shm_perm.security[selinux_idx];

AVC_AUDIT_DATA_INIT(&ad, IPC);
ad.u.ipc_id = shp->shm_perm.key;
@@ -3851,8 +3697,8 @@
struct ipc_security_struct *isec;
struct avc_audit_data ad;

- tsec = current->security;
- isec = shp->shm_perm.security;
+ tsec = current->security[selinux_idx];
+ isec = shp->shm_perm.security[selinux_idx];

AVC_AUDIT_DATA_INIT(&ad, IPC);
ad.u.ipc_id = shp->shm_perm.key;
@@ -3898,11 +3744,6 @@
char __user *shmaddr, int shmflg)
{
u32 perms;
- int rc;
-
- rc = secondary_ops->shm_shmat(shp, shmaddr, shmflg);
- if (rc)
- return rc;

if (shmflg & SHM_RDONLY)
perms = SHM__READ;
@@ -3924,8 +3765,8 @@
if (rc)
return rc;

- tsec = current->security;
- isec = sma->sem_perm.security;
+ tsec = current->security[selinux_idx];
+ isec = sma->sem_perm.security[selinux_idx];

AVC_AUDIT_DATA_INIT(&ad, IPC);
ad.u.ipc_id = sma->sem_perm.key;
@@ -3950,8 +3791,8 @@
struct ipc_security_struct *isec;
struct avc_audit_data ad;

- tsec = current->security;
- isec = sma->sem_perm.security;
+ tsec = current->security[selinux_idx];
+ isec = sma->sem_perm.security[selinux_idx];

AVC_AUDIT_DATA_INIT(&ad, IPC);
ad.u.ipc_id = sma->sem_perm.key;
@@ -4017,7 +3858,7 @@

static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short
flag)
{
- struct ipc_security_struct *isec = ipcp->security;
+ struct ipc_security_struct *isec = ipcp->security[selinux_idx];
u16 sclass = SECCLASS_IPC;
u32 av = 0;

@@ -4036,37 +3877,6 @@
return ipc_has_perm(ipcp, sclass, av);
}

-/* module stacking operations */
-int selinux_register_security (const char *name, struct
security_operations *ops)
-{
- if (secondary_ops != original_ops) {
- printk(KERN_INFO "%s: There is already a secondary security "
- "module registered.\n", __FUNCTION__);
- return -EINVAL;
- }
-
- secondary_ops = ops;
-
- printk(KERN_INFO "%s: Registering secondary module %s\n",
- __FUNCTION__,
- name);
-
- return 0;
-}
-
-int selinux_unregister_security (const char *name, struct
security_operations *ops)
-{
- if (ops != secondary_ops) {
- printk (KERN_INFO "%s: trying to unregister a security module "
- "that is not registered.\n", __FUNCTION__);
- return -EINVAL;
- }
-
- secondary_ops = original_ops;
-
- return 0;
-}
-
static void selinux_d_instantiate (struct dentry *dentry, struct inode
*inode)
{
if (inode)
@@ -4090,7 +3900,7 @@
if (!size)
return -ERANGE;

- tsec = p->security;
+ tsec = p->security[selinux_idx];

if (!strcmp(name, "current"))
sid = tsec->sid;
@@ -4160,7 +3970,7 @@
operation. See selinux_bprm_set_security for the execve
checks and may_create for the file creation checks. The
operation will then fail if the context is not permitted. */
- tsec = p->security;
+ tsec = p->security[selinux_idx];
if (!strcmp(name, "exec"))
tsec->exec_sid = sid;
else if (!strcmp(name, "fscreate"))
@@ -4175,7 +3985,6 @@
.ptrace = selinux_ptrace,
.capget = selinux_capget,
.capset_check = selinux_capset_check,
- .capset_set = selinux_capset_set,
.sysctl = selinux_sysctl,
.capable = selinux_capable,
.quotactl = selinux_quotactl,
@@ -4190,7 +3999,6 @@
.bprm_free_security = selinux_bprm_free_security,
.bprm_apply_creds = selinux_bprm_apply_creds,
.bprm_set_security = selinux_bprm_set_security,
- .bprm_check_security = selinux_bprm_check_security,
.bprm_secureexec = selinux_bprm_secureexec,

.sb_alloc_security = selinux_sb_alloc_security,
@@ -4247,7 +4055,6 @@
.task_alloc_security = selinux_task_alloc_security,
.task_free_security = selinux_task_free_security,
.task_setuid = selinux_task_setuid,
- .task_post_setuid = selinux_task_post_setuid,
.task_setgid = selinux_task_setgid,
.task_setpgid = selinux_task_setpgid,
.task_getpgid = selinux_task_getpgid,
@@ -4287,9 +4094,6 @@
.sem_semctl = selinux_sem_semctl,
.sem_semop = selinux_sem_semop,

- .register_security = selinux_register_security,
- .unregister_security = selinux_unregister_security,
-
.d_instantiate = selinux_d_instantiate,

.getprocattr = selinux_getprocattr,
@@ -4319,10 +4123,13 @@
#endif
};

+#define MY_NAME "selinux"
__init int selinux_init(void)
{
struct task_security_struct *tsec;

+ secondary = 0;
+
if (!selinux_enabled) {
printk(KERN_INFO "SELinux: Disabled at boot.\n");
return 0;
@@ -4333,16 +4140,24 @@
/* Set the security state for the initial task. */
if (task_alloc_security(current))
panic("SELinux: Failed to initialize initial task.\n");
- tsec = current->security;
+ tsec = current->security[selinux_idx];
tsec->osid = tsec->sid = SECINITSID_KERNEL;

avc_init();

- original_ops = secondary_ops = security_ops;
- if (!secondary_ops)
- panic ("SELinux: No initial security operations\n");
- if (register_security (&selinux_ops))
- panic("SELinux: Unable to register with kernel.\n");
+ selinux_idx = register_security (&selinux_ops);
+ if (selinux_idx) {
+ secondary = 1;
+ selinux_idx = mod_reg_security( MY_NAME, &selinux_ops);
+ if (selinux_idx < 0) {
+ printk(KERN_ERR "%s: mod_reg_security returned %d.\n",
+ __FUNCTION__, selinux_idx);
+ panic("SELinux: Unable to register with kernel.\n");
+ } else {
+ printk(KERN_ERR "%s: registered with id %d\n",
+ __FUNCTION__, selinux_idx);
+ }
+ }

if (selinux_enforcing) {
printk(KERN_INFO "SELinux: Starting in enforcing mode\n");
@@ -4473,9 +4288,14 @@

selinux_disabled = 1;

- /* Reset security_ops to the secondary module, dummy or capability. */
- security_ops = secondary_ops;
-
+ /* Unregister selinux */
+ if (secondary) {
+ if (mod_unreg_security(MY_NAME, &selinux_ops))
+ printk(KERN_INFO "Failure unregistering selinux.\n");
+ } else {
+ if (unregister_security(&selinux_ops))
+ printk(KERN_INFO "Failure unregistering selinux.\n");
+ }
/* Unregister netfilter hooks. */
selinux_nf_ip_exit();

Index: linux-2.6.10-rc1-bk12-stack/security/selinux/selinuxfs.c
===================================================================
---
linux-2.6.10-rc1-bk12-stack.orig/security/selinux/selinuxfs.c 2004-11-02
19:56:04.454410920 -0600
+++ linux-2.6.10-rc1-bk12-stack/security/selinux/selinuxfs.c 2004-11-02
20:05:51.038236624 -0600
@@ -33,6 +33,8 @@

static DECLARE_MUTEX(sel_sem);

+extern int selinux_idx;
+
/* global data for booleans */
static struct dentry *bool_dir = NULL;
static int bool_num = 0;
@@ -46,7 +48,7 @@
{
struct task_security_struct *tsec;

- tsec = tsk->security;
+ tsec = tsk->security[selinux_idx];
if (!tsec)
return -EACCES;

@@ -856,7 +858,7 @@
ret = -ENAMETOOLONG;
goto err;
}
- isec = (struct inode_security_struct*)inode->i_security;
+ isec = (struct inode_security_struct*)inode->i_security[selinux_idx];
if ((ret = security_genfs_sid("selinuxfs", page, SECCLASS_FILE,
&sid)))
goto err;
isec->sid = sid;
@@ -934,7 +936,7 @@
inode = sel_make_inode(sb, S_IFCHR | S_IRUGO | S_IWUGO);
if (!inode)
goto out;
- isec = (struct inode_security_struct*)inode->i_security;
+ isec = (struct inode_security_struct*)inode->i_security[selinux_idx];
isec->sid = SECINITSID_DEVNULL;
isec->sclass = SECCLASS_CHR_FILE;
isec->initialized = 1;


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/