Commit 275bb41e authored by David Howells's avatar David Howells Committed by James Morris

CRED: Wrap access to SELinux's task SID

Wrap access to SELinux's task SID, using task_sid() and current_sid() as
appropriate.
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
Acked-by: default avatarJames Morris <jmorris@namei.org>
Signed-off-by: default avatarJames Morris <jmorris@namei.org>
parent c69e8d9c
...@@ -172,10 +172,35 @@ static int cred_alloc_security(struct cred *cred) ...@@ -172,10 +172,35 @@ static int cred_alloc_security(struct cred *cred)
return 0; return 0;
} }
/*
* get the security ID of a task
*/
static inline u32 task_sid(const struct task_struct *task)
{
const struct task_security_struct *tsec;
u32 sid;
rcu_read_lock();
tsec = __task_cred(task)->security;
sid = tsec->sid;
rcu_read_unlock();
return sid;
}
/*
* get the security ID of the current task
*/
static inline u32 current_sid(void)
{
const struct task_security_struct *tsec = current_cred()->security;
return tsec->sid;
}
static int inode_alloc_security(struct inode *inode) static int inode_alloc_security(struct inode *inode)
{ {
struct task_security_struct *tsec = current->cred->security;
struct inode_security_struct *isec; struct inode_security_struct *isec;
u32 sid = current_sid();
isec = kmem_cache_zalloc(sel_inode_cache, GFP_NOFS); isec = kmem_cache_zalloc(sel_inode_cache, GFP_NOFS);
if (!isec) if (!isec)
...@@ -186,7 +211,7 @@ static int inode_alloc_security(struct inode *inode) ...@@ -186,7 +211,7 @@ static int inode_alloc_security(struct inode *inode)
isec->inode = inode; isec->inode = inode;
isec->sid = SECINITSID_UNLABELED; isec->sid = SECINITSID_UNLABELED;
isec->sclass = SECCLASS_FILE; isec->sclass = SECCLASS_FILE;
isec->task_sid = tsec->sid; isec->task_sid = sid;
inode->i_security = isec; inode->i_security = isec;
return 0; return 0;
...@@ -208,15 +233,15 @@ static void inode_free_security(struct inode *inode) ...@@ -208,15 +233,15 @@ static void inode_free_security(struct inode *inode)
static int file_alloc_security(struct file *file) static int file_alloc_security(struct file *file)
{ {
struct task_security_struct *tsec = current->cred->security;
struct file_security_struct *fsec; struct file_security_struct *fsec;
u32 sid = current_sid();
fsec = kzalloc(sizeof(struct file_security_struct), GFP_KERNEL); fsec = kzalloc(sizeof(struct file_security_struct), GFP_KERNEL);
if (!fsec) if (!fsec)
return -ENOMEM; return -ENOMEM;
fsec->sid = tsec->sid; fsec->sid = sid;
fsec->fown_sid = tsec->sid; fsec->fown_sid = sid;
file->f_security = fsec; file->f_security = fsec;
return 0; return 0;
...@@ -331,8 +356,9 @@ static const match_table_t tokens = { ...@@ -331,8 +356,9 @@ static const match_table_t tokens = {
static int may_context_mount_sb_relabel(u32 sid, static int may_context_mount_sb_relabel(u32 sid,
struct superblock_security_struct *sbsec, struct superblock_security_struct *sbsec,
struct task_security_struct *tsec) const struct cred *cred)
{ {
const struct task_security_struct *tsec = cred->security;
int rc; int rc;
rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM, rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
...@@ -347,8 +373,9 @@ static int may_context_mount_sb_relabel(u32 sid, ...@@ -347,8 +373,9 @@ static int may_context_mount_sb_relabel(u32 sid,
static int may_context_mount_inode_relabel(u32 sid, static int may_context_mount_inode_relabel(u32 sid,
struct superblock_security_struct *sbsec, struct superblock_security_struct *sbsec,
struct task_security_struct *tsec) const struct cred *cred)
{ {
const struct task_security_struct *tsec = cred->security;
int rc; int rc;
rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM, rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
FILESYSTEM__RELABELFROM, NULL); FILESYSTEM__RELABELFROM, NULL);
...@@ -546,8 +573,8 @@ static int bad_option(struct superblock_security_struct *sbsec, char flag, ...@@ -546,8 +573,8 @@ static int bad_option(struct superblock_security_struct *sbsec, char flag,
static int selinux_set_mnt_opts(struct super_block *sb, static int selinux_set_mnt_opts(struct super_block *sb,
struct security_mnt_opts *opts) struct security_mnt_opts *opts)
{ {
const struct cred *cred = current_cred();
int rc = 0, i; int rc = 0, i;
struct task_security_struct *tsec = current->cred->security;
struct superblock_security_struct *sbsec = sb->s_security; struct superblock_security_struct *sbsec = sb->s_security;
const char *name = sb->s_type->name; const char *name = sb->s_type->name;
struct inode *inode = sbsec->sb->s_root->d_inode; struct inode *inode = sbsec->sb->s_root->d_inode;
...@@ -673,8 +700,7 @@ static int selinux_set_mnt_opts(struct super_block *sb, ...@@ -673,8 +700,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
/* sets the context of the superblock for the fs being mounted. */ /* sets the context of the superblock for the fs being mounted. */
if (fscontext_sid) { if (fscontext_sid) {
rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, cred);
rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, tsec);
if (rc) if (rc)
goto out; goto out;
...@@ -688,12 +714,14 @@ static int selinux_set_mnt_opts(struct super_block *sb, ...@@ -688,12 +714,14 @@ static int selinux_set_mnt_opts(struct super_block *sb,
*/ */
if (context_sid) { if (context_sid) {
if (!fscontext_sid) { if (!fscontext_sid) {
rc = may_context_mount_sb_relabel(context_sid, sbsec, tsec); rc = may_context_mount_sb_relabel(context_sid, sbsec,
cred);
if (rc) if (rc)
goto out; goto out;
sbsec->sid = context_sid; sbsec->sid = context_sid;
} else { } else {
rc = may_context_mount_inode_relabel(context_sid, sbsec, tsec); rc = may_context_mount_inode_relabel(context_sid, sbsec,
cred);
if (rc) if (rc)
goto out; goto out;
} }
...@@ -705,7 +733,8 @@ static int selinux_set_mnt_opts(struct super_block *sb, ...@@ -705,7 +733,8 @@ static int selinux_set_mnt_opts(struct super_block *sb,
} }
if (rootcontext_sid) { if (rootcontext_sid) {
rc = may_context_mount_inode_relabel(rootcontext_sid, sbsec, tsec); rc = may_context_mount_inode_relabel(rootcontext_sid, sbsec,
cred);
if (rc) if (rc)
goto out; goto out;
...@@ -723,7 +752,7 @@ static int selinux_set_mnt_opts(struct super_block *sb, ...@@ -723,7 +752,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
if (defcontext_sid != sbsec->def_sid) { if (defcontext_sid != sbsec->def_sid) {
rc = may_context_mount_inode_relabel(defcontext_sid, rc = may_context_mount_inode_relabel(defcontext_sid,
sbsec, tsec); sbsec, cred);
if (rc) if (rc)
goto out; goto out;
} }
...@@ -1338,18 +1367,23 @@ static inline u32 signal_to_av(int sig) ...@@ -1338,18 +1367,23 @@ static inline u32 signal_to_av(int sig)
return perm; return perm;
} }
/* Check permission betweeen a pair of tasks, e.g. signal checks, /*
fork check, ptrace check, etc. */ * Check permission betweeen a pair of tasks, e.g. signal checks,
static int task_has_perm(struct task_struct *tsk1, * fork check, ptrace check, etc.
struct task_struct *tsk2, * tsk1 is the actor and tsk2 is the target
*/
static int task_has_perm(const struct task_struct *tsk1,
const struct task_struct *tsk2,
u32 perms) u32 perms)
{ {
struct task_security_struct *tsec1, *tsec2; const struct task_security_struct *__tsec1, *__tsec2;
u32 sid1, sid2;
tsec1 = tsk1->cred->security; rcu_read_lock();
tsec2 = tsk2->cred->security; __tsec1 = __task_cred(tsk1)->security; sid1 = __tsec1->sid;
return avc_has_perm(tsec1->sid, tsec2->sid, __tsec2 = __task_cred(tsk2)->security; sid2 = __tsec2->sid;
SECCLASS_PROCESS, perms, NULL); rcu_read_unlock();
return avc_has_perm(sid1, sid2, SECCLASS_PROCESS, perms, NULL);
} }
#if CAP_LAST_CAP > 63 #if CAP_LAST_CAP > 63
...@@ -1360,15 +1394,13 @@ static int task_has_perm(struct task_struct *tsk1, ...@@ -1360,15 +1394,13 @@ static int task_has_perm(struct task_struct *tsk1,
static int task_has_capability(struct task_struct *tsk, static int task_has_capability(struct task_struct *tsk,
int cap, int audit) int cap, int audit)
{ {
struct task_security_struct *tsec;
struct avc_audit_data ad; struct avc_audit_data ad;
struct av_decision avd; struct av_decision avd;
u16 sclass; u16 sclass;
u32 sid = task_sid(tsk);
u32 av = CAP_TO_MASK(cap); u32 av = CAP_TO_MASK(cap);
int rc; int rc;
tsec = tsk->cred->security;
AVC_AUDIT_DATA_INIT(&ad, CAP); AVC_AUDIT_DATA_INIT(&ad, CAP);
ad.tsk = tsk; ad.tsk = tsk;
ad.u.cap = cap; ad.u.cap = cap;
...@@ -1386,9 +1418,9 @@ static int task_has_capability(struct task_struct *tsk, ...@@ -1386,9 +1418,9 @@ static int task_has_capability(struct task_struct *tsk,
BUG(); BUG();
} }
rc = avc_has_perm_noaudit(tsec->sid, tsec->sid, sclass, av, 0, &avd); rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd);
if (audit == SECURITY_CAP_AUDIT) if (audit == SECURITY_CAP_AUDIT)
avc_audit(tsec->sid, tsec->sid, sclass, av, &avd, rc, &ad); avc_audit(sid, sid, sclass, av, &avd, rc, &ad);
return rc; return rc;
} }
...@@ -1396,11 +1428,9 @@ static int task_has_capability(struct task_struct *tsk, ...@@ -1396,11 +1428,9 @@ static int task_has_capability(struct task_struct *tsk,
static int task_has_system(struct task_struct *tsk, static int task_has_system(struct task_struct *tsk,
u32 perms) u32 perms)
{ {
struct task_security_struct *tsec; u32 sid = task_sid(tsk);
tsec = tsk->cred->security;
return avc_has_perm(tsec->sid, SECINITSID_KERNEL, return avc_has_perm(sid, SECINITSID_KERNEL,
SECCLASS_SYSTEM, perms, NULL); SECCLASS_SYSTEM, perms, NULL);
} }
...@@ -1412,14 +1442,14 @@ static int inode_has_perm(struct task_struct *tsk, ...@@ -1412,14 +1442,14 @@ static int inode_has_perm(struct task_struct *tsk,
u32 perms, u32 perms,
struct avc_audit_data *adp) struct avc_audit_data *adp)
{ {
struct task_security_struct *tsec;
struct inode_security_struct *isec; struct inode_security_struct *isec;
struct avc_audit_data ad; struct avc_audit_data ad;
u32 sid;
if (unlikely(IS_PRIVATE(inode))) if (unlikely(IS_PRIVATE(inode)))
return 0; return 0;
tsec = tsk->cred->security; sid = task_sid(tsk);
isec = inode->i_security; isec = inode->i_security;
if (!adp) { if (!adp) {
...@@ -1428,7 +1458,7 @@ static int inode_has_perm(struct task_struct *tsk, ...@@ -1428,7 +1458,7 @@ static int inode_has_perm(struct task_struct *tsk,
ad.u.fs.inode = inode; ad.u.fs.inode = inode;
} }
return avc_has_perm(tsec->sid, isec->sid, isec->sclass, perms, adp); return avc_has_perm(sid, isec->sid, isec->sclass, perms, adp);
} }
/* Same as inode_has_perm, but pass explicit audit data containing /* Same as inode_has_perm, but pass explicit audit data containing
...@@ -1459,17 +1489,17 @@ static int file_has_perm(struct task_struct *tsk, ...@@ -1459,17 +1489,17 @@ static int file_has_perm(struct task_struct *tsk,
struct file *file, struct file *file,
u32 av) u32 av)
{ {
struct task_security_struct *tsec = tsk->cred->security;
struct file_security_struct *fsec = file->f_security; struct file_security_struct *fsec = file->f_security;
struct inode *inode = file->f_path.dentry->d_inode; struct inode *inode = file->f_path.dentry->d_inode;
struct avc_audit_data ad; struct avc_audit_data ad;
u32 sid = task_sid(tsk);
int rc; int rc;
AVC_AUDIT_DATA_INIT(&ad, FS); AVC_AUDIT_DATA_INIT(&ad, FS);
ad.u.fs.path = file->f_path; ad.u.fs.path = file->f_path;
if (tsec->sid != fsec->sid) { if (sid != fsec->sid) {
rc = avc_has_perm(tsec->sid, fsec->sid, rc = avc_has_perm(sid, fsec->sid,
SECCLASS_FD, SECCLASS_FD,
FD__USE, FD__USE,
&ad); &ad);
...@@ -1489,36 +1519,36 @@ static int may_create(struct inode *dir, ...@@ -1489,36 +1519,36 @@ static int may_create(struct inode *dir,
struct dentry *dentry, struct dentry *dentry,
u16 tclass) u16 tclass)
{ {
struct task_security_struct *tsec; const struct cred *cred = current_cred();
const struct task_security_struct *tsec = cred->security;
struct inode_security_struct *dsec; struct inode_security_struct *dsec;
struct superblock_security_struct *sbsec; struct superblock_security_struct *sbsec;
u32 newsid; u32 sid, newsid;
struct avc_audit_data ad; struct avc_audit_data ad;
int rc; int rc;
tsec = current->cred->security;
dsec = dir->i_security; dsec = dir->i_security;
sbsec = dir->i_sb->s_security; sbsec = dir->i_sb->s_security;
sid = tsec->sid;
newsid = tsec->create_sid;
AVC_AUDIT_DATA_INIT(&ad, FS); AVC_AUDIT_DATA_INIT(&ad, FS);
ad.u.fs.path.dentry = dentry; ad.u.fs.path.dentry = dentry;
rc = avc_has_perm(tsec->sid, dsec->sid, SECCLASS_DIR, rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR,
DIR__ADD_NAME | DIR__SEARCH, DIR__ADD_NAME | DIR__SEARCH,
&ad); &ad);
if (rc) if (rc)
return rc; return rc;
if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) { if (!newsid || sbsec->behavior == SECURITY_FS_USE_MNTPOINT) {
newsid = tsec->create_sid; rc = security_transition_sid(sid, dsec->sid, tclass, &newsid);
} else {
rc = security_transition_sid(tsec->sid, dsec->sid, tclass,
&newsid);
if (rc) if (rc)
return rc; return rc;
} }
rc = avc_has_perm(tsec->sid, newsid, tclass, FILE__CREATE, &ad); rc = avc_has_perm(sid, newsid, tclass, FILE__CREATE, &ad);
if (rc) if (rc)
return rc; return rc;
...@@ -1531,11 +1561,9 @@ static int may_create(struct inode *dir, ...@@ -1531,11 +1561,9 @@ static int may_create(struct inode *dir,
static int may_create_key(u32 ksid, static int may_create_key(u32 ksid,
struct task_struct *ctx) struct task_struct *ctx)
{ {
struct task_security_struct *tsec; u32 sid = task_sid(ctx);
tsec = ctx->cred->security;
return avc_has_perm(tsec->sid, ksid, SECCLASS_KEY, KEY__CREATE, NULL); return avc_has_perm(sid, ksid, SECCLASS_KEY, KEY__CREATE, NULL);
} }
#define MAY_LINK 0 #define MAY_LINK 0
...@@ -1548,13 +1576,12 @@ static int may_link(struct inode *dir, ...@@ -1548,13 +1576,12 @@ static int may_link(struct inode *dir,
int kind) int kind)
{ {
struct task_security_struct *tsec;
struct inode_security_struct *dsec, *isec; struct inode_security_struct *dsec, *isec;
struct avc_audit_data ad; struct avc_audit_data ad;
u32 sid = current_sid();
u32 av; u32 av;
int rc; int rc;
tsec = current->cred->security;
dsec = dir->i_security; dsec = dir->i_security;
isec = dentry->d_inode->i_security; isec = dentry->d_inode->i_security;
...@@ -1563,7 +1590,7 @@ static int may_link(struct inode *dir, ...@@ -1563,7 +1590,7 @@ static int may_link(struct inode *dir,
av = DIR__SEARCH; av = DIR__SEARCH;
av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME); av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
rc = avc_has_perm(tsec->sid, dsec->sid, SECCLASS_DIR, av, &ad); rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, av, &ad);
if (rc) if (rc)
return rc; return rc;
...@@ -1583,7 +1610,7 @@ static int may_link(struct inode *dir, ...@@ -1583,7 +1610,7 @@ static int may_link(struct inode *dir,
return 0; return 0;
} }
rc = avc_has_perm(tsec->sid, isec->sid, isec->sclass, av, &ad); rc = avc_has_perm(sid, isec->sid, isec->sclass, av, &ad);
return rc; return rc;
} }
...@@ -1592,14 +1619,13 @@ static inline int may_rename(struct inode *old_dir, ...@@ -1592,14 +1619,13 @@ static inline int may_rename(struct inode *old_dir,
struct inode *new_dir, struct inode *new_dir,
struct dentry *new_dentry) struct dentry *new_dentry)
{ {
struct task_security_struct *tsec;
struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec; struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
struct avc_audit_data ad; struct avc_audit_data ad;
u32 sid = current_sid();
u32 av; u32 av;
int old_is_dir, new_is_dir; int old_is_dir, new_is_dir;
int rc; int rc;
tsec = current->cred->security;
old_dsec = old_dir->i_security; old_dsec = old_dir->i_security;
old_isec = old_dentry->d_inode->i_security; old_isec = old_dentry->d_inode->i_security;
old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode); old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
...@@ -1608,16 +1634,16 @@ static inline int may_rename(struct inode *old_dir, ...@@ -1608,16 +1634,16 @@ static inline int may_rename(struct inode *old_dir,
AVC_AUDIT_DATA_INIT(&ad, FS); AVC_AUDIT_DATA_INIT(&ad, FS);
ad.u.fs.path.dentry = old_dentry; ad.u.fs.path.dentry = old_dentry;
rc = avc_has_perm(tsec->sid, old_dsec->sid, SECCLASS_DIR, rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR,
DIR__REMOVE_NAME | DIR__SEARCH, &ad); DIR__REMOVE_NAME | DIR__SEARCH, &ad);
if (rc) if (rc)
return rc; return rc;
rc = avc_has_perm(tsec->sid, old_isec->sid, rc = avc_has_perm(sid, old_isec->sid,
old_isec->sclass, FILE__RENAME, &ad); old_isec->sclass, FILE__RENAME, &ad);
if (rc) if (rc)
return rc; return rc;
if (old_is_dir && new_dir != old_dir) { if (old_is_dir && new_dir != old_dir) {
rc = avc_has_perm(tsec->sid, old_isec->sid, rc = avc_has_perm(sid, old_isec->sid,
old_isec->sclass, DIR__REPARENT, &ad); old_isec->sclass, DIR__REPARENT, &ad);
if (rc) if (rc)
return rc; return rc;
...@@ -1627,13 +1653,13 @@ static inline int may_rename(struct inode *old_dir, ...@@ -1627,13 +1653,13 @@ static inline int may_rename(struct inode *old_dir,
av = DIR__ADD_NAME | DIR__SEARCH; av = DIR__ADD_NAME | DIR__SEARCH;
if (new_dentry->d_inode) if (new_dentry->d_inode)
av |= DIR__REMOVE_NAME; av |= DIR__REMOVE_NAME;
rc = avc_has_perm(tsec->sid, new_dsec->sid, SECCLASS_DIR, av, &ad); rc = avc_has_perm(sid, new_dsec->sid, SECCLASS_DIR, av, &ad);
if (rc) if (rc)
return rc; return rc;
if (new_dentry->d_inode) { if (new_dentry->d_inode) {
new_isec = new_dentry->d_inode->i_security; new_isec = new_dentry->d_inode->i_security;
new_is_dir = S_ISDIR(new_dentry->d_inode->i_mode); new_is_dir = S_ISDIR(new_dentry->d_inode->i_mode);
rc = avc_has_perm(tsec->sid, new_isec->sid, rc = avc_has_perm(sid, new_isec->sid,
new_isec->sclass, new_isec->sclass,
(new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad); (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad);
if (rc) if (rc)
...@@ -1649,13 +1675,11 @@ static int superblock_has_perm(struct task_struct *tsk, ...@@ -1649,13 +1675,11 @@ static int superblock_has_perm(struct task_struct *tsk,
u32 perms, u32 perms,
struct avc_audit_data *ad) struct avc_audit_data *ad)
{ {
struct task_security_struct *tsec;
struct superblock_security_struct *sbsec; struct superblock_security_struct *sbsec;
u32 sid = task_sid(tsk);
tsec = tsk->cred->security;
sbsec = sb->s_security; sbsec = sb->s_security;
return avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM, return avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad);
perms, ad);
} }
/* Convert a Linux mode and permission mask to an access vector. */ /* Convert a Linux mode and permission mask to an access vector. */
...@@ -1751,10 +1775,9 @@ static int selinux_ptrace_may_access(struct task_struct *child, ...@@ -1751,10 +1775,9 @@ static int selinux_ptrace_may_access(struct task_struct *child,
return rc; return rc;
if (mode == PTRACE_MODE_READ) { if (mode == PTRACE_MODE_READ) {
struct task_security_struct *tsec = current->cred->security; u32 sid = current_sid();
struct task_security_struct *csec = child->cred->security; u32 csid = task_sid(child);
return avc_has_perm(tsec->sid, csec->sid, return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ, NULL);
SECCLASS_FILE, FILE__READ, NULL);
} }
return task_has_perm(current, child, PROCESS__PTRACE); return task_has_perm(current, child, PROCESS__PTRACE);
...@@ -1859,15 +1882,14 @@ static int selinux_sysctl(ctl_table *table, int op) ...@@ -1859,15 +1882,14 @@ static int selinux_sysctl(ctl_table *table, int op)
{ {
int error = 0; int error = 0;
u32 av; u32 av;
struct task_security_struct *tsec; u32 tsid, sid;
u32 tsid;
int rc; int rc;
rc = secondary_ops->sysctl(table, op); rc = secondary_ops->sysctl(table, op);
if (rc) if (rc)
return rc; return rc;
tsec = current->cred->security; sid = current_sid();
rc = selinux_sysctl_get_sid(table, (op == 0001) ? rc = selinux_sysctl_get_sid(table, (op == 0001) ?
SECCLASS_DIR : SECCLASS_FILE, &tsid); SECCLASS_DIR : SECCLASS_FILE, &tsid);
...@@ -1879,7 +1901,7 @@ static int selinux_sysctl(ctl_table *table, int op) ...@@ -1879,7 +1901,7 @@ static int selinux_sysctl(ctl_table *table, int op)
/* The op values are "defined" in sysctl.c, thereby creating /* The op values are "defined" in sysctl.c, thereby creating
* a bad coupling between this module and sysctl.c */ * a bad coupling between this module and sysctl.c */
if (op == 001) { if (op == 001) {
error = avc_has_perm(tsec->sid, tsid, error = avc_has_perm(sid, tsid,
SECCLASS_DIR, DIR__SEARCH, NULL); SECCLASS_DIR, DIR__SEARCH, NULL);
} else { } else {
av = 0; av = 0;
...@@ -1888,7 +1910,7 @@ static int selinux_sysctl(ctl_table *table, int op) ...@@ -1888,7 +1910,7 @@ static int selinux_sysctl(ctl_table *table, int op)
if (op & 002) if (op & 002)
av |= FILE__WRITE; av |= FILE__WRITE;
if (av) if (av)
error = avc_has_perm(tsec->sid, tsid, error = avc_has_perm(sid, tsid,
SECCLASS_FILE, av, NULL); SECCLASS_FILE, av, NULL);
} }
...@@ -2018,7 +2040,7 @@ static int selinux_bprm_set_security(struct linux_binprm *bprm) ...@@ -2018,7 +2040,7 @@ static int selinux_bprm_set_security(struct linux_binprm *bprm)
if (bsec->set) if (bsec->set)
return 0; return 0;
tsec = current->cred->security; tsec = current_security();
isec = inode->i_security; isec = inode->i_security;
/* Default to the current task SID. */ /* Default to the current task SID. */
...@@ -2083,14 +2105,19 @@ static int selinux_bprm_check_security(struct linux_binprm *bprm) ...@@ -2083,14 +2105,19 @@ static int selinux_bprm_check_security(struct linux_binprm *bprm)
static int selinux_bprm_secureexec(struct linux_binprm *bprm) static int selinux_bprm_secureexec(struct linux_binprm *bprm)
{ {
struct task_security_struct *tsec = current->cred->security; const struct cred *cred = current_cred();
const struct task_security_struct *tsec = cred->security;
u32 sid, osid;
int atsecure = 0; int atsecure = 0;
if (tsec->osid != tsec->sid) { sid = tsec->sid;
osid = tsec->osid;
if (osid != sid) {
/* Enable secure mode for SIDs transitions unless /* Enable secure mode for SIDs transitions unless
the noatsecure permission is granted between the noatsecure permission is granted between
the two SIDs, i.e. ahp returns 0. */ the two SIDs, i.e. ahp returns 0. */
atsecure = avc_has_perm(tsec->osid, tsec->sid, atsecure = avc_has_perm(osid, sid,
SECCLASS_PROCESS, SECCLASS_PROCESS,
PROCESS__NOATSECURE, NULL); PROCESS__NOATSECURE, NULL);
} }
...@@ -2207,7 +2234,7 @@ static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe) ...@@ -2207,7 +2234,7 @@ static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe)
secondary_ops->bprm_apply_creds(bprm, unsafe); secondary_ops->bprm_apply_creds(bprm, unsafe);
tsec = current->cred->security; tsec = current_security();
bsec = bprm->security; bsec = bprm->security;
sid = bsec->sid; sid = bsec->sid;
...@@ -2236,7 +2263,7 @@ static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe) ...@@ -2236,7 +2263,7 @@ static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe)
rcu_read_lock(); rcu_read_lock();
tracer = tracehook_tracer_task(current); tracer = tracehook_tracer_task(current);
if (likely(tracer != NULL)) { if (likely(tracer != NULL)) {
sec = tracer->cred->security; sec = __task_cred(tracer)->security;
ptsid = sec->sid; ptsid = sec->sid;
} }
rcu_read_unlock(); rcu_read_unlock();
...@@ -2267,7 +2294,7 @@ static void selinux_bprm_post_apply_creds(struct linux_binprm *bprm) ...@@ -2267,7 +2294,7 @@ static void selinux_bprm_post_apply_creds(struct linux_binprm *bprm)
int rc, i; int rc, i;
unsigned long flags; unsigned long flags;
tsec = current->cred->security; tsec = current_security();
bsec = bprm->security; bsec = bprm->security;
if (bsec->unsafe) { if (bsec->unsafe) {
...@@ -2507,21 +2534,22 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, ...@@ -2507,21 +2534,22 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
char **name, void **value, char **name, void **value,
size_t *len) size_t *len)
{ {
struct task_security_struct *tsec; const struct cred *cred = current_cred();
const struct task_security_struct *tsec = cred->security;
struct inode_security_struct *dsec; struct inode_security_struct *dsec;
struct superblock_security_struct *sbsec; struct superblock_security_struct *sbsec;
u32 newsid, clen; u32 sid, newsid, clen;
int rc; int rc;
char *namep = NULL, *context; char *namep = NULL, *context;
tsec = current->cred->security;
dsec = dir->i_security; dsec = dir->i_security;
sbsec = dir->i_sb->s_security; sbsec = dir->i_sb->s_security;
if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) { sid = tsec->sid;
newsid = tsec->create_sid; newsid = tsec->create_sid;
} else {
rc = security_transition_sid(tsec->sid, dsec->sid, if (!newsid || sbsec->behavior == SECURITY_FS_USE_MNTPOINT) {
rc = security_transition_sid(sid, dsec->sid,
inode_mode_to_security_class(inode->i_mode), inode_mode_to_security_class(inode->i_mode),
&newsid); &newsid);
if (rc) { if (rc) {
...@@ -2699,12 +2727,11 @@ static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name) ...@@ -2699,12 +2727,11 @@ static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name)
static int selinux_inode_setxattr(struct dentry *dentry, const char *name, static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags) const void *value, size_t size, int flags)
{ {
struct task_security_struct *tsec = current->cred->security;
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
struct inode_security_struct *isec = inode->i_security; struct inode_security_struct *isec = inode->i_security;
struct superblock_security_struct *sbsec; struct superblock_security_struct *sbsec;
struct avc_audit_data ad; struct avc_audit_data ad;
u32 newsid; u32 newsid, sid = current_sid();
int rc = 0; int rc = 0;
if (strcmp(name, XATTR_NAME_SELINUX)) if (strcmp(name, XATTR_NAME_SELINUX))
...@@ -2720,7 +2747,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name, ...@@ -2720,7 +2747,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
AVC_AUDIT_DATA_INIT(&ad, FS); AVC_AUDIT_DATA_INIT(&ad, FS);
ad.u.fs.path.dentry = dentry; ad.u.fs.path.dentry = dentry;
rc = avc_has_perm(tsec->sid, isec->sid, isec->sclass, rc = avc_has_perm(sid, isec->sid, isec->sclass,
FILE__RELABELFROM, &ad); FILE__RELABELFROM, &ad);
if (rc) if (rc)
return rc; return rc;
...@@ -2734,12 +2761,12 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name, ...@@ -2734,12 +2761,12 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
if (rc) if (rc)
return rc; return rc;
rc = avc_has_perm(tsec->sid, newsid, isec->sclass, rc = avc_has_perm(sid, newsid, isec->sclass,
FILE__RELABELTO, &ad); FILE__RELABELTO, &ad);
if (rc) if (rc)
return rc; return rc;
rc = security_validate_transition(isec->sid, newsid, tsec->sid, rc = security_validate_transition(isec->sid, newsid, sid,
isec->sclass); isec->sclass);
if (rc) if (rc)
return rc; return rc;
...@@ -2911,16 +2938,16 @@ static int selinux_revalidate_file_permission(struct file *file, int mask) ...@@ -2911,16 +2938,16 @@ static int selinux_revalidate_file_permission(struct file *file, int mask)
static int selinux_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 inode *inode = file->f_path.dentry->d_inode;
struct task_security_struct *tsec = current->cred->security;
struct file_security_struct *fsec = file->f_security; struct file_security_struct *fsec = file->f_security;
struct inode_security_struct *isec = inode->i_security; struct inode_security_struct *isec = inode->i_security;
u32 sid = current_sid();
if (!mask) { if (!mask) {
/* No permission to check. Existence test. */ /* No permission to check. Existence test. */
return 0; return 0;
} }
if (tsec->sid == fsec->sid && fsec->isid == isec->sid if (sid == fsec->sid && fsec->isid == isec->sid
&& fsec->pseqno == avc_policy_seqno()) && fsec->pseqno == avc_policy_seqno())
return selinux_netlbl_inode_permission(inode, mask); return selinux_netlbl_inode_permission(inode, mask);
...@@ -2988,8 +3015,7 @@ static int selinux_file_mmap(struct file *file, unsigned long reqprot, ...@@ -2988,8 +3015,7 @@ static int selinux_file_mmap(struct file *file, unsigned long reqprot,
unsigned long addr, unsigned long addr_only) unsigned long addr, unsigned long addr_only)
{ {
int rc = 0; int rc = 0;
u32 sid = ((struct task_security_struct *) u32 sid = current_sid();
(current->cred->security))->sid;
if (addr < mmap_min_addr) if (addr < mmap_min_addr)
rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT, rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
...@@ -3098,12 +3124,10 @@ static int selinux_file_fcntl(struct file *file, unsigned int cmd, ...@@ -3098,12 +3124,10 @@ static int selinux_file_fcntl(struct file *file, unsigned int cmd,
static int selinux_file_set_fowner(struct file *file) static int selinux_file_set_fowner(struct file *file)
{ {
struct task_security_struct *tsec;
struct file_security_struct *fsec; struct file_security_struct *fsec;
tsec = current->cred->security;
fsec = file->f_security; fsec = file->f_security;
fsec->fown_sid = tsec->sid; fsec->fown_sid = current_sid();
return 0; return 0;
} }
...@@ -3112,14 +3136,13 @@ static int selinux_file_send_sigiotask(struct task_struct *tsk, ...@@ -3112,14 +3136,13 @@ static int selinux_file_send_sigiotask(struct task_struct *tsk,
struct fown_struct *fown, int signum) struct fown_struct *fown, int signum)
{ {
struct file *file; struct file *file;
u32 sid = current_sid();
u32 perm; u32 perm;
struct task_security_struct *tsec;
struct file_security_struct *fsec; struct file_security_struct *fsec;
/* struct fown_struct is never outside the context of a struct file */ /* struct fown_struct is never outside the context of a struct file */
file = container_of(fown, struct file, f_owner); file = container_of(fown, struct file, f_owner);
tsec = tsk->cred->security;
fsec = file->f_security; fsec = file->f_security;
if (!signum) if (!signum)
...@@ -3127,7 +3150,7 @@ static int selinux_file_send_sigiotask(struct task_struct *tsk, ...@@ -3127,7 +3150,7 @@ static int selinux_file_send_sigiotask(struct task_struct *tsk,
else else
perm = signal_to_av(signum); perm = signal_to_av(signum);
return avc_has_perm(fsec->fown_sid, tsec->sid, return avc_has_perm(fsec->fown_sid, sid,
SECCLASS_PROCESS, perm, NULL); SECCLASS_PROCESS, perm, NULL);
} }
...@@ -3182,7 +3205,7 @@ static int selinux_cred_alloc_security(struct cred *cred) ...@@ -3182,7 +3205,7 @@ static int selinux_cred_alloc_security(struct cred *cred)
struct task_security_struct *tsec1, *tsec2; struct task_security_struct *tsec1, *tsec2;
int rc; int rc;
tsec1 = current->cred->security; tsec1 = current_security();
rc = cred_alloc_security(cred); rc = cred_alloc_security(cred);
if (rc) if (rc)
...@@ -3250,8 +3273,7 @@ static int selinux_task_getsid(struct task_struct *p) ...@@ -3250,8 +3273,7 @@ static int selinux_task_getsid(struct task_struct *p)
static void selinux_task_getsecid(struct task_struct *p, u32 *secid) static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
{ {
struct task_security_struct *tsec = p->cred->security; *secid = task_sid(p);
*secid = tsec->sid;
} }
static int selinux_task_setgroups(struct group_info *group_info) static int selinux_task_setgroups(struct group_info *group_info)
...@@ -3332,7 +3354,6 @@ static int selinux_task_kill(struct task_struct *p, struct siginfo *info, ...@@ -3332,7 +3354,6 @@ static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
{ {
u32 perm; u32 perm;
int rc; int rc;
struct task_security_struct *tsec;
rc = secondary_ops->task_kill(p, info, sig, secid); rc = secondary_ops->task_kill(p, info, sig, secid);
if (rc) if (rc)
...@@ -3342,9 +3363,9 @@ static int selinux_task_kill(struct task_struct *p, struct siginfo *info, ...@@ -3342,9 +3363,9 @@ static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
perm = PROCESS__SIGNULL; /* null signal; existence test */ perm = PROCESS__SIGNULL; /* null signal; existence test */
else else
perm = signal_to_av(sig); perm = signal_to_av(sig);
tsec = p->cred->security;
if (secid) if (secid)
rc = avc_has_perm(secid, tsec->sid, SECCLASS_PROCESS, perm, NULL); rc = avc_has_perm(secid, task_sid(p),
SECCLASS_PROCESS, perm, NULL);
else else
rc = task_has_perm(current, p, perm); rc = task_has_perm(current, p, perm);
return rc; return rc;
...@@ -3383,12 +3404,11 @@ static void selinux_task_reparent_to_init(struct task_struct *p) ...@@ -3383,12 +3404,11 @@ static void selinux_task_reparent_to_init(struct task_struct *p)
static void selinux_task_to_inode(struct task_struct *p, static void selinux_task_to_inode(struct task_struct *p,
struct inode *inode) struct inode *inode)
{ {
struct task_security_struct *tsec = p->cred->security;
struct inode_security_struct *isec = inode->i_security; struct inode_security_struct *isec = inode->i_security;
u32 sid = task_sid(p);
isec->sid = tsec->sid; isec->sid = sid;
isec->initialized = 1; isec->initialized = 1;
return;
} }
/* Returns error only if unable to parse addresses */ /* Returns error only if unable to parse addresses */
...@@ -3627,19 +3647,19 @@ static int socket_has_perm(struct task_struct *task, struct socket *sock, ...@@ -3627,19 +3647,19 @@ static int socket_has_perm(struct task_struct *task, struct socket *sock,
u32 perms) u32 perms)
{ {
struct inode_security_struct *isec; struct inode_security_struct *isec;
struct task_security_struct *tsec;
struct avc_audit_data ad; struct avc_audit_data ad;
u32 sid;
int err = 0; int err = 0;
tsec = task->cred->security;
isec = SOCK_INODE(sock)->i_security; isec = SOCK_INODE(sock)->i_security;
if (isec->sid == SECINITSID_KERNEL) if (isec->sid == SECINITSID_KERNEL)
goto out; goto out;
sid = task_sid(task);
AVC_AUDIT_DATA_INIT(&ad, NET); AVC_AUDIT_DATA_INIT(&ad, NET);
ad.u.net.sk = sock->sk; ad.u.net.sk = sock->sk;
err = avc_has_perm(tsec->sid, isec->sid, isec->sclass, perms, &ad); err = avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad);
out: out:
return err; return err;
...@@ -3648,18 +3668,20 @@ static int socket_has_perm(struct task_struct *task, struct socket *sock, ...@@ -3648,18 +3668,20 @@ static int socket_has_perm(struct task_struct *task, struct socket *sock,
static int selinux_socket_create(int family, int type, static int selinux_socket_create(int family, int type,
int protocol, int kern) int protocol, int kern)
{ {
const struct cred *cred = current_cred();
const struct task_security_struct *tsec = cred->security;
u32 sid, newsid;
u16 secclass;
int err = 0; int err = 0;
struct task_security_struct *tsec;
u32 newsid;
if (kern) if (kern)
goto out; goto out;
tsec = current->cred->security; sid = tsec->sid;
newsid = tsec->sockcreate_sid ? : tsec->sid; newsid = tsec->sockcreate_sid ?: sid;
err = avc_has_perm(tsec->sid, newsid,
socket_type_to_security_class(family, type, secclass = socket_type_to_security_class(family, type, protocol);
protocol), SOCKET__CREATE, NULL); err = avc_has_perm(sid, newsid, secclass, SOCKET__CREATE, NULL);
out: out:
return err; return err;
...@@ -3668,18 +3690,26 @@ static int selinux_socket_create(int family, int type, ...@@ -3668,18 +3690,26 @@ static int selinux_socket_create(int family, int type,
static int selinux_socket_post_create(struct socket *sock, int family, static int selinux_socket_post_create(struct socket *sock, int family,
int type, int protocol, int kern) int type, int protocol, int kern)
{ {
int err = 0; const struct cred *cred = current_cred();
const struct task_security_struct *tsec = cred->security;
struct inode_security_struct *isec; struct inode_security_struct *isec;
struct task_security_struct *tsec;
struct sk_security_struct *sksec; struct sk_security_struct *sksec;
u32 newsid; u32 sid, newsid;
int err = 0;
sid = tsec->sid;
newsid = tsec->sockcreate_sid;
isec = SOCK_INODE(sock)->i_security; isec = SOCK_INODE(sock)->i_security;
tsec = current->cred->security; if (kern)
newsid = tsec->sockcreate_sid ? : tsec->sid; isec->sid = SECINITSID_KERNEL;
else if (newsid)
isec->sid = newsid;
else
isec->sid = sid;
isec->sclass = socket_type_to_security_class(family, type, protocol); isec->sclass = socket_type_to_security_class(family, type, protocol);
isec->sid = kern ? SECINITSID_KERNEL : newsid;
isec->initialized = 1; isec->initialized = 1;
if (sock->sk) { if (sock->sk) {
...@@ -3714,7 +3744,6 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in ...@@ -3714,7 +3744,6 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
if (family == PF_INET || family == PF_INET6) { if (family == PF_INET || family == PF_INET6) {
char *addrp; char *addrp;
struct inode_security_struct *isec; struct inode_security_struct *isec;
struct task_security_struct *tsec;
struct avc_audit_data ad; struct avc_audit_data ad;
struct sockaddr_in *addr4 = NULL; struct sockaddr_in *addr4 = NULL;
struct sockaddr_in6 *addr6 = NULL; struct sockaddr_in6 *addr6 = NULL;
...@@ -3722,7 +3751,6 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in ...@@ -3722,7 +3751,6 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
u32 sid, node_perm; u32 sid, node_perm;
tsec = current->cred->security;
isec = SOCK_INODE(sock)->i_security; isec = SOCK_INODE(sock)->i_security;
if (family == PF_INET) { if (family == PF_INET) {
...@@ -4763,15 +4791,16 @@ static int ipc_alloc_security(struct task_struct *task, ...@@ -4763,15 +4791,16 @@ static int ipc_alloc_security(struct task_struct *task,
struct kern_ipc_perm *perm, struct kern_ipc_perm *perm,
u16 sclass) u16 sclass)
{ {
struct task_security_struct *tsec = task->cred->security;
struct ipc_security_struct *isec; struct ipc_security_struct *isec;
u32 sid;
isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL); isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
if (!isec) if (!isec)
return -ENOMEM; return -ENOMEM;
sid = task_sid(task);
isec->sclass = sclass; isec->sclass = sclass;
isec->sid = tsec->sid; isec->sid = sid;
perm->security = isec; perm->security = isec;
return 0; return 0;
...@@ -4809,17 +4838,16 @@ static void msg_msg_free_security(struct msg_msg *msg) ...@@ -4809,17 +4838,16 @@ static void msg_msg_free_security(struct msg_msg *msg)
static int ipc_has_perm(struct kern_ipc_perm *ipc_perms, static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
u32 perms) u32 perms)
{ {
struct task_security_struct *tsec;
struct ipc_security_struct *isec; struct ipc_security_struct *isec;
struct avc_audit_data ad; struct avc_audit_data ad;
u32 sid = current_sid();
tsec = current->cred->security;
isec = ipc_perms->security; isec = ipc_perms->security;
AVC_AUDIT_DATA_INIT(&ad, IPC); AVC_AUDIT_DATA_INIT(&ad, IPC);
ad.u.ipc_id = ipc_perms->key; ad.u.ipc_id = ipc_perms->key;
return avc_has_perm(tsec->sid, isec->sid, isec->sclass, perms, &ad); return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad);
} }
static int selinux_msg_msg_alloc_security(struct msg_msg *msg) static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
...@@ -4835,22 +4863,21 @@ static void selinux_msg_msg_free_security(struct msg_msg *msg) ...@@ -4835,22 +4863,21 @@ static void selinux_msg_msg_free_security(struct msg_msg *msg)
/* message queue security operations */ /* message queue security operations */
static int selinux_msg_queue_alloc_security(struct msg_queue *msq) static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
{ {
struct task_security_struct *tsec;
struct ipc_security_struct *isec; struct ipc_security_struct *isec;
struct avc_audit_data ad; struct avc_audit_data ad;
u32 sid = current_sid();
int rc; int rc;
rc = ipc_alloc_security(current, &msq->q_perm, SECCLASS_MSGQ); rc = ipc_alloc_security(current, &msq->q_perm, SECCLASS_MSGQ);
if (rc) if (rc)
return rc; return rc;
tsec = current->cred->security;
isec = msq->q_perm.security; isec = msq->q_perm.security;
AVC_AUDIT_DATA_INIT(&ad, IPC); AVC_AUDIT_DATA_INIT(&ad, IPC);
ad.u.ipc_id = msq->q_perm.key; ad.u.ipc_id = msq->q_perm.key;
rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_MSGQ, rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
MSGQ__CREATE, &ad); MSGQ__CREATE, &ad);
if (rc) { if (rc) {
ipc_free_security(&msq->q_perm); ipc_free_security(&msq->q_perm);
...@@ -4866,17 +4893,16 @@ static void selinux_msg_queue_free_security(struct msg_queue *msq) ...@@ -4866,17 +4893,16 @@ static void selinux_msg_queue_free_security(struct msg_queue *msq)
static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg) static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)
{ {
struct task_security_struct *tsec;
struct ipc_security_struct *isec; struct ipc_security_struct *isec;
struct avc_audit_data ad; struct avc_audit_data ad;
u32 sid = current_sid();
tsec = current->cred->security;
isec = msq->q_perm.security; isec = msq->q_perm.security;
AVC_AUDIT_DATA_INIT(&ad, IPC); AVC_AUDIT_DATA_INIT(&ad, IPC);
ad.u.ipc_id = msq->q_perm.key; ad.u.ipc_id = msq->q_perm.key;
return avc_has_perm(tsec->sid, isec->sid, SECCLASS_MSGQ, return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
MSGQ__ASSOCIATE, &ad); MSGQ__ASSOCIATE, &ad);
} }
...@@ -4910,13 +4936,12 @@ static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd) ...@@ -4910,13 +4936,12 @@ static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd)
static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, int msqflg) static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, int msqflg)
{ {
struct task_security_struct *tsec;
struct ipc_security_struct *isec; struct ipc_security_struct *isec;
struct msg_security_struct *msec; struct msg_security_struct *msec;
struct avc_audit_data ad; struct avc_audit_data ad;
u32 sid = current_sid();
int rc; int rc;
tsec = current->cred->security;
isec = msq->q_perm.security; isec = msq->q_perm.security;
msec = msg->security; msec = msg->security;
...@@ -4928,9 +4953,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, ...@@ -4928,9 +4953,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg,
* Compute new sid based on current process and * Compute new sid based on current process and
* message queue this message will be stored in * message queue this message will be stored in
*/ */
rc = security_transition_sid(tsec->sid, rc = security_transition_sid(sid, isec->sid, SECCLASS_MSG,
isec->sid,
SECCLASS_MSG,
&msec->sid); &msec->sid);
if (rc) if (rc)
return rc; return rc;
...@@ -4940,16 +4963,16 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, ...@@ -4940,16 +4963,16 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg,
ad.u.ipc_id = msq->q_perm.key; ad.u.ipc_id = msq->q_perm.key;
/* Can this process write to the queue? */ /* Can this process write to the queue? */
rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_MSGQ, rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
MSGQ__WRITE, &ad); MSGQ__WRITE, &ad);
if (!rc) if (!rc)
/* Can this process send the message */ /* Can this process send the message */
rc = avc_has_perm(tsec->sid, msec->sid, rc = avc_has_perm(sid, msec->sid, SECCLASS_MSG,
SECCLASS_MSG, MSG__SEND, &ad); MSG__SEND, &ad);
if (!rc) if (!rc)
/* Can the message be put in the queue? */ /* Can the message be put in the queue? */
rc = avc_has_perm(msec->sid, isec->sid, rc = avc_has_perm(msec->sid, isec->sid, SECCLASS_MSGQ,
SECCLASS_MSGQ, MSGQ__ENQUEUE, &ad); MSGQ__ENQUEUE, &ad);
return rc; return rc;
} }
...@@ -4958,23 +4981,22 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, ...@@ -4958,23 +4981,22 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
struct task_struct *target, struct task_struct *target,
long type, int mode) long type, int mode)
{ {
struct task_security_struct *tsec;
struct ipc_security_struct *isec; struct ipc_security_struct *isec;
struct msg_security_struct *msec; struct msg_security_struct *msec;
struct avc_audit_data ad; struct avc_audit_data ad;
u32 sid = task_sid(target);
int rc; int rc;
tsec = target->cred->security;
isec = msq->q_perm.security; isec = msq->q_perm.security;
msec = msg->security; msec = msg->security;
AVC_AUDIT_DATA_INIT(&ad, IPC); AVC_AUDIT_DATA_INIT(&ad, IPC);
ad.u.ipc_id = msq->q_perm.key; ad.u.ipc_id = msq->q_perm.key;
rc = avc_has_perm(tsec->sid, isec->sid, rc = avc_has_perm(sid, isec->sid,
SECCLASS_MSGQ, MSGQ__READ, &ad); SECCLASS_MSGQ, MSGQ__READ, &ad);
if (!rc) if (!rc)
rc = avc_has_perm(tsec->sid, msec->sid, rc = avc_has_perm(sid, msec->sid,
SECCLASS_MSG, MSG__RECEIVE, &ad); SECCLASS_MSG, MSG__RECEIVE, &ad);
return rc; return rc;
} }
...@@ -4982,22 +5004,21 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, ...@@ -4982,22 +5004,21 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
/* Shared Memory security operations */ /* Shared Memory security operations */
static int selinux_shm_alloc_security(struct shmid_kernel *shp) static int selinux_shm_alloc_security(struct shmid_kernel *shp)
{ {
struct task_security_struct *tsec;
struct ipc_security_struct *isec; struct ipc_security_struct *isec;
struct avc_audit_data ad; struct avc_audit_data ad;
u32 sid = current_sid();
int rc; int rc;
rc = ipc_alloc_security(current, &shp->shm_perm, SECCLASS_SHM); rc = ipc_alloc_security(current, &shp->shm_perm, SECCLASS_SHM);
if (rc) if (rc)
return rc; return rc;
tsec = current->cred->security;
isec = shp->shm_perm.security; isec = shp->shm_perm.security;
AVC_AUDIT_DATA_INIT(&ad, IPC); AVC_AUDIT_DATA_INIT(&ad, IPC);
ad.u.ipc_id = shp->shm_perm.key; ad.u.ipc_id = shp->shm_perm.key;
rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_SHM, rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM,
SHM__CREATE, &ad); SHM__CREATE, &ad);
if (rc) { if (rc) {
ipc_free_security(&shp->shm_perm); ipc_free_security(&shp->shm_perm);
...@@ -5013,17 +5034,16 @@ static void selinux_shm_free_security(struct shmid_kernel *shp) ...@@ -5013,17 +5034,16 @@ static void selinux_shm_free_security(struct shmid_kernel *shp)
static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg) static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)
{ {
struct task_security_struct *tsec;
struct ipc_security_struct *isec; struct ipc_security_struct *isec;
struct avc_audit_data ad; struct avc_audit_data ad;
u32 sid = current_sid();
tsec = current->cred->security;
isec = shp->shm_perm.security; isec = shp->shm_perm.security;
AVC_AUDIT_DATA_INIT(&ad, IPC); AVC_AUDIT_DATA_INIT(&ad, IPC);
ad.u.ipc_id = shp->shm_perm.key; ad.u.ipc_id = shp->shm_perm.key;
return avc_has_perm(tsec->sid, isec->sid, SECCLASS_SHM, return avc_has_perm(sid, isec->sid, SECCLASS_SHM,
SHM__ASSOCIATE, &ad); SHM__ASSOCIATE, &ad);
} }
...@@ -5081,22 +5101,21 @@ static int selinux_shm_shmat(struct shmid_kernel *shp, ...@@ -5081,22 +5101,21 @@ static int selinux_shm_shmat(struct shmid_kernel *shp,
/* Semaphore security operations */ /* Semaphore security operations */
static int selinux_sem_alloc_security(struct sem_array *sma) static int selinux_sem_alloc_security(struct sem_array *sma)
{ {
struct task_security_struct *tsec;
struct ipc_security_struct *isec; struct ipc_security_struct *isec;
struct avc_audit_data ad; struct avc_audit_data ad;
u32 sid = current_sid();
int rc; int rc;
rc = ipc_alloc_security(current, &sma->sem_perm, SECCLASS_SEM); rc = ipc_alloc_security(current, &sma->sem_perm, SECCLASS_SEM);
if (rc) if (rc)
return rc; return rc;
tsec = current->cred->security;
isec = sma->sem_perm.security; isec = sma->sem_perm.security;
AVC_AUDIT_DATA_INIT(&ad, IPC); AVC_AUDIT_DATA_INIT(&ad, IPC);
ad.u.ipc_id = sma->sem_perm.key; ad.u.ipc_id = sma->sem_perm.key;
rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_SEM, rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM,
SEM__CREATE, &ad); SEM__CREATE, &ad);
if (rc) { if (rc) {
ipc_free_security(&sma->sem_perm); ipc_free_security(&sma->sem_perm);
...@@ -5112,17 +5131,16 @@ static void selinux_sem_free_security(struct sem_array *sma) ...@@ -5112,17 +5131,16 @@ static void selinux_sem_free_security(struct sem_array *sma)
static int selinux_sem_associate(struct sem_array *sma, int semflg) static int selinux_sem_associate(struct sem_array *sma, int semflg)
{ {
struct task_security_struct *tsec;
struct ipc_security_struct *isec; struct ipc_security_struct *isec;
struct avc_audit_data ad; struct avc_audit_data ad;
u32 sid = current_sid();
tsec = current->cred->security;
isec = sma->sem_perm.security; isec = sma->sem_perm.security;
AVC_AUDIT_DATA_INIT(&ad, IPC); AVC_AUDIT_DATA_INIT(&ad, IPC);
ad.u.ipc_id = sma->sem_perm.key; ad.u.ipc_id = sma->sem_perm.key;
return avc_has_perm(tsec->sid, isec->sid, SECCLASS_SEM, return avc_has_perm(sid, isec->sid, SECCLASS_SEM,
SEM__ASSOCIATE, &ad); SEM__ASSOCIATE, &ad);
} }
...@@ -5212,7 +5230,7 @@ static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode) ...@@ -5212,7 +5230,7 @@ static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
static int selinux_getprocattr(struct task_struct *p, static int selinux_getprocattr(struct task_struct *p,
char *name, char **value) char *name, char **value)
{ {
struct task_security_struct *tsec; const struct task_security_struct *__tsec;
u32 sid; u32 sid;
int error; int error;
unsigned len; unsigned len;
...@@ -5223,22 +5241,24 @@ static int selinux_getprocattr(struct task_struct *p, ...@@ -5223,22 +5241,24 @@ static int selinux_getprocattr(struct task_struct *p,
return error; return error;
} }
tsec = p->cred->security; rcu_read_lock();
__tsec = __task_cred(p)->security;
if (!strcmp(name, "current")) if (!strcmp(name, "current"))
sid = tsec->sid; sid = __tsec->sid;
else if (!strcmp(name, "prev")) else if (!strcmp(name, "prev"))
sid = tsec->osid; sid = __tsec->osid;
else if (!strcmp(name, "exec")) else if (!strcmp(name, "exec"))
sid = tsec->exec_sid; sid = __tsec->exec_sid;
else if (!strcmp(name, "fscreate")) else if (!strcmp(name, "fscreate"))
sid = tsec->create_sid; sid = __tsec->create_sid;
else if (!strcmp(name, "keycreate")) else if (!strcmp(name, "keycreate"))
sid = tsec->keycreate_sid; sid = __tsec->keycreate_sid;
else if (!strcmp(name, "sockcreate")) else if (!strcmp(name, "sockcreate"))
sid = tsec->sockcreate_sid; sid = __tsec->sockcreate_sid;
else else
return -EINVAL; goto invalid;
rcu_read_unlock();
if (!sid) if (!sid)
return 0; return 0;
...@@ -5247,6 +5267,10 @@ static int selinux_getprocattr(struct task_struct *p, ...@@ -5247,6 +5267,10 @@ static int selinux_getprocattr(struct task_struct *p,
if (error) if (error)
return error; return error;
return len; return len;
invalid:
rcu_read_unlock();
return -EINVAL;
} }
static int selinux_setprocattr(struct task_struct *p, static int selinux_setprocattr(struct task_struct *p,
...@@ -5360,9 +5384,7 @@ static int selinux_setprocattr(struct task_struct *p, ...@@ -5360,9 +5384,7 @@ static int selinux_setprocattr(struct task_struct *p,
rcu_read_lock(); rcu_read_lock();
tracer = tracehook_tracer_task(p); tracer = tracehook_tracer_task(p);
if (tracer != NULL) { if (tracer != NULL) {
struct task_security_struct *ptsec = u32 ptsid = task_sid(tracer);
tracer->cred->security;
u32 ptsid = ptsec->sid;
rcu_read_unlock(); rcu_read_unlock();
error = avc_has_perm_noaudit(ptsid, sid, error = avc_has_perm_noaudit(ptsid, sid,
SECCLASS_PROCESS, SECCLASS_PROCESS,
...@@ -5405,19 +5427,22 @@ static void selinux_release_secctx(char *secdata, u32 seclen) ...@@ -5405,19 +5427,22 @@ static void selinux_release_secctx(char *secdata, u32 seclen)
static int selinux_key_alloc(struct key *k, struct task_struct *tsk, static int selinux_key_alloc(struct key *k, struct task_struct *tsk,
unsigned long flags) unsigned long flags)
{ {
struct task_security_struct *tsec = tsk->cred->security; const struct task_security_struct *__tsec;
struct key_security_struct *ksec; struct key_security_struct *ksec;
ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL); ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL);
if (!ksec) if (!ksec)
return -ENOMEM; return -ENOMEM;
if (tsec->keycreate_sid) rcu_read_lock();
ksec->sid = tsec->keycreate_sid; __tsec = __task_cred(tsk)->security;
if (__tsec->keycreate_sid)
ksec->sid = __tsec->keycreate_sid;
else else
ksec->sid = tsec->sid; ksec->sid = __tsec->sid;
k->security = ksec; rcu_read_unlock();
k->security = ksec;
return 0; return 0;
} }
...@@ -5434,13 +5459,8 @@ static int selinux_key_permission(key_ref_t key_ref, ...@@ -5434,13 +5459,8 @@ static int selinux_key_permission(key_ref_t key_ref,
key_perm_t perm) key_perm_t perm)
{ {
struct key *key; struct key *key;
struct task_security_struct *tsec;
struct key_security_struct *ksec; struct key_security_struct *ksec;
u32 sid;
key = key_ref_to_ptr(key_ref);
tsec = ctx->cred->security;
ksec = key->security;
/* if no specific permissions are requested, we skip the /* if no specific permissions are requested, we skip the
permission check. No serious, additional covert channels permission check. No serious, additional covert channels
...@@ -5448,8 +5468,12 @@ static int selinux_key_permission(key_ref_t key_ref, ...@@ -5448,8 +5468,12 @@ static int selinux_key_permission(key_ref_t key_ref,
if (perm == 0) if (perm == 0)
return 0; return 0;
return avc_has_perm(tsec->sid, ksec->sid, sid = task_sid(ctx);
SECCLASS_KEY, perm, NULL);
key = key_ref_to_ptr(key_ref);
ksec = key->security;
return avc_has_perm(sid, ksec->sid, SECCLASS_KEY, perm, NULL);
} }
static int selinux_key_getsecurity(struct key *key, char **_buffer) static int selinux_key_getsecurity(struct key *key, char **_buffer)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment