[PATCH 03/24] CRED: Alter security_task_getsecid() and similar to return both task SIDs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Alter security_task_getsecid(), selinux_get_task_sid() and associated functions
to return both the objective/victim and subjective/action task SIDs.  Both
results are optional by submitting NULL result pointers.

Interestingly, AF_NETLINK calls directly into SELinux.  I suspect this to be
incorrect.  It should probably use security_task_getsecid() instead.

Signed-off-by: David Howells <[email protected]>
---

 drivers/usb/core/devio.c          |    4 ++--
 include/linux/security.h          |   18 +++++++++++++-----
 include/linux/selinux.h           |   15 ++++++++++-----
 kernel/auditsc.c                  |   14 +++++++-------
 net/netlabel/netlabel_unlabeled.c |    2 +-
 net/netlink/af_netlink.c          |    2 +-
 security/dummy.c                  |    3 ++-
 security/selinux/exports.c        |   22 ++++++++++++++++++----
 security/selinux/hooks.c          |    5 +++--
 security/selinux/xfrm.c           |   12 ++++++------
 10 files changed, 63 insertions(+), 34 deletions(-)

diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 927a181..1e651d8 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -579,7 +579,7 @@ static int usbdev_open(struct inode *inode, struct file *file)
 	ps->disc_euid = current->euid;
 	ps->disccontext = NULL;
 	ps->ifclaimed = 0;
-	security_task_getsecid(current, &ps->secid);
+	security_task_getsecid(current, NULL, &ps->secid);
 	smp_wmb();
 	list_add_tail(&ps->list, &dev->filelist);
 	file->private_data = ps;
@@ -1069,7 +1069,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
 	as->pid = get_pid(task_pid(current));
 	as->uid = current->uid;
 	as->euid = current->euid;
