* [PATCH 5/5] LSM: SELinux changes to allow LSM stacking
@ 2012-09-05 2:09 Casey Schaufler
2012-09-05 14:38 ` Stephen Smalley
0 siblings, 1 reply; 5+ messages in thread
From: Casey Schaufler @ 2012-09-05 2:09 UTC (permalink / raw)
To: LSM, SE Linux, Eric Paris; +Cc: Casey Schaufler
Subject: LSM: SELinux changes to allow LSM stacking
Change security blob accesses to use the lsm_get/lsm_set
interfaces. This requires removal of the cred pointer
poisoning in selinux_cred_free.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
security/Kconfig | 7 +-
security/selinux/hooks.c | 264 +++++++++++++++++++++----------------
security/selinux/include/objsec.h | 2 +
security/selinux/include/xfrm.h | 2 +-
security/selinux/selinuxfs.c | 6 +-
security/selinux/xfrm.c | 9 +-
6 files changed, 167 insertions(+), 123 deletions(-)
diff --git a/security/Kconfig b/security/Kconfig
index cf83c27..fccab76 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -126,12 +126,15 @@ source security/yama/Kconfig
config SECURITY_COMPOSER
bool "Allow multiple concurrent LSMs"
depends on SECURITY && \
- !SECURITY_SELINUX
+ !(SECURITY_SELINUX && SECURITY_SMACK)
default n
help
Allows multiple security modules to be used concurrently.
Only LSMs that have been made composer friendly may be used
- when set. Smack, TOMOYO, AppArmor and Yama are composer friendly.
+ when set. Smack, TOMOYO, AppArmor, SELinux and Yama are
+ composer friendly. Smack and SELinux have conflicting uses
+ of the CIPSO IP option. Until a resolution is found they
+ may not be used together.
If you are unsure how to answer this question, answer N.
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 6c77f63..d1e0145 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -158,7 +158,7 @@ static void cred_init_security(void)
panic("SELinux: Failed to initialize initial task.\n");
tsec->osid = tsec->sid = SECINITSID_KERNEL;
- cred->security = tsec;
+ lsm_set_cred(cred, tsec, &selinux_ops);
}
/*
@@ -168,7 +168,7 @@ static inline u32 cred_sid(const struct cred *cred)
{
const struct task_security_struct *tsec;
- tsec = cred->security;
+ tsec = lsm_get_cred(cred, &selinux_ops);
return tsec->sid;
}
@@ -190,8 +190,9 @@ static inline u32 task_sid(const struct task_struct *task)
*/
static inline u32 current_sid(void)
{
- const struct task_security_struct *tsec = current_security();
+ const struct task_security_struct *tsec;
+ tsec = lsm_get_cred(current_cred(), &selinux_ops);
return tsec->sid;
}
@@ -212,22 +213,23 @@ static int inode_alloc_security(struct inode *inode)
isec->sid = SECINITSID_UNLABELED;
isec->sclass = SECCLASS_FILE;
isec->task_sid = sid;
- inode->i_security = isec;
+ lsm_set_inode(inode, isec, &selinux_ops);
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 = lsm_get_inode(inode, &selinux_ops);
+ struct superblock_security_struct *sbsec =
+ lsm_get_super(inode->i_sb, &selinux_ops);
spin_lock(&sbsec->isec_lock);
if (!list_empty(&isec->list))
list_del_init(&isec->list);
spin_unlock(&sbsec->isec_lock);
- inode->i_security = NULL;
+ lsm_set_inode(inode, NULL, &selinux_ops);
kmem_cache_free(sel_inode_cache, isec);
}
@@ -242,15 +244,15 @@ static int file_alloc_security(struct file *file)
fsec->sid = sid;
fsec->fown_sid = sid;
- file->f_security = fsec;
+ lsm_set_file(file, fsec, &selinux_ops);
return 0;
}
static void file_free_security(struct file *file)
{
- struct file_security_struct *fsec = file->f_security;
- file->f_security = NULL;
+ struct file_security_struct *fsec = lsm_get_file(file, &selinux_ops);
+ lsm_set_file(file, NULL, &selinux_ops);
kfree(fsec);
}
@@ -269,15 +271,16 @@ static int superblock_alloc_security(struct super_block *sb)
sbsec->sid = SECINITSID_UNLABELED;
sbsec->def_sid = SECINITSID_FILE;
sbsec->mntpoint_sid = SECINITSID_UNLABELED;
- sb->s_security = sbsec;
+ lsm_set_super(sb, sbsec, &selinux_ops);
return 0;
}
static void superblock_free_security(struct super_block *sb)
{
- struct superblock_security_struct *sbsec = sb->s_security;
- sb->s_security = NULL;
+ struct superblock_security_struct *sbsec =
+ lsm_get_super(sb, &selinux_ops);
+ lsm_set_super(sb, NULL, &selinux_ops);
kfree(sbsec);
}
@@ -323,9 +326,10 @@ static int may_context_mount_sb_relabel(u32 sid,
struct superblock_security_struct *sbsec,
const struct cred *cred)
{
- const struct task_security_struct *tsec = cred->security;
+ const struct task_security_struct *tsec;
int rc;
+ tsec = lsm_get_cred(cred, &selinux_ops);
rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
FILESYSTEM__RELABELFROM, NULL);
if (rc)
@@ -340,8 +344,10 @@ static int may_context_mount_inode_relabel(u32 sid,
struct superblock_security_struct *sbsec,
const struct cred *cred)
{
- const struct task_security_struct *tsec = cred->security;
+ const struct task_security_struct *tsec;
int rc;
+
+ tsec = lsm_get_cred(cred, &selinux_ops);
rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
FILESYSTEM__RELABELFROM, NULL);
if (rc)
@@ -354,7 +360,8 @@ static int may_context_mount_inode_relabel(u32 sid,
static int sb_finish_set_opts(struct super_block *sb)
{
- struct superblock_security_struct *sbsec = sb->s_security;
+ struct superblock_security_struct *sbsec =
+ lsm_get_super(sb, &selinux_ops);
struct dentry *root = sb->s_root;
struct inode *root_inode = root->d_inode;
int rc = 0;
@@ -444,7 +451,8 @@ static int selinux_get_mnt_opts(const struct super_block *sb,
struct security_mnt_opts *opts)
{
int rc = 0, i;
- struct superblock_security_struct *sbsec = sb->s_security;
+ struct superblock_security_struct *sbsec =
+ lsm_get_super(sb, &selinux_ops);
char *context = NULL;
u32 len;
char tmp;
@@ -504,8 +512,9 @@ static int selinux_get_mnt_opts(const struct super_block *sb,
}
if (sbsec->flags & ROOTCONTEXT_MNT) {
struct inode *root = sbsec->sb->s_root->d_inode;
- struct inode_security_struct *isec = root->i_security;
+ struct inode_security_struct *isec;
+ isec = lsm_get_inode(root, &selinux_ops);
rc = security_sid_to_context(isec->sid, &context, &len);
if (rc)
goto out_free;
@@ -555,10 +564,12 @@ static int selinux_set_mnt_opts(struct super_block *sb,
{
const struct cred *cred = current_cred();
int rc = 0, i;
- struct superblock_security_struct *sbsec = sb->s_security;
+ struct superblock_security_struct *sbsec =
+ lsm_get_super(sb, &selinux_ops);
const char *name = sb->s_type->name;
struct inode *inode = sbsec->sb->s_root->d_inode;
- struct inode_security_struct *root_isec = inode->i_security;
+ struct inode_security_struct *root_isec =
+ lsm_get_inode(inode, &selinux_ops);
u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
u32 defcontext_sid = 0;
char **mount_options = opts->mnt_opts;
@@ -753,8 +764,10 @@ out_double_mount:
static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
struct super_block *newsb)
{
- const struct superblock_security_struct *oldsbsec = oldsb->s_security;
- struct superblock_security_struct *newsbsec = newsb->s_security;
+ const struct superblock_security_struct *oldsbsec =
+ lsm_get_super(oldsb, &selinux_ops);
+ struct superblock_security_struct *newsbsec =
+ lsm_get_super(newsb, &selinux_ops);
int set_fscontext = (oldsbsec->flags & FSCONTEXT_MNT);
int set_context = (oldsbsec->flags & CONTEXT_MNT);
@@ -789,16 +802,19 @@ static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
newsbsec->sid = sid;
if (!set_rootcontext) {
struct inode *newinode = newsb->s_root->d_inode;
- struct inode_security_struct *newisec = newinode->i_security;
+ struct inode_security_struct *newisec =
+ lsm_get_inode(newinode, &selinux_ops);
newisec->sid = sid;
}
newsbsec->mntpoint_sid = sid;
}
if (set_rootcontext) {
const struct inode *oldinode = oldsb->s_root->d_inode;
- const struct inode_security_struct *oldisec = oldinode->i_security;
+ const struct inode_security_struct *oldisec =
+ lsm_get_inode(oldinode, &selinux_ops);
struct inode *newinode = newsb->s_root->d_inode;
- struct inode_security_struct *newisec = newinode->i_security;
+ struct inode_security_struct *newisec =
+ lsm_get_inode(newinode, &selinux_ops);
newisec->sid = oldisec->sid;
}
@@ -1162,7 +1178,7 @@ static int selinux_proc_get_sid(struct dentry *dentry,
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 = lsm_get_inode(inode, &selinux_ops);
u32 sid;
struct dentry *dentry;
#define INITCONTEXTLEN 255
@@ -1177,7 +1193,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
if (isec->initialized)
goto out_unlock;
- sbsec = inode->i_sb->s_security;
+ sbsec = lsm_get_super(inode->i_sb, &selinux_ops);
if (!(sbsec->flags & SE_SBINITIALIZED)) {
/* Defer initialization until selinux_complete_init,
after the initial policy is loaded and the security
@@ -1389,8 +1405,10 @@ static int task_has_perm(const struct task_struct *tsk1,
u32 sid1, sid2;
rcu_read_lock();
- __tsec1 = __task_cred(tsk1)->security; sid1 = __tsec1->sid;
- __tsec2 = __task_cred(tsk2)->security; sid2 = __tsec2->sid;
+ __tsec1 = lsm_get_cred(__task_cred(tsk1), &selinux_ops);
+ sid1 = __tsec1->sid;
+ __tsec2 = lsm_get_cred(__task_cred(tsk2), &selinux_ops);
+ sid2 = __tsec2->sid;
rcu_read_unlock();
return avc_has_perm(sid1, sid2, SECCLASS_PROCESS, perms, NULL);
}
@@ -1480,7 +1498,7 @@ static int inode_has_perm(const struct cred *cred,
return 0;
sid = cred_sid(cred);
- isec = inode->i_security;
+ isec = lsm_get_inode(inode, &selinux_ops);
return avc_has_perm_flags(sid, isec->sid, isec->sclass, perms, adp, flags);
}
@@ -1527,7 +1545,7 @@ static int file_has_perm(const struct cred *cred,
struct file *file,
u32 av)
{
- struct file_security_struct *fsec = file->f_security;
+ struct file_security_struct *fsec = lsm_get_file(file, &selinux_ops);
struct inode *inode = file->f_path.dentry->d_inode;
struct common_audit_data ad;
u32 sid = cred_sid(cred);
@@ -1559,15 +1577,16 @@ static int may_create(struct inode *dir,
struct dentry *dentry,
u16 tclass)
{
- const struct task_security_struct *tsec = current_security();
+ const struct task_security_struct *tsec =
+ lsm_get_cred(current_cred(), &selinux_ops);
struct inode_security_struct *dsec;
struct superblock_security_struct *sbsec;
u32 sid, newsid;
struct common_audit_data ad;
int rc;
- dsec = dir->i_security;
- sbsec = dir->i_sb->s_security;
+ dsec = lsm_get_inode(dir, &selinux_ops);
+ sbsec = lsm_get_super(dir->i_sb, &selinux_ops);
sid = tsec->sid;
newsid = tsec->create_sid;
@@ -1622,8 +1641,8 @@ static int may_link(struct inode *dir,
u32 av;
int rc;
- dsec = dir->i_security;
- isec = dentry->d_inode->i_security;
+ dsec = lsm_get_inode(dir, &selinux_ops);
+ isec = lsm_get_inode(dentry->d_inode, &selinux_ops);
ad.type = LSM_AUDIT_DATA_DENTRY;
ad.u.dentry = dentry;
@@ -1666,10 +1685,10 @@ static inline int may_rename(struct inode *old_dir,
int old_is_dir, new_is_dir;
int rc;
- old_dsec = old_dir->i_security;
- old_isec = old_dentry->d_inode->i_security;
+ old_dsec = lsm_get_inode(old_dir, &selinux_ops);
+ old_isec = lsm_get_inode(old_dentry->d_inode, &selinux_ops);
old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
- new_dsec = new_dir->i_security;
+ new_dsec = lsm_get_inode(new_dir, &selinux_ops);
ad.type = LSM_AUDIT_DATA_DENTRY;
@@ -1697,7 +1716,7 @@ static inline int may_rename(struct inode *old_dir,
if (rc)
return rc;
if (new_dentry->d_inode) {
- new_isec = new_dentry->d_inode->i_security;
+ new_isec = lsm_get_inode(new_dentry->d_inode, &selinux_ops);
new_is_dir = S_ISDIR(new_dentry->d_inode->i_mode);
rc = avc_has_perm(sid, new_isec->sid,
new_isec->sclass,
@@ -1718,7 +1737,7 @@ static int superblock_has_perm(const struct cred *cred,
struct superblock_security_struct *sbsec;
u32 sid = cred_sid(cred);
- sbsec = sb->s_security;
+ sbsec = lsm_get_super(sb, &selinux_ops);
return avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad);
}
@@ -1969,9 +1988,9 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
if (bprm->cred_prepared)
return 0;
- old_tsec = current_security();
- new_tsec = bprm->cred->security;
- isec = inode->i_security;
+ old_tsec = lsm_get_cred(current_cred(), &selinux_ops);
+ new_tsec = lsm_get_cred(bprm->cred, &selinux_ops);
+ isec = lsm_get_inode(inode, &selinux_ops);
/* Default to the current task SID. */
new_tsec->sid = old_tsec->sid;
@@ -2046,7 +2065,8 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
rcu_read_lock();
tracer = ptrace_parent(current);
if (likely(tracer != NULL)) {
- sec = __task_cred(tracer)->security;
+ sec = lsm_get_cred(__task_cred(tracer),
+ &selinux_ops);
ptsid = sec->sid;
}
rcu_read_unlock();
@@ -2069,7 +2089,8 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
static int selinux_bprm_secureexec(struct linux_binprm *bprm)
{
- const struct task_security_struct *tsec = current_security();
+ const struct task_security_struct *tsec =
+ lsm_get_cred(current_cred(), &selinux_ops);
u32 sid, osid;
int atsecure = 0;
@@ -2186,7 +2207,7 @@ static void selinux_bprm_committing_creds(struct linux_binprm *bprm)
struct rlimit *rlim, *initrlim;
int rc, i;
- new_tsec = bprm->cred->security;
+ new_tsec = lsm_get_cred(bprm->cred, &selinux_ops);
if (new_tsec->sid == new_tsec->osid)
return;
@@ -2227,7 +2248,8 @@ static void selinux_bprm_committing_creds(struct linux_binprm *bprm)
*/
static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
{
- const struct task_security_struct *tsec = current_security();
+ const struct task_security_struct *tsec =
+ lsm_get_cred(current_cred(), &selinux_ops);
struct itimerval itimer;
u32 osid, sid;
int rc, i;
@@ -2374,7 +2396,8 @@ static int selinux_sb_remount(struct super_block *sb, void *data)
int rc, i, *flags;
struct security_mnt_opts opts;
char *secdata, **mount_options;
- struct superblock_security_struct *sbsec = sb->s_security;
+ struct superblock_security_struct *sbsec =
+ lsm_get_super(sb, &selinux_ops);
if (!(sbsec->flags & SE_SBINITIALIZED))
return 0;
@@ -2426,7 +2449,8 @@ static int selinux_sb_remount(struct super_block *sb, void *data)
break;
case ROOTCONTEXT_MNT: {
struct inode_security_struct *root_isec;
- root_isec = sb->s_root->d_inode->i_security;
+ root_isec = lsm_get_inode(sb->s_root->d_inode,
+ &selinux_ops);
if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid))
goto out_bad_option;
@@ -2522,15 +2546,16 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
const struct qstr *qstr, char **name,
void **value, size_t *len)
{
- const struct task_security_struct *tsec = current_security();
+ const struct task_security_struct *tsec =
+ lsm_get_cred(current_cred(), &selinux_ops);
struct inode_security_struct *dsec;
struct superblock_security_struct *sbsec;
u32 sid, newsid, clen;
int rc;
char *namep = NULL, *context;
- dsec = dir->i_security;
- sbsec = dir->i_sb->s_security;
+ dsec = lsm_get_inode(dir, &selinux_ops);
+ sbsec = lsm_get_super(dir->i_sb, &selinux_ops);
sid = tsec->sid;
newsid = tsec->create_sid;
@@ -2554,7 +2579,8 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
/* Possibly defer initialization to selinux_complete_init. */
if (sbsec->flags & SE_SBINITIALIZED) {
- struct inode_security_struct *isec = inode->i_security;
+ struct inode_security_struct *isec =
+ lsm_get_inode(inode, &selinux_ops);
isec->sclass = inode_mode_to_security_class(inode->i_mode);
isec->sid = newsid;
isec->initialized = 1;
@@ -2643,7 +2669,7 @@ static noinline int audit_inode_permission(struct inode *inode,
unsigned flags)
{
struct common_audit_data ad;
- struct inode_security_struct *isec = inode->i_security;
+ struct inode_security_struct *isec = lsm_get_inode(inode, &selinux_ops);
int rc;
ad.type = LSM_AUDIT_DATA_INODE;
@@ -2683,7 +2709,7 @@ static int selinux_inode_permission(struct inode *inode, int mask)
perms = file_mask_to_av(inode->i_mode, mask);
sid = cred_sid(cred);
- isec = inode->i_security;
+ isec = lsm_get_inode(inode, &selinux_ops);
rc = avc_has_perm_noaudit(sid, isec->sid, isec->sclass, perms, 0, &avd);
audited = avc_audit_required(perms, &avd, rc,
@@ -2758,7 +2784,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
const 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 = lsm_get_inode(inode, &selinux_ops);
struct superblock_security_struct *sbsec;
struct common_audit_data ad;
u32 newsid, sid = current_sid();
@@ -2767,7 +2793,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
if (strcmp(name, XATTR_NAME_SELINUX))
return selinux_inode_setotherxattr(dentry, name);
- sbsec = inode->i_sb->s_security;
+ sbsec = lsm_get_super(inode->i_sb, &selinux_ops);
if (!(sbsec->flags & SE_SBLABELSUPP))
return -EOPNOTSUPP;
@@ -2835,7 +2861,7 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
int flags)
{
struct inode *inode = dentry->d_inode;
- struct inode_security_struct *isec = inode->i_security;
+ struct inode_security_struct *isec = lsm_get_inode(inode, &selinux_ops);
u32 newsid;
int rc;
@@ -2890,7 +2916,7 @@ static int selinux_inode_getsecurity(const struct inode *inode, const char *name
u32 size;
int error;
char *context = NULL;
- struct inode_security_struct *isec = inode->i_security;
+ struct inode_security_struct *isec = lsm_get_inode(inode, &selinux_ops);
if (strcmp(name, XATTR_SELINUX_SUFFIX))
return -EOPNOTSUPP;
@@ -2926,7 +2952,7 @@ out_nofree:
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 = lsm_get_inode(inode, &selinux_ops);
u32 newsid;
int rc;
@@ -2955,7 +2981,7 @@ static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t
static void selinux_inode_getsecid(const struct inode *inode, u32 *secid)
{
- struct inode_security_struct *isec = inode->i_security;
+ struct inode_security_struct *isec = lsm_get_inode(inode, &selinux_ops);
*secid = isec->sid;
}
@@ -2977,8 +3003,8 @@ static int selinux_revalidate_file_permission(struct file *file, int mask)
static int selinux_file_permission(struct file *file, int mask)
{
struct inode *inode = file->f_path.dentry->d_inode;
- struct file_security_struct *fsec = file->f_security;
- struct inode_security_struct *isec = inode->i_security;
+ struct file_security_struct *fsec = lsm_get_file(file, &selinux_ops);
+ struct inode_security_struct *isec = lsm_get_inode(inode, &selinux_ops);
u32 sid = current_sid();
if (!mask)
@@ -3212,7 +3238,7 @@ static int selinux_file_set_fowner(struct file *file)
{
struct file_security_struct *fsec;
- fsec = file->f_security;
+ fsec = lsm_get_file(file, &selinux_ops);
fsec->fown_sid = current_sid();
return 0;
@@ -3229,7 +3255,7 @@ static int selinux_file_send_sigiotask(struct task_struct *tsk,
/* struct fown_struct is never outside the context of a struct file */
file = container_of(fown, struct file, f_owner);
- fsec = file->f_security;
+ fsec = lsm_get_file(file, &selinux_ops);
if (!signum)
perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */
@@ -3252,8 +3278,8 @@ static int selinux_file_open(struct file *file, const struct cred *cred)
struct file_security_struct *fsec;
struct inode_security_struct *isec;
- fsec = file->f_security;
- isec = file->f_path.dentry->d_inode->i_security;
+ fsec = lsm_get_file(file, &selinux_ops);
+ isec = lsm_get_inode(file->f_path.dentry->d_inode, &selinux_ops);
/*
* Save inode label and policy sequence number
* at open-time so that selinux_file_permission
@@ -3292,7 +3318,7 @@ static int selinux_cred_alloc_blank(struct cred *cred, gfp_t gfp)
if (!tsec)
return -ENOMEM;
- cred->security = tsec;
+ lsm_set_cred(cred, tsec, &selinux_ops);
return 0;
}
@@ -3301,14 +3327,14 @@ static int selinux_cred_alloc_blank(struct cred *cred, gfp_t gfp)
*/
static void selinux_cred_free(struct cred *cred)
{
- struct task_security_struct *tsec = cred->security;
+ struct task_security_struct *tsec = lsm_get_cred(cred, &selinux_ops);
/*
* cred->security == NULL if security_cred_alloc_blank() or
* security_prepare_creds() returned an error.
*/
- BUG_ON(cred->security && (unsigned long) cred->security < PAGE_SIZE);
- cred->security = (void *) 0x7UL;
+ BUG_ON(tsec && (unsigned long) tsec < PAGE_SIZE);
+ lsm_set_cred(cred, NULL, &selinux_ops);
kfree(tsec);
}
@@ -3321,13 +3347,13 @@ static int selinux_cred_prepare(struct cred *new, const struct cred *old,
const struct task_security_struct *old_tsec;
struct task_security_struct *tsec;
- old_tsec = old->security;
+ old_tsec = lsm_get_cred(old, &selinux_ops);
tsec = kmemdup(old_tsec, sizeof(struct task_security_struct), gfp);
if (!tsec)
return -ENOMEM;
- new->security = tsec;
+ lsm_set_cred(new, tsec, &selinux_ops);
return 0;
}
@@ -3336,9 +3362,15 @@ static int selinux_cred_prepare(struct cred *new, const struct cred *old,
*/
static void selinux_cred_transfer(struct cred *new, const struct cred *old)
{
- const struct task_security_struct *old_tsec = old->security;
- struct task_security_struct *tsec = new->security;
+ const struct task_security_struct *old_tsec;
+ struct task_security_struct *tsec;
+
+ old_tsec = lsm_get_cred(old, &selinux_ops);
+ tsec = lsm_get_cred(new, &selinux_ops);
+ /*
+ * This is a data copy, not a pointer assignment.
+ */
*tsec = *old_tsec;
}
@@ -3348,7 +3380,7 @@ static void selinux_cred_transfer(struct cred *new, const struct cred *old)
*/
static int selinux_kernel_act_as(struct cred *new, u32 secid)
{
- struct task_security_struct *tsec = new->security;
+ struct task_security_struct *tsec = lsm_get_cred(new, &selinux_ops);
u32 sid = current_sid();
int ret;
@@ -3371,8 +3403,8 @@ static int selinux_kernel_act_as(struct cred *new, u32 secid)
*/
static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)
{
- struct inode_security_struct *isec = inode->i_security;
- struct task_security_struct *tsec = new->security;
+ struct inode_security_struct *isec = lsm_get_inode(inode, &selinux_ops);
+ struct task_security_struct *tsec = lsm_get_cred(new, &selinux_ops);
u32 sid = current_sid();
int ret;
@@ -3509,7 +3541,7 @@ static int selinux_task_wait(struct task_struct *p)
static void selinux_task_to_inode(struct task_struct *p,
struct inode *inode)
{
- struct inode_security_struct *isec = inode->i_security;
+ struct inode_security_struct *isec = lsm_get_inode(inode, &selinux_ops);
u32 sid = task_sid(p);
isec->sid = sid;
@@ -3782,7 +3814,8 @@ static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms)
static int selinux_socket_create(int family, int type,
int protocol, int kern)
{
- const struct task_security_struct *tsec = current_security();
+ const struct task_security_struct *tsec =
+ lsm_get_cred(current_cred(), &selinux_ops);
u32 newsid;
u16 secclass;
int rc;
@@ -3801,8 +3834,10 @@ static int selinux_socket_create(int family, int type,
static int selinux_socket_post_create(struct socket *sock, int family,
int type, int protocol, int kern)
{
- const struct task_security_struct *tsec = current_security();
- struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
+ const struct task_security_struct *tsec =
+ lsm_get_cred(current_cred(), &selinux_ops);
+ struct inode_security_struct *isec =
+ lsm_get_inode(SOCK_INODE(sock), &selinux_ops);
struct sk_security_struct *sksec;
int err = 0;
@@ -4002,9 +4037,9 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
if (err)
return err;
- newisec = SOCK_INODE(newsock)->i_security;
+ newisec = lsm_get_inode(SOCK_INODE(newsock), &selinux_ops);
- isec = SOCK_INODE(sock)->i_security;
+ isec = lsm_get_inode(SOCK_INODE(sock), &selinux_ops);
newisec->sclass = isec->sclass;
newisec->sid = isec->sid;
newisec->initialized = 1;
@@ -4339,7 +4374,8 @@ static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
static void selinux_sock_graft(struct sock *sk, struct socket *parent)
{
- struct inode_security_struct *isec = SOCK_INODE(parent)->i_security;
+ struct inode_security_struct *isec =
+ lsm_get_inode(SOCK_INODE(parent), &selinux_ops);
struct sk_security_struct *sksec = sk->sk_security;
if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
@@ -4412,7 +4448,7 @@ static int selinux_secmark_relabel_packet(u32 sid)
const struct task_security_struct *__tsec;
u32 tsid;
- __tsec = current_security();
+ __tsec = lsm_get_cred(current_cred(), &selinux_ops);
tsid = __tsec->sid;
return avc_has_perm(tsid, sid, SECCLASS_PACKET, PACKET__RELABELTO, NULL);
@@ -4796,15 +4832,15 @@ static int ipc_alloc_security(struct task_struct *task,
sid = task_sid(task);
isec->sclass = sclass;
isec->sid = sid;
- perm->security = isec;
+ lsm_set_ipc(perm, isec, &selinux_ops);
return 0;
}
static void ipc_free_security(struct kern_ipc_perm *perm)
{
- struct ipc_security_struct *isec = perm->security;
- perm->security = NULL;
+ struct ipc_security_struct *isec = lsm_get_ipc(perm, &selinux_ops);
+ lsm_set_ipc(perm, NULL, &selinux_ops);
kfree(isec);
}
@@ -4817,16 +4853,16 @@ static int msg_msg_alloc_security(struct msg_msg *msg)
return -ENOMEM;
msec->sid = SECINITSID_UNLABELED;
- msg->security = msec;
+ lsm_set_msg(msg, msec, &selinux_ops);
return 0;
}
static void msg_msg_free_security(struct msg_msg *msg)
{
- struct msg_security_struct *msec = msg->security;
+ struct msg_security_struct *msec = lsm_get_msg(msg, &selinux_ops);
- msg->security = NULL;
+ lsm_set_msg(msg, NULL, &selinux_ops);
kfree(msec);
}
@@ -4837,7 +4873,7 @@ static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
struct common_audit_data ad;
u32 sid = current_sid();
- isec = ipc_perms->security;
+ isec = lsm_get_ipc(ipc_perms, &selinux_ops);
ad.type = LSM_AUDIT_DATA_IPC;
ad.u.ipc_id = ipc_perms->key;
@@ -4867,7 +4903,7 @@ static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
if (rc)
return rc;
- isec = msq->q_perm.security;
+ isec = lsm_get_ipc(&msq->q_perm, &selinux_ops);
ad.type = LSM_AUDIT_DATA_IPC;
ad.u.ipc_id = msq->q_perm.key;
@@ -4892,7 +4928,7 @@ static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)
struct common_audit_data ad;
u32 sid = current_sid();
- isec = msq->q_perm.security;
+ isec = lsm_get_ipc(&msq->q_perm, &selinux_ops);
ad.type = LSM_AUDIT_DATA_IPC;
ad.u.ipc_id = msq->q_perm.key;
@@ -4937,8 +4973,8 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg,
u32 sid = current_sid();
int rc;
- isec = msq->q_perm.security;
- msec = msg->security;
+ isec = lsm_get_ipc(&msq->q_perm, &selinux_ops);
+ msec = lsm_get_msg(msg, &selinux_ops);
/*
* First time through, need to assign label to the message
@@ -4982,8 +5018,8 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
u32 sid = task_sid(target);
int rc;
- isec = msq->q_perm.security;
- msec = msg->security;
+ isec = lsm_get_ipc(&msq->q_perm, &selinux_ops);
+ msec = lsm_get_msg(msg, &selinux_ops);
ad.type = LSM_AUDIT_DATA_IPC;
ad.u.ipc_id = msq->q_perm.key;
@@ -5008,7 +5044,7 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp)
if (rc)
return rc;
- isec = shp->shm_perm.security;
+ isec = lsm_get_ipc(&shp->shm_perm, &selinux_ops);
ad.type = LSM_AUDIT_DATA_IPC;
ad.u.ipc_id = shp->shm_perm.key;
@@ -5033,7 +5069,7 @@ static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)
struct common_audit_data ad;
u32 sid = current_sid();
- isec = shp->shm_perm.security;
+ isec = lsm_get_ipc(&shp->shm_perm, &selinux_ops);
ad.type = LSM_AUDIT_DATA_IPC;
ad.u.ipc_id = shp->shm_perm.key;
@@ -5100,7 +5136,7 @@ static int selinux_sem_alloc_security(struct sem_array *sma)
if (rc)
return rc;
- isec = sma->sem_perm.security;
+ isec = lsm_get_ipc(&sma->sem_perm, &selinux_ops);
ad.type = LSM_AUDIT_DATA_IPC;
ad.u.ipc_id = sma->sem_perm.key;
@@ -5125,7 +5161,7 @@ static int selinux_sem_associate(struct sem_array *sma, int semflg)
struct common_audit_data ad;
u32 sid = current_sid();
- isec = sma->sem_perm.security;
+ isec = lsm_get_ipc(&sma->sem_perm, &selinux_ops);
ad.type = LSM_AUDIT_DATA_IPC;
ad.u.ipc_id = sma->sem_perm.key;
@@ -5207,7 +5243,7 @@ static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
{
- struct ipc_security_struct *isec = ipcp->security;
+ struct ipc_security_struct *isec = lsm_get_ipc(ipcp, &selinux_ops);
*secid = isec->sid;
}
@@ -5232,7 +5268,7 @@ static int selinux_getprocattr(struct task_struct *p,
}
rcu_read_lock();
- __tsec = __task_cred(p)->security;
+ __tsec = lsm_get_cred(__task_cred(p), &selinux_ops);
if (!strcmp(name, "current"))
sid = __tsec->sid;
@@ -5341,7 +5377,7 @@ static int selinux_setprocattr(struct task_struct *p,
operation. See selinux_bprm_set_creds for the execve
checks and may_create for the file creation checks. The
operation will then fail if the context is not permitted. */
- tsec = new->security;
+ tsec = lsm_get_cred(new, &selinux_ops);
if (!strcmp(name, "exec")) {
tsec->exec_sid = sid;
} else if (!strcmp(name, "fscreate")) {
@@ -5455,21 +5491,21 @@ static int selinux_key_alloc(struct key *k, const struct cred *cred,
if (!ksec)
return -ENOMEM;
- tsec = cred->security;
+ tsec = lsm_get_cred(cred, &selinux_ops);
if (tsec->keycreate_sid)
ksec->sid = tsec->keycreate_sid;
else
ksec->sid = tsec->sid;
- k->security = ksec;
+ lsm_set_key(k, ksec, &selinux_ops);
return 0;
}
static void selinux_key_free(struct key *k)
{
- struct key_security_struct *ksec = k->security;
+ struct key_security_struct *ksec = lsm_get_key(k, &selinux_ops);
- k->security = NULL;
+ lsm_set_key(k, NULL, &selinux_ops);
kfree(ksec);
}
@@ -5490,14 +5526,14 @@ static int selinux_key_permission(key_ref_t key_ref,
sid = cred_sid(cred);
key = key_ref_to_ptr(key_ref);
- ksec = key->security;
+ ksec = lsm_get_key(key, &selinux_ops);
return avc_has_perm(sid, ksec->sid, SECCLASS_KEY, perm, NULL);
}
static int selinux_key_getsecurity(struct key *key, char **_buffer)
{
- struct key_security_struct *ksec = key->security;
+ struct key_security_struct *ksec = lsm_get_key(key, &selinux_ops);
char *context = NULL;
unsigned len;
int rc;
@@ -5511,7 +5547,7 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer)
#endif
-static struct security_operations selinux_ops = {
+struct security_operations selinux_ops = {
.name = "selinux",
.ptrace_access_check = selinux_ptrace_access_check,
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
index 26c7eee..1d1dd10 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -24,6 +24,7 @@
#include <linux/binfmts.h>
#include <linux/in.h>
#include <linux/spinlock.h>
+#include <linux/lsm.h>
#include "flask.h"
#include "avc.h"
@@ -115,5 +116,6 @@ struct key_security_struct {
};
extern unsigned int selinux_checkreqprot;
+extern struct security_operations selinux_ops;
#endif /* _SELINUX_OBJSEC_H_ */
diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h
index c220f31..1e4b4f2 100644
--- a/security/selinux/include/xfrm.h
+++ b/security/selinux/include/xfrm.h
@@ -31,7 +31,7 @@ static inline struct inode_security_struct *get_sock_isec(struct sock *sk)
if (!sk->sk_socket)
return NULL;
- return SOCK_INODE(sk->sk_socket)->i_security;
+ return lsm_get_inode(SOCK_INODE(sk->sk_socket), &selinux_ops);
}
#ifdef CONFIG_SECURITY_NETWORK_XFRM
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index 298e695..7f42abe 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -83,7 +83,7 @@ static int task_has_security(struct task_struct *tsk,
u32 sid = 0;
rcu_read_lock();
- tsec = __task_cred(tsk)->security;
+ tsec = lsm_get_cred(__task_cred(tsk), &selinux_ops);
if (tsec)
sid = tsec->sid;
rcu_read_unlock();
@@ -1264,7 +1264,7 @@ static int sel_make_bools(void)
if (len >= PAGE_SIZE)
goto out;
- isec = (struct inode_security_struct *)inode->i_security;
+ isec = lsm_get_inode(inode, &selinux_ops);
ret = security_genfs_sid("selinuxfs", page, SECCLASS_FILE, &sid);
if (ret)
goto out;
@@ -1831,7 +1831,7 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent)
goto err;
inode->i_ino = ++sel_last_ino;
- isec = (struct inode_security_struct *)inode->i_security;
+ isec = lsm_get_inode(inode, &selinux_ops);
isec->sid = SECINITSID_DEVNULL;
isec->sclass = SECCLASS_CHR_FILE;
isec->initialized = 1;
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c
index 48665ec..02979a3 100644
--- a/security/selinux/xfrm.c
+++ b/security/selinux/xfrm.c
@@ -198,7 +198,8 @@ static int selinux_xfrm_sec_ctx_alloc(struct xfrm_sec_ctx **ctxp,
struct xfrm_user_sec_ctx *uctx, u32 sid)
{
int rc = 0;
- const struct task_security_struct *tsec = current_security();
+ const struct task_security_struct *tsec =
+ lsm_get_cred(current_cred(), &selinux_ops);
struct xfrm_sec_ctx *ctx = NULL;
char *ctx_str = NULL;
u32 str_len;
@@ -334,7 +335,8 @@ void selinux_xfrm_policy_free(struct xfrm_sec_ctx *ctx)
*/
int selinux_xfrm_policy_delete(struct xfrm_sec_ctx *ctx)
{
- const struct task_security_struct *tsec = current_security();
+ const struct task_security_struct *tsec =
+ lsm_get_cred(current_cred(), &selinux_ops);
int rc = 0;
if (ctx) {
@@ -379,7 +381,8 @@ void selinux_xfrm_state_free(struct xfrm_state *x)
*/
int selinux_xfrm_state_delete(struct xfrm_state *x)
{
- const struct task_security_struct *tsec = current_security();
+ const struct task_security_struct *tsec =
+ lsm_get_cred(current_cred(), &selinux_ops);
struct xfrm_sec_ctx *ctx = x->security;
int rc = 0;
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 5/5] LSM: SELinux changes to allow LSM stacking
2012-09-05 2:09 [PATCH 5/5] LSM: SELinux changes to allow LSM stacking Casey Schaufler
@ 2012-09-05 14:38 ` Stephen Smalley
2012-09-05 15:35 ` Casey Schaufler
2012-09-06 13:08 ` Stephen Smalley
0 siblings, 2 replies; 5+ messages in thread
From: Stephen Smalley @ 2012-09-05 14:38 UTC (permalink / raw)
To: Casey Schaufler; +Cc: LSM, SE Linux, Eric Paris
On Tue, 2012-09-04 at 19:09 -0700, Casey Schaufler wrote:
> Subject: LSM: SELinux changes to allow LSM stacking
>
> Change security blob accesses to use the lsm_get/lsm_set
> interfaces. This requires removal of the cred pointer
> poisoning in selinux_cred_free.
>
> Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
FWIW, passes the selinux-testsuite with SELinux and Yama enabled.
--
Stephen Smalley
National Security Agency
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 5/5] LSM: SELinux changes to allow LSM stacking
2012-09-05 14:38 ` Stephen Smalley
@ 2012-09-05 15:35 ` Casey Schaufler
2012-09-06 13:08 ` Stephen Smalley
1 sibling, 0 replies; 5+ messages in thread
From: Casey Schaufler @ 2012-09-05 15:35 UTC (permalink / raw)
To: Stephen Smalley; +Cc: LSM, SE Linux, Eric Paris, Casey Schaufler
On 9/5/2012 7:38 AM, Stephen Smalley wrote:
> On Tue, 2012-09-04 at 19:09 -0700, Casey Schaufler wrote:
>> Subject: LSM: SELinux changes to allow LSM stacking
>>
>> Change security blob accesses to use the lsm_get/lsm_set
>> interfaces. This requires removal of the cred pointer
>> poisoning in selinux_cred_free.
>>
>> Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
> FWIW, passes the selinux-testsuite with SELinux and Yama enabled.
>
Thank you. I'm not at all surprised given the intent of Yama. I would be
much
more interested in the results with AppArmor and TOMOYO.
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 5/5] LSM: SELinux changes to allow LSM stacking
2012-09-05 14:38 ` Stephen Smalley
2012-09-05 15:35 ` Casey Schaufler
@ 2012-09-06 13:08 ` Stephen Smalley
2012-09-06 15:17 ` Casey Schaufler
1 sibling, 1 reply; 5+ messages in thread
From: Stephen Smalley @ 2012-09-06 13:08 UTC (permalink / raw)
To: Casey Schaufler; +Cc: LSM, SE Linux, Eric Paris
On Wed, 2012-09-05 at 10:38 -0400, Stephen Smalley wrote:
> On Tue, 2012-09-04 at 19:09 -0700, Casey Schaufler wrote:
> > Subject: LSM: SELinux changes to allow LSM stacking
> >
> > Change security blob accesses to use the lsm_get/lsm_set
> > interfaces. This requires removal of the cred pointer
> > poisoning in selinux_cred_free.
> >
> > Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
>
> FWIW, passes the selinux-testsuite with SELinux and Yama enabled.
However, setting SELINUX=disabled in /etc/selinux/config and rebooting
with this kernel yields a kernel panic during reset_security_ops(),
called by selinux_disable().
--
Stephen Smalley
National Security Agency
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 5/5] LSM: SELinux changes to allow LSM stacking
2012-09-06 13:08 ` Stephen Smalley
@ 2012-09-06 15:17 ` Casey Schaufler
0 siblings, 0 replies; 5+ messages in thread
From: Casey Schaufler @ 2012-09-06 15:17 UTC (permalink / raw)
To: Stephen Smalley; +Cc: LSM, SE Linux, Eric Paris, Casey Schaufler
On 9/6/2012 6:08 AM, Stephen Smalley wrote:
> On Wed, 2012-09-05 at 10:38 -0400, Stephen Smalley wrote:
>> On Tue, 2012-09-04 at 19:09 -0700, Casey Schaufler wrote:
>>> Subject: LSM: SELinux changes to allow LSM stacking
>>>
>>> Change security blob accesses to use the lsm_get/lsm_set
>>> interfaces. This requires removal of the cred pointer
>>> poisoning in selinux_cred_free.
>>>
>>> Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
>> FWIW, passes the selinux-testsuite with SELinux and Yama enabled.
> However, setting SELINUX=disabled in /etc/selinux/config and rebooting
> with this kernel yields a kernel panic during reset_security_ops(),
> called by selinux_disable().
>
reset_security_ops is only used by SELinux. There are a number of ways
to repair this. The important question is whether a general solution is
required or if it can be left SELinux specific. If it is a general
interface, does it clear all the LSMs or just the LSM calling it?
I would suggest that leaving it to SELinux is the best choice, and
clearing the calling LSM only the next best choice.
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2012-09-06 15:17 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-09-05 2:09 [PATCH 5/5] LSM: SELinux changes to allow LSM stacking Casey Schaufler
2012-09-05 14:38 ` Stephen Smalley
2012-09-05 15:35 ` Casey Schaufler
2012-09-06 13:08 ` Stephen Smalley
2012-09-06 15:17 ` Casey Schaufler
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.