Add an act-as SID to task_security_struct that is equivalent to fsuid/fsgid in
task_struct. This permits a task to perform operations as if it is the
overriding SID, without changing its own SID as that might be needed to control
access to the process by ptrace, signals, /proc, etc.
This is useful for CacheFiles in that it allows CacheFiles to access the cache
files and directories using the cache's security context rather than the
security context of the process on whose behalf it is working, and in the
context of which it is running.
Signed-Off-By: David Howells <[email protected]>
---
include/linux/security.h | 32 +++++++
security/dummy.c | 12 +++
security/selinux/exports.c | 2
security/selinux/hooks.c | 160 +++++++++++++++++++++++--------------
security/selinux/include/objsec.h | 1
security/selinux/selinuxfs.c | 2
security/selinux/xfrm.c | 6 +
7 files changed, 148 insertions(+), 67 deletions(-)
diff --git a/include/linux/security.h b/include/linux/security.h
index 7955017..63617e4 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1161,6 +1161,16 @@ #ifdef CONFIG_SECURITY
* Set the current FS security ID.
* @secid contains the security ID to set.
*
+ * @act_as_secid:
+ * Set the security ID as which to act, returning the security ID as which
+ * the process was previously acting.
+ * @secid contains the security ID to act as.
+ *
+ * @act_as_self:
+ * Reset the security ID as which to act to be the same as the process's
+ * owning security ID, and return the security ID as which the process was
+ * previously acting.
+ *
* This is the main security structure.
*/
struct security_operations {
@@ -1345,6 +1355,8 @@ struct security_operations {
void (*release_secctx)(char *secdata, u32 seclen);
u32 (*get_fscreate_secid)(void);
u32 (*set_fscreate_secid)(u32 secid);
+ u32 (*act_as_secid)(u32 secid);
+ u32 (*act_as_self)(void);
#ifdef CONFIG_SECURITY_NETWORK
int (*unix_stream_connect) (struct socket * sock,
@@ -2150,6 +2162,16 @@ static inline u32 security_set_fscreate_
return security_ops->set_fscreate_secid(secid);
}
+static inline u32 security_act_as_secid(u32 secid)
+{
+ return security_ops->act_as_secid(secid);
+}
+
+static inline u32 security_act_as_self(void)
+{
+ return security_ops->act_as_self();
+}
+
/* prototypes */
extern int security_init (void);
extern int register_security (struct security_operations *ops);
@@ -2840,6 +2862,16 @@ static inline u32 security_set_fscreate_
return 0;
}
+static inline u32 security_act_as_secid(u32 secid)
+{
+ return 0;
+}
+
+static inline u32 security_act_as_self(void)
+{
+ return 0;
+}
+
#endif /* CONFIG_SECURITY */
#ifdef CONFIG_SECURITY_NETWORK
diff --git a/security/dummy.c b/security/dummy.c
index ee3c886..f7b47a9 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -937,6 +937,16 @@ static u32 dummy_set_fscreate_secid(u32
return 0;
}
+static u32 dummy_act_as_secid(u32 secid)
+{
+ return 0;
+}
+
+static u32 dummy_act_as_self(void)
+{
+ return 0;
+}
+
#ifdef CONFIG_KEYS
static inline int dummy_key_alloc(struct key *key, struct task_struct *ctx,
unsigned long flags)
@@ -1093,6 +1103,8 @@ void security_fixup_ops (struct security
set_to_dummy_if_null(ops, release_secctx);
set_to_dummy_if_null(ops, get_fscreate_secid);
set_to_dummy_if_null(ops, set_fscreate_secid);
+ set_to_dummy_if_null(ops, act_as_secid);
+ set_to_dummy_if_null(ops, act_as_self);
#ifdef CONFIG_SECURITY_NETWORK
set_to_dummy_if_null(ops, unix_stream_connect);
set_to_dummy_if_null(ops, unix_may_send);
diff --git a/security/selinux/exports.c b/security/selinux/exports.c
index b6f9694..b559699 100644
--- a/security/selinux/exports.c
+++ b/security/selinux/exports.c
@@ -79,7 +79,7 @@ int selinux_relabel_packet_permission(u3
if (selinux_enabled) {
struct task_security_struct *tsec = current->security;
- return avc_has_perm(tsec->sid, sid, SECCLASS_PACKET,
+ return avc_has_perm(tsec->actor_sid, sid, SECCLASS_PACKET,
PACKET__RELABELTO, NULL);
}
return 0;
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 7f5ec86..09def09 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -162,7 +162,8 @@ static int task_alloc_security(struct ta
return -ENOMEM;
tsec->task = task;
- tsec->osid = tsec->sid = tsec->ptrace_sid = SECINITSID_UNLABELED;
+ tsec->osid = tsec->actor_sid = tsec->sid = tsec->ptrace_sid =
+ SECINITSID_UNLABELED;
task->security = tsec;
return 0;
@@ -190,7 +191,7 @@ static int inode_alloc_security(struct i
isec->inode = inode;
isec->sid = SECINITSID_UNLABELED;
isec->sclass = SECCLASS_FILE;
- isec->task_sid = tsec->sid;
+ isec->task_sid = tsec->actor_sid;
inode->i_security = isec;
return 0;
@@ -220,8 +221,8 @@ static int file_alloc_security(struct fi
return -ENOMEM;
fsec->file = file;
- fsec->sid = tsec->sid;
- fsec->fown_sid = tsec->sid;
+ fsec->sid = tsec->actor_sid;
+ fsec->fown_sid = tsec->actor_sid;
file->f_security = fsec;
return 0;
@@ -338,12 +339,12 @@ static int may_context_mount_sb_relabel(
{
int rc;
- rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
+ rc = avc_has_perm(tsec->actor_sid, sbsec->sid, SECCLASS_FILESYSTEM,
FILESYSTEM__RELABELFROM, NULL);
if (rc)
return rc;
- rc = avc_has_perm(tsec->sid, sid, SECCLASS_FILESYSTEM,
+ rc = avc_has_perm(tsec->actor_sid, sid, SECCLASS_FILESYSTEM,
FILESYSTEM__RELABELTO, NULL);
return rc;
}
@@ -353,7 +354,7 @@ static int may_context_mount_inode_relab
struct task_security_struct *tsec)
{
int rc;
- rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
+ rc = avc_has_perm(tsec->actor_sid, sbsec->sid, SECCLASS_FILESYSTEM,
FILESYSTEM__RELABELFROM, NULL);
if (rc)
return rc;
@@ -1030,7 +1031,7 @@ static int task_has_perm(struct task_str
tsec1 = tsk1->security;
tsec2 = tsk2->security;
- return avc_has_perm(tsec1->sid, tsec2->sid,
+ return avc_has_perm(tsec1->actor_sid, tsec2->sid,
SECCLASS_PROCESS, perms, NULL);
}
@@ -1047,7 +1048,7 @@ static int task_has_capability(struct ta
ad.tsk = tsk;
ad.u.cap = cap;
- return avc_has_perm(tsec->sid, tsec->sid,
+ return avc_has_perm(tsec->actor_sid, tsec->actor_sid,
SECCLASS_CAPABILITY, CAP_TO_MASK(cap), &ad);
}
@@ -1059,7 +1060,7 @@ static int task_has_system(struct task_s
tsec = tsk->security;
- return avc_has_perm(tsec->sid, SECINITSID_KERNEL,
+ return avc_has_perm(tsec->actor_sid, SECINITSID_KERNEL,
SECCLASS_SYSTEM, perms, NULL);
}
@@ -1084,7 +1085,8 @@ static int inode_has_perm(struct task_st
ad.u.fs.inode = inode;
}
- return avc_has_perm(tsec->sid, isec->sid, isec->sclass, perms, adp);
+ return avc_has_perm(tsec->actor_sid, isec->sid, isec->sclass, perms,
+ adp);
}
/* Same as inode_has_perm, but pass explicit audit data containing
@@ -1127,8 +1129,8 @@ static int file_has_perm(struct task_str
ad.u.fs.mnt = mnt;
ad.u.fs.dentry = dentry;
- if (tsec->sid != fsec->sid) {
- rc = avc_has_perm(tsec->sid, fsec->sid,
+ if (tsec->actor_sid != fsec->sid) {
+ rc = avc_has_perm(tsec->actor_sid, fsec->sid,
SECCLASS_FD,
FD__USE,
&ad);
@@ -1162,7 +1164,7 @@ static int may_create(struct inode *dir,
AVC_AUDIT_DATA_INIT(&ad, FS);
ad.u.fs.dentry = dentry;
- rc = avc_has_perm(tsec->sid, dsec->sid, SECCLASS_DIR,
+ rc = avc_has_perm(tsec->actor_sid, dsec->sid, SECCLASS_DIR,
DIR__ADD_NAME | DIR__SEARCH,
&ad);
if (rc)
@@ -1171,13 +1173,13 @@ static int may_create(struct inode *dir,
if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
newsid = tsec->create_sid;
} else {
- rc = security_transition_sid(tsec->sid, dsec->sid, tclass,
- &newsid);
+ rc = security_transition_sid(tsec->actor_sid, dsec->sid,
+ tclass, &newsid);
if (rc)
return rc;
}
- rc = avc_has_perm(tsec->sid, newsid, tclass, FILE__CREATE, &ad);
+ rc = avc_has_perm(tsec->actor_sid, newsid, tclass, FILE__CREATE, &ad);
if (rc)
return rc;
@@ -1194,7 +1196,8 @@ static int may_create_key(u32 ksid,
tsec = ctx->security;
- return avc_has_perm(tsec->sid, ksid, SECCLASS_KEY, KEY__CREATE, NULL);
+ return avc_has_perm(tsec->actor_sid, ksid, SECCLASS_KEY, KEY__CREATE,
+ NULL);
}
#define MAY_LINK 0
@@ -1222,7 +1225,7 @@ static int may_link(struct inode *dir,
av = DIR__SEARCH;
av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
- rc = avc_has_perm(tsec->sid, dsec->sid, SECCLASS_DIR, av, &ad);
+ rc = avc_has_perm(tsec->actor_sid, dsec->sid, SECCLASS_DIR, av, &ad);
if (rc)
return rc;
@@ -1241,7 +1244,7 @@ static int may_link(struct inode *dir,
return 0;
}
- rc = avc_has_perm(tsec->sid, isec->sid, isec->sclass, av, &ad);
+ rc = avc_has_perm(tsec->actor_sid, isec->sid, isec->sclass, av, &ad);
return rc;
}
@@ -1266,16 +1269,16 @@ static inline int may_rename(struct inod
AVC_AUDIT_DATA_INIT(&ad, FS);
ad.u.fs.dentry = old_dentry;
- rc = avc_has_perm(tsec->sid, old_dsec->sid, SECCLASS_DIR,
+ rc = avc_has_perm(tsec->actor_sid, old_dsec->sid, SECCLASS_DIR,
DIR__REMOVE_NAME | DIR__SEARCH, &ad);
if (rc)
return rc;
- rc = avc_has_perm(tsec->sid, old_isec->sid,
+ rc = avc_has_perm(tsec->actor_sid, old_isec->sid,
old_isec->sclass, FILE__RENAME, &ad);
if (rc)
return rc;
if (old_is_dir && new_dir != old_dir) {
- rc = avc_has_perm(tsec->sid, old_isec->sid,
+ rc = avc_has_perm(tsec->actor_sid, old_isec->sid,
old_isec->sclass, DIR__REPARENT, &ad);
if (rc)
return rc;
@@ -1285,15 +1288,17 @@ static inline int may_rename(struct inod
av = DIR__ADD_NAME | DIR__SEARCH;
if (new_dentry->d_inode)
av |= DIR__REMOVE_NAME;
- rc = avc_has_perm(tsec->sid, new_dsec->sid, SECCLASS_DIR, av, &ad);
+ rc = avc_has_perm(tsec->actor_sid, new_dsec->sid, SECCLASS_DIR, av,
+ &ad);
if (rc)
return rc;
if (new_dentry->d_inode) {
new_isec = new_dentry->d_inode->i_security;
new_is_dir = S_ISDIR(new_dentry->d_inode->i_mode);
- rc = avc_has_perm(tsec->sid, new_isec->sid,
+ rc = avc_has_perm(tsec->actor_sid, new_isec->sid,
new_isec->sclass,
- (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad);
+ (new_is_dir ? DIR__RMDIR : FILE__UNLINK),
+ &ad);
if (rc)
return rc;
}
@@ -1312,7 +1317,7 @@ static int superblock_has_perm(struct ta
tsec = tsk->security;
sbsec = sb->s_security;
- return avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
+ return avc_has_perm(tsec->actor_sid, sbsec->sid, SECCLASS_FILESYSTEM,
perms, ad);
}
@@ -1376,7 +1381,7 @@ static int selinux_ptrace(struct task_st
rc = task_has_perm(parent, child, PROCESS__PTRACE);
/* Save the SID of the tracing process for later use in apply_creds. */
if (!(child->ptrace & PT_PTRACED) && !rc)
- csec->ptrace_sid = psec->sid;
+ csec->ptrace_sid = psec->actor_sid;
return rc;
}
@@ -1445,7 +1450,7 @@ static int selinux_sysctl(ctl_table *tab
/* The op values are "defined" in sysctl.c, thereby creating
* a bad coupling between this module and sysctl.c */
if(op == 001) {
- error = avc_has_perm(tsec->sid, tsid,
+ error = avc_has_perm(tsec->actor_sid, tsid,
SECCLASS_DIR, DIR__SEARCH, NULL);
} else {
av = 0;
@@ -1454,7 +1459,7 @@ static int selinux_sysctl(ctl_table *tab
if (op & 002)
av |= FILE__WRITE;
if (av)
- error = avc_has_perm(tsec->sid, tsid,
+ error = avc_has_perm(tsec->actor_sid, tsid,
SECCLASS_FILE, av, NULL);
}
@@ -1546,7 +1551,7 @@ static int selinux_vm_enough_memory(long
rc = secondary_ops->capable(current, CAP_SYS_ADMIN);
if (rc == 0)
- rc = avc_has_perm_noaudit(tsec->sid, tsec->sid,
+ rc = avc_has_perm_noaudit(tsec->actor_sid, tsec->actor_sid,
SECCLASS_CAPABILITY,
CAP_TO_MASK(CAP_SYS_ADMIN),
NULL);
@@ -1598,7 +1603,7 @@ static int selinux_bprm_set_security(str
isec = inode->i_security;
/* Default to the current task SID. */
- bsec->sid = tsec->sid;
+ bsec->sid = tsec->actor_sid;
/* Reset fs, key, and sock SIDs on execve. */
tsec->create_sid = 0;
@@ -1611,7 +1616,7 @@ static int selinux_bprm_set_security(str
tsec->exec_sid = 0;
} else {
/* Check for a default transition on this program. */
- rc = security_transition_sid(tsec->sid, isec->sid,
+ rc = security_transition_sid(tsec->actor_sid, isec->sid,
SECCLASS_PROCESS, &newsid);
if (rc)
return rc;
@@ -1622,16 +1627,16 @@ static int selinux_bprm_set_security(str
ad.u.fs.dentry = bprm->file->f_dentry;
if (bprm->file->f_vfsmnt->mnt_flags & MNT_NOSUID)
- newsid = tsec->sid;
+ newsid = tsec->actor_sid;
- if (tsec->sid == newsid) {
- rc = avc_has_perm(tsec->sid, isec->sid,
+ if (tsec->actor_sid == newsid) {
+ rc = avc_has_perm(tsec->actor_sid, isec->sid,
SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);
if (rc)
return rc;
} else {
/* Check permissions for the transition. */
- rc = avc_has_perm(tsec->sid, newsid,
+ rc = avc_has_perm(tsec->actor_sid, newsid,
SECCLASS_PROCESS, PROCESS__TRANSITION, &ad);
if (rc)
return rc;
@@ -1810,6 +1815,8 @@ static void selinux_bprm_apply_creds(str
return;
}
}
+ if (tsec->actor_sid == tsec->sid)
+ tsec->actor_sid = sid;
tsec->sid = sid;
}
}
@@ -2084,7 +2091,7 @@ static int selinux_inode_init_security(s
if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
newsid = tsec->create_sid;
} else {
- rc = security_transition_sid(tsec->sid, dsec->sid,
+ rc = security_transition_sid(tsec->actor_sid, dsec->sid,
inode_mode_to_security_class(inode->i_mode),
&newsid);
if (rc) {
@@ -2275,7 +2282,7 @@ static int selinux_inode_setxattr(struct
AVC_AUDIT_DATA_INIT(&ad,FS);
ad.u.fs.dentry = dentry;
- rc = avc_has_perm(tsec->sid, isec->sid, isec->sclass,
+ rc = avc_has_perm(tsec->actor_sid, isec->sid, isec->sclass,
FILE__RELABELFROM, &ad);
if (rc)
return rc;
@@ -2284,12 +2291,12 @@ static int selinux_inode_setxattr(struct
if (rc)
return rc;
- rc = avc_has_perm(tsec->sid, newsid, isec->sclass,
+ rc = avc_has_perm(tsec->actor_sid, newsid, isec->sclass,
FILE__RELABELTO, &ad);
if (rc)
return rc;
- rc = security_validate_transition(isec->sid, newsid, tsec->sid,
+ rc = security_validate_transition(isec->sid, newsid, tsec->actor_sid,
isec->sclass);
if (rc)
return rc;
@@ -2693,7 +2700,7 @@ static int selinux_task_alloc_security(s
tsec2 = tsk->security;
tsec2->osid = tsec1->osid;
- tsec2->sid = tsec1->sid;
+ tsec2->actor_sid = tsec2->sid = tsec1->sid;
/* Retain the exec, fs, key, and sock SIDs across fork */
tsec2->exec_sid = tsec1->exec_sid;
@@ -2872,6 +2879,8 @@ static void selinux_task_reparent_to_ini
tsec = p->security;
tsec->osid = tsec->sid;
+ if (tsec->actor_sid == tsec->sid)
+ tsec->actor_sid = SECINITSID_KERNEL;
tsec->sid = SECINITSID_KERNEL;
return;
}
@@ -3054,7 +3063,8 @@ static int socket_has_perm(struct task_s
AVC_AUDIT_DATA_INIT(&ad,NET);
ad.u.net.sk = sock->sk;
- err = avc_has_perm(tsec->sid, isec->sid, isec->sclass, perms, &ad);
+ err = avc_has_perm(tsec->actor_sid, isec->sid, isec->sclass, perms,
+ &ad);
out:
return err;
@@ -3071,8 +3081,8 @@ static int selinux_socket_create(int fam
goto out;
tsec = current->security;
- newsid = tsec->sockcreate_sid ? : tsec->sid;
- err = avc_has_perm(tsec->sid, newsid,
+ newsid = tsec->sockcreate_sid ? : tsec->actor_sid;
+ err = avc_has_perm(tsec->actor_sid, newsid,
socket_type_to_security_class(family, type,
protocol), SOCKET__CREATE, NULL);
@@ -3092,7 +3102,7 @@ static int selinux_socket_post_create(st
isec = SOCK_INODE(sock)->i_security;
tsec = current->security;
- newsid = tsec->sockcreate_sid ? : tsec->sid;
+ newsid = tsec->sockcreate_sid ? : tsec->actor_sid;
isec->sclass = socket_type_to_security_class(family, type, protocol);
isec->sid = kern ? SECINITSID_KERNEL : newsid;
isec->initialized = 1;
@@ -3904,7 +3914,7 @@ static int ipc_alloc_security(struct tas
isec->sclass = sclass;
isec->ipc_perm = perm;
- isec->sid = tsec->sid;
+ isec->sid = tsec->actor_sid;
perm->security = isec;
return 0;
@@ -3953,7 +3963,8 @@ static int ipc_has_perm(struct kern_ipc_
AVC_AUDIT_DATA_INIT(&ad, IPC);
ad.u.ipc_id = ipc_perms->key;
- return avc_has_perm(tsec->sid, isec->sid, isec->sclass, perms, &ad);
+ return avc_has_perm(tsec->actor_sid, isec->sid, isec->sclass, perms,
+ &ad);
}
static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
@@ -3984,7 +3995,7 @@ static int selinux_msg_queue_alloc_secur
AVC_AUDIT_DATA_INIT(&ad, IPC);
ad.u.ipc_id = msq->q_perm.key;
- rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_MSGQ,
+ rc = avc_has_perm(tsec->actor_sid, isec->sid, SECCLASS_MSGQ,
MSGQ__CREATE, &ad);
if (rc) {
ipc_free_security(&msq->q_perm);
@@ -4010,7 +4021,7 @@ static int selinux_msg_queue_associate(s
AVC_AUDIT_DATA_INIT(&ad, IPC);
ad.u.ipc_id = msq->q_perm.key;
- return avc_has_perm(tsec->sid, isec->sid, SECCLASS_MSGQ,
+ return avc_has_perm(tsec->actor_sid, isec->sid, SECCLASS_MSGQ,
MSGQ__ASSOCIATE, &ad);
}
@@ -4062,7 +4073,7 @@ static int selinux_msg_queue_msgsnd(stru
* Compute new sid based on current process and
* message queue this message will be stored in
*/
- rc = security_transition_sid(tsec->sid,
+ rc = security_transition_sid(tsec->actor_sid,
isec->sid,
SECCLASS_MSG,
&msec->sid);
@@ -4074,11 +4085,11 @@ static int selinux_msg_queue_msgsnd(stru
ad.u.ipc_id = msq->q_perm.key;
/* Can this process write to the queue? */
- rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_MSGQ,
+ rc = avc_has_perm(tsec->actor_sid, isec->sid, SECCLASS_MSGQ,
MSGQ__WRITE, &ad);
if (!rc)
/* Can this process send the message */
- rc = avc_has_perm(tsec->sid, msec->sid,
+ rc = avc_has_perm(tsec->actor_sid, msec->sid,
SECCLASS_MSG, MSG__SEND, &ad);
if (!rc)
/* Can the message be put in the queue? */
@@ -4105,10 +4116,10 @@ static int selinux_msg_queue_msgrcv(stru
AVC_AUDIT_DATA_INIT(&ad, IPC);
ad.u.ipc_id = msq->q_perm.key;
- rc = avc_has_perm(tsec->sid, isec->sid,
+ rc = avc_has_perm(tsec->actor_sid, isec->sid,
SECCLASS_MSGQ, MSGQ__READ, &ad);
if (!rc)
- rc = avc_has_perm(tsec->sid, msec->sid,
+ rc = avc_has_perm(tsec->actor_sid, msec->sid,
SECCLASS_MSG, MSG__RECEIVE, &ad);
return rc;
}
@@ -4131,7 +4142,7 @@ static int selinux_shm_alloc_security(st
AVC_AUDIT_DATA_INIT(&ad, IPC);
ad.u.ipc_id = shp->shm_perm.key;
- rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_SHM,
+ rc = avc_has_perm(tsec->actor_sid, isec->sid, SECCLASS_SHM,
SHM__CREATE, &ad);
if (rc) {
ipc_free_security(&shp->shm_perm);
@@ -4157,7 +4168,7 @@ static int selinux_shm_associate(struct
AVC_AUDIT_DATA_INIT(&ad, IPC);
ad.u.ipc_id = shp->shm_perm.key;
- return avc_has_perm(tsec->sid, isec->sid, SECCLASS_SHM,
+ return avc_has_perm(tsec->actor_sid, isec->sid, SECCLASS_SHM,
SHM__ASSOCIATE, &ad);
}
@@ -4230,7 +4241,7 @@ static int selinux_sem_alloc_security(st
AVC_AUDIT_DATA_INIT(&ad, IPC);
ad.u.ipc_id = sma->sem_perm.key;
- rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_SEM,
+ rc = avc_has_perm(tsec->actor_sid, isec->sid, SECCLASS_SEM,
SEM__CREATE, &ad);
if (rc) {
ipc_free_security(&sma->sem_perm);
@@ -4256,7 +4267,7 @@ static int selinux_sem_associate(struct
AVC_AUDIT_DATA_INIT(&ad, IPC);
ad.u.ipc_id = sma->sem_perm.key;
- return avc_has_perm(tsec->sid, isec->sid, SECCLASS_SEM,
+ return avc_has_perm(tsec->actor_sid, isec->sid, SECCLASS_SEM,
SEM__ASSOCIATE, &ad);
}
@@ -4500,14 +4511,19 @@ static int selinux_setprocattr(struct ta
error = avc_has_perm_noaudit(tsec->ptrace_sid, sid,
SECCLASS_PROCESS,
PROCESS__PTRACE, &avd);
- if (!error)
+ if (!error) {
+ if (tsec->actor_sid == tsec->sid)
+ tsec->actor_sid = sid;
tsec->sid = sid;
+ }
task_unlock(p);
avc_audit(tsec->ptrace_sid, sid, SECCLASS_PROCESS,
PROCESS__PTRACE, &avd, error, NULL);
if (error)
return error;
} else {
+ if (tsec->actor_sid == tsec->sid)
+ tsec->actor_sid = sid;
tsec->sid = sid;
task_unlock(p);
}
@@ -4545,6 +4561,24 @@ static u32 selinux_set_fscreate_secid(u3
return oldsid;
}
+static u32 selinux_act_as_secid(u32 secid)
+{
+ struct task_security_struct *tsec = current->security;
+ u32 oldactor_sid = tsec->actor_sid;
+
+ tsec->actor_sid = secid;
+ return oldactor_sid;
+}
+
+static u32 selinux_act_as_self(void)
+{
+ struct task_security_struct *tsec = current->security;
+ u32 oldactor_sid = tsec->actor_sid;
+
+ tsec->actor_sid = tsec->sid;
+ return oldactor_sid;
+}
+
#ifdef CONFIG_KEYS
static int selinux_key_alloc(struct key *k, struct task_struct *tsk,
@@ -4594,7 +4628,7 @@ static int selinux_key_permission(key_re
if (perm == 0)
return 0;
- return avc_has_perm(tsec->sid, ksec->sid,
+ return avc_has_perm(tsec->actor_sid, ksec->sid,
SECCLASS_KEY, perm, NULL);
}
@@ -4729,6 +4763,8 @@ static struct security_operations selinu
.release_secctx = selinux_release_secctx,
.get_fscreate_secid = selinux_get_fscreate_secid,
.set_fscreate_secid = selinux_set_fscreate_secid,
+ .act_as_secid = selinux_act_as_secid,
+ .act_as_self = selinux_act_as_self,
.unix_stream_connect = selinux_socket_unix_stream_connect,
.unix_may_send = selinux_socket_unix_may_send,
@@ -4794,7 +4830,7 @@ static __init int selinux_init(void)
if (task_alloc_security(current))
panic("SELinux: Failed to initialize initial task.\n");
tsec = current->security;
- tsec->osid = tsec->sid = SECINITSID_KERNEL;
+ tsec->osid = tsec->actor_sid = tsec->sid = SECINITSID_KERNEL;
sel_inode_cache = kmem_cache_create("selinux_inode_security",
sizeof(struct inode_security_struct),
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
index ef2267f..4e8da30 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -30,6 +30,7 @@ struct task_security_struct {
struct task_struct *task; /* back pointer to task object */
u32 osid; /* SID prior to last execve */
u32 sid; /* current SID */
+ u32 actor_sid; /* act-as SID (normally == sid) */
u32 exec_sid; /* exec SID */
u32 create_sid; /* fscreate SID */
u32 keycreate_sid; /* keycreate SID */
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index cd24441..c676b4b 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -79,7 +79,7 @@ static int task_has_security(struct task
if (!tsec)
return -EACCES;
- return avc_has_perm(tsec->sid, SECINITSID_SECURITY,
+ return avc_has_perm(tsec->actor_sid, SECINITSID_SECURITY,
SECCLASS_SECURITY, perms, NULL);
}
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c
index 675b995..4ea1f58 100644
--- a/security/selinux/xfrm.c
+++ b/security/selinux/xfrm.c
@@ -270,7 +270,7 @@ static int selinux_xfrm_sec_ctx_alloc(st
/*
* Does the subject have permission to set security context?
*/
- rc = avc_has_perm(tsec->sid, ctx->ctx_sid,
+ rc = avc_has_perm(tsec->actor_sid, ctx->ctx_sid,
SECCLASS_ASSOCIATION,
ASSOCIATION__SETCONTEXT, NULL);
if (rc)
@@ -387,7 +387,7 @@ int selinux_xfrm_policy_delete(struct xf
int rc = 0;
if (ctx)
- rc = avc_has_perm(tsec->sid, ctx->ctx_sid,
+ rc = avc_has_perm(tsec->actor_sid, ctx->ctx_sid,
SECCLASS_ASSOCIATION,
ASSOCIATION__SETCONTEXT, NULL);
@@ -497,7 +497,7 @@ int selinux_xfrm_state_delete(struct xfr
int rc = 0;
if (ctx)
- rc = avc_has_perm(tsec->sid, ctx->ctx_sid,
+ rc = avc_has_perm(tsec->actor_sid, ctx->ctx_sid,
SECCLASS_ASSOCIATION,
ASSOCIATION__SETCONTEXT, NULL);
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[Index of Archives]
[Kernel Newbies]
[Netfilter]
[Bugtraq]
[Photo]
[Stuff]
[Gimp]
[Yosemite News]
[MIPS Linux]
[ARM Linux]
[Linux Security]
[Linux RAID]
[Video 4 Linux]
[Linux for the blind]
[Linux Resources]