-	security_task_getsecid(current, &as->secid);
+	security_task_getsecid(current, NULL, &as->secid);
 	if (!(uurb->endpoint & USB_DIR_IN)) {
 		if (copy_from_user(as->urb->transfer_buffer, uurb->buffer, as->urb->transfer_buffer_length)) {
 			free_async(as);
diff --git a/include/linux/security.h b/include/linux/security.h
index 74cc204..0933333 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -584,7 +584,12 @@ struct request_sock;
  *	Return 0 if permission is granted.
  * @task_getsecid:
  *	Retrieve the security identifier of the process @p.
- *	@p contains the task_struct for the process and place is into @secid.
+ *	@p contains the task_struct for the process to be interrogated.  The
+ *	security ID of the task itself is placed in *@object_secid, and the
+ *	security ID as which the task is currently acting is placed in
+ *	*@action_secid.  Either result pointer may be NULL if that particular
+ *	ID is not required.
+ *
  * @task_setgroups:
  *	Check permission before setting the supplementary group set of the
  *	current process.
@@ -1281,7 +1286,8 @@ struct security_operations {
 	int (*task_setpgid) (struct task_struct * p, pid_t pgid);
 	int (*task_getpgid) (struct task_struct * p);
 	int (*task_getsid) (struct task_struct * p);
-	void (*task_getsecid) (struct task_struct * p, u32 * secid);
+	void (*task_getsecid) (struct task_struct * p,
+			       u32 * object_secid, u32 * subject_secid);
 	int (*task_setgroups) (struct group_info *group_info);
 	int (*task_setnice) (struct task_struct * p, int nice);
 	int (*task_setioprio) (struct task_struct * p, int ioprio);
@@ -1936,9 +1942,10 @@ static inline int security_task_getsid (struct task_struct *p)
 	return security_ops->task_getsid (p);
 }
 
-static inline void security_task_getsecid (struct task_struct *p, u32 *secid)
+static inline void security_task_getsecid (struct task_struct *p,
+					   u32 *object_secid, u32 *action_secid)
 {
-	security_ops->task_getsecid (p, secid);
+	security_ops->task_getsecid (p, object_secid, action_secid);
 }
 
 static inline int security_task_setgroups (struct group_info *group_info)
@@ -2625,7 +2632,8 @@ static inline int security_task_getsid (struct task_struct *p)
 	return 0;
 }
 
-static inline void security_task_getsecid (struct task_struct *p, u32 *secid)
+static inline void security_task_getsecid (struct task_struct *p,
+					   u32 *object_secid, u32 *action_secid)
 { }
 
 static inline int security_task_setgroups (struct group_info *group_info)
diff --git a/include/linux/selinux.h b/include/linux/selinux.h
index d1b7ca6..26cdec3 100644
--- a/include/linux/selinux.h
+++ b/include/linux/selinux.h
@@ -101,12 +101,16 @@ void selinux_get_ipc_sid(const struct kern_ipc_perm *ipcp, u32 *sid);
 
 /**
  *     selinux_get_task_sid - return the SID of task
- *     @tsk: the task whose SID will be returned
- *     @sid: pointer to security context ID to be filled in.
+ *     @tsk: the task to be queried.
+ *     @object_sid: optional pointer to where the objective security context ID
+ *     of the task is to be placed.
+ *     @action_sid: optional pointer to where the subjective security context ID
+ *     of the task is to be placed.
  *
  *     Returns nothing
  */
-void selinux_get_task_sid(struct task_struct *tsk, u32 *sid);
+void selinux_get_task_sid(struct task_struct *tsk,
+			  u32 *object_sid, u32 *action_sid);
 
 /**
  *     selinux_string_to_sid - map a security context string to a security ID
@@ -173,9 +177,10 @@ static inline void selinux_get_ipc_sid(const struct kern_ipc_perm *ipcp, u32 *si
 	*sid = 0;
 }
 
-static inline void selinux_get_task_sid(struct task_struct *tsk, u32 *sid)
+lstatic inline void selinux_get_task_sid(struct task_struct *tsk,
+					 u32 *object_sid, u32 *action_sid)
 {
-	*sid = 0;
+	*object_sid = *action_sid = 0;
 }
 
 static inline int selinux_string_to_sid(const char *str, u32 *sid)
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 282e041..d87f7ac 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -399,7 +399,7 @@ static int audit_filter_rules(struct task_struct *tsk,
 			   logged upon error */
 			if (f->se_rule) {
 				if (need_sid) {
-					selinux_get_task_sid(tsk, &sid);
+					selinux_get_task_sid(tsk, NULL, &sid);
 					need_sid = 0;
 				}
 				result = selinux_audit_rule_match(sid, f->type,
@@ -746,7 +746,7 @@ void audit_log_task_context(struct audit_buffer *ab)
 	int error;
 	u32 sid;
 
-	selinux_get_task_sid(current, &sid);
+	selinux_get_task_sid(current, NULL, &sid);
 	if (!sid)
 		return;
 
@@ -1977,7 +1977,7 @@ void __audit_ptrace(struct task_struct *t)
 	struct audit_context *context = current->audit_context;
 
 	context->target_pid = t->pid;
-	selinux_get_task_sid(t, &context->target_sid);
+	selinux_get_task_sid(t, &context->target_sid, NULL);
 }
 
 /**
@@ -2004,7 +2004,7 @@ int __audit_signal_info(int sig, struct task_struct *t)
 				audit_sig_uid = ctx->loginuid;
 			else
 				audit_sig_uid = tsk->uid;
-			selinux_get_task_sid(tsk, &audit_sig_sid);
+			selinux_get_task_sid(tsk, NULL, &audit_sig_sid);
 		}
 		if (!audit_signals || audit_dummy_context())
 			return 0;
@@ -2014,7 +2014,7 @@ int __audit_signal_info(int sig, struct task_struct *t)
 	 * in audit_context */
 	if (!ctx->target_pid) {
 		ctx->target_pid = t->tgid;
-		selinux_get_task_sid(t, &ctx->target_sid);
+		selinux_get_task_sid(t, &ctx->target_sid, NULL);
 		return 0;
 	}
 
@@ -2031,7 +2031,7 @@ int __audit_signal_info(int sig, struct task_struct *t)
 	BUG_ON(axp->pid_count >= AUDIT_AUX_PIDS);
 
 	axp->target_pid[axp->pid_count] = t->tgid;
-	selinux_get_task_sid(t, &axp->target_sid[axp->pid_count]);
+	selinux_get_task_sid(t, &axp->target_sid[axp->pid_count], NULL);
 	axp->pid_count++;
 
 	return 0;
@@ -2059,7 +2059,7 @@ void audit_core_dumps(long signr)
 	audit_log_format(ab, "auid=%u uid=%u gid=%u",
 			audit_get_loginuid(current->audit_context),
 			current->uid, current->gid);
-	selinux_get_task_sid(current, &sid);
+	selinux_get_task_sid(current, NULL, &sid);
 	if (sid) {
 		char *ctx = NULL;
 		u32 len;
diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c
index 5c303c6..474c03a 100644
--- a/net/netlabel/netlabel_unlabeled.c
+++ b/net/netlabel/netlabel_unlabeled.c
@@ -277,7 +277,7 @@ int netlbl_unlabel_defconf(void)
 	/* Only the kernel is allowed to call this function and the only time
 	 * it is called is at bootup before the audit subsystem is reporting
 	 * messages so don't worry to much about these values. */
-	security_task_getsecid(current, &audit_info.secid);
+	security_task_getsecid(current, NULL, &audit_info.secid);
 	audit_info.loginuid = 0;
 
 	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 5681ce3..8c37d5f 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1190,7 +1190,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
 	NETLINK_CB(skb).pid	= nlk->pid;
 	NETLINK_CB(skb).dst_group = dst_group;
 	NETLINK_CB(skb).loginuid = audit_get_loginuid(current->audit_context);
-	selinux_get_task_sid(current, &(NETLINK_CB(skb).sid));
+	selinux_get_task_sid(current, NULL, &(NETLINK_CB(skb).sid));
 	memcpy(NETLINK_CREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
 
 	/* What can I do? Netlink is asynchronous, so that
diff --git a/security/dummy.c b/security/dummy.c
index f535cc6..187fc4b 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -523,7 +523,8 @@ static int dummy_task_getsid (struct task_struct *p)
 	return 0;
 }
 
-static void dummy_task_getsecid (struct task_struct *p, u32 *secid)
+static void dummy_task_getsecid (struct task_struct *p,
+				 u32 *object_secid, u32 *action_secid)
 { }
 
 static int dummy_task_setgroups (struct group_info *group_info)
diff --git a/security/selinux/exports.c b/security/selinux/exports.c
index 29cb87a..374a7b2 100644
--- a/security/selinux/exports.c
+++ b/security/selinux/exports.c
@@ -53,14 +53,28 @@ void selinux_get_ipc_sid(const struct kern_ipc_perm *ipcp, u32 *sid)
 	*sid = 0;
 }
 
-void selinux_get_task_sid(struct task_struct *tsk, u32 *sid)
+void selinux_get_task_sid(struct task_struct *tsk,
+			  u32 *object_sid, u32 *action_sid)
 {
 	if (selinux_enabled) {
-		struct task_security_struct *tsec = tsk->security;
-		*sid = tsec->victim_sid;
+		struct task_security_struct *tsec;
+		struct cred_security_struct *csec;
+		if (object_sid) {
+			tsec = tsk->security;
+			*object_sid = tsec->victim_sid;
+		}
+		if (action_sid) {
+			rcu_read_lock();
+			csec = task_cred(tsk)->security;
+			*action_sid = csec->action_sid;
+			rcu_read_unlock();
+		}
 		return;
 	}
-	*sid = 0;
+	if (object_sid)
+		*object_sid = 0;
+	if (action_sid)
+		*action_sid = 0;
 }
 
 int selinux_string_to_sid(char *str, u32 *sid)
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 4e72dbb..2ee1712 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2853,9 +2853,10 @@ static int selinux_task_getsid(struct task_struct *p)
 	return task_has_perm(current, p, PROCESS__GETSESSION);
 }
 
-static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
+static void selinux_task_getsecid(struct task_struct *p,
+				  u32 *object_secid, u32 *action_secid)
 {
-	selinux_get_task_sid(p, secid);
+	selinux_get_task_sid(p, object_secid, action_secid);
 }
 
 static int selinux_task_setgroups(struct group_info *group_info)
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c
index 902d302..9dfa8f3 100644
--- a/security/selinux/xfrm.c
+++ b/security/selinux/xfrm.c
@@ -199,7 +199,7 @@ static int selinux_xfrm_sec_ctx_alloc(struct xfrm_sec_ctx **ctxp,
 	struct xfrm_user_sec_ctx *uctx, u32 sid)
 {
 	int rc = 0;
-	struct task_security_struct *tsec = current->security;
+	struct cred_security_struct *csec = current->cred->security;
 	struct xfrm_sec_ctx *ctx = NULL;
 	char *ctx_str = NULL;
 	u32 str_len;
@@ -240,7 +240,7 @@ static int selinux_xfrm_sec_ctx_alloc(struct xfrm_sec_ctx **ctxp,
 	/*
 	 * Does the subject have permission to set security context?
 	 */
-	rc = avc_has_perm(tsec->action_sid, ctx->ctx_sid,
+	rc = avc_has_perm(csec->action_sid, ctx->ctx_sid,
 			  SECCLASS_ASSOCIATION,
 			  ASSOCIATION__SETCONTEXT, NULL);
 	if (rc)
@@ -336,12 +336,12 @@ void selinux_xfrm_policy_free(struct xfrm_policy *xp)
  */
 int selinux_xfrm_policy_delete(struct xfrm_policy *xp)
 {
-	struct task_security_struct *tsec = current->security;
+	struct cred_security_struct *csec = current->cred->security;
 	struct xfrm_sec_ctx *ctx = xp->security;
 	int rc = 0;
 
 	if (ctx)
-		rc = avc_has_perm(tsec->action_sid, ctx->ctx_sid,
+		rc = avc_has_perm(csec->action_sid, ctx->ctx_sid,
 				  SECCLASS_ASSOCIATION,
 				  ASSOCIATION__SETCONTEXT, NULL);
 
@@ -378,12 +378,12 @@ void selinux_xfrm_state_free(struct xfrm_state *x)
   */
 int selinux_xfrm_state_delete(struct xfrm_state *x)
 {
-	struct task_security_struct *tsec = current->security;
+	struct cred_security_struct *csec = current->cred->security;
 	struct xfrm_sec_ctx *ctx = x->security;
 	int rc = 0;
 
 	if (ctx)
-		rc = avc_has_perm(tsec->action_sid, ctx->ctx_sid,
+		rc = avc_has_perm(csec->action_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]
  Powered by Linux