aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Smalley <sds@tycho.nsa.gov>2017-09-08 12:40:01 -0400
committerJames Morris <james.morris@microsoft.com>2018-03-06 17:05:53 -0500
commit6b4f3d01052a479c7ebbe99d52a663558dc1be2a (patch)
tree430c1d7c7be50abb1fe71f88426a4376d37de3ab
parenta02633e9b13dcb9b1a656b08f81bc8ba2d4d2294 (diff)
usb, signal, security: only pass the cred, not the secid, to kill_pid_info_as_cred and security_task_kill
commit d178bc3a708f39cbfefc3fab37032d3f2511b4ec ("user namespace: usb: make usb urbs user namespace aware (v2)") changed kill_pid_info_as_uid to kill_pid_info_as_cred, saving and passing a cred structure instead of uids. Since the secid can be obtained from the cred, drop the secid fields from the usb_dev_state and async structures, and drop the secid argument to kill_pid_info_as_cred. Replace the secid argument to security_task_kill with the cred. Update SELinux, Smack, and AppArmor to use the cred, which avoids the need for Smack and AppArmor to use a secid at all in this hook. Further changes to Smack might still be required to take full advantage of this change, since it should now be possible to perform capability checking based on the supplied cred. The changes to Smack and AppArmor have only been compile-tested. Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov> Acked-by: Paul Moore <paul@paul-moore.com> Acked-by: Casey Schaufler <casey@schaufler-ca.com> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Acked-by: John Johansen <john.johansen@canonical.com> Signed-off-by: James Morris <james.morris@microsoft.com>
-rw-r--r--drivers/usb/core/devio.c10
-rw-r--r--include/linux/lsm_hooks.h5
-rw-r--r--include/linux/sched/signal.h2
-rw-r--r--include/linux/security.h4
-rw-r--r--kernel/signal.c6
-rw-r--r--security/apparmor/lsm.c17
-rw-r--r--security/security.c4
-rw-r--r--security/selinux/hooks.c7
-rw-r--r--security/smack/smack_lsm.c12
9 files changed, 35 insertions, 32 deletions
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index d526595bc959..76e16c5251b9 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -65,7 +65,6 @@ struct usb_dev_state {
65 const struct cred *cred; 65 const struct cred *cred;
66 void __user *disccontext; 66 void __user *disccontext;
67 unsigned long ifclaimed; 67 unsigned long ifclaimed;
68 u32 secid;
69 u32 disabled_bulk_eps; 68 u32 disabled_bulk_eps;
70 bool privileges_dropped; 69 bool privileges_dropped;
71 unsigned long interface_allowed_mask; 70 unsigned long interface_allowed_mask;
@@ -95,7 +94,6 @@ struct async {
95 struct usb_memory *usbm; 94 struct usb_memory *usbm;
96 unsigned int mem_usage; 95 unsigned int mem_usage;
97 int status; 96 int status;
98 u32 secid;
99 u8 bulk_addr; 97 u8 bulk_addr;
100 u8 bulk_status; 98 u8 bulk_status;
101}; 99};
@@ -586,7 +584,6 @@ static void async_completed(struct urb *urb)
586 struct usb_dev_state *ps = as->ps; 584 struct usb_dev_state *ps = as->ps;
587 struct siginfo sinfo; 585 struct siginfo sinfo;
588 struct pid *pid = NULL; 586 struct pid *pid = NULL;
589 u32 secid = 0;
590 const struct cred *cred = NULL; 587 const struct cred *cred = NULL;
591 int signr; 588 int signr;
592 589
@@ -602,7 +599,6 @@ static void async_completed(struct urb *urb)
602 sinfo.si_addr = as->userurb; 599 sinfo.si_addr = as->userurb;
603 pid = get_pid(as->pid); 600 pid = get_pid(as->pid);
604 cred = get_cred(as->cred); 601 cred = get_cred(as->cred);
605 secid = as->secid;
606 } 602 }
607 snoop(&urb->dev->dev, "urb complete\n"); 603 snoop(&urb->dev->dev, "urb complete\n");
608 snoop_urb(urb->dev, as->userurb, urb->pipe, urb->actual_length, 604 snoop_urb(urb->dev, as->userurb, urb->pipe, urb->actual_length,
@@ -618,7 +614,7 @@ static void async_completed(struct urb *urb)
618 spin_unlock(&ps->lock); 614 spin_unlock(&ps->lock);
619 615
620 if (signr) { 616 if (signr) {
621 kill_pid_info_as_cred(sinfo.si_signo, &sinfo, pid, cred, secid); 617 kill_pid_info_as_cred(sinfo.si_signo, &sinfo, pid, cred);
622 put_pid(pid); 618 put_pid(pid);
623 put_cred(cred); 619 put_cred(cred);
624 } 620 }
@@ -1013,7 +1009,6 @@ static int usbdev_open(struct inode *inode, struct file *file)
1013 init_waitqueue_head(&ps->wait); 1009 init_waitqueue_head(&ps->wait);
1014 ps->disc_pid = get_pid(task_pid(current)); 1010 ps->disc_pid = get_pid(task_pid(current));
1015 ps->cred = get_current_cred(); 1011 ps->cred = get_current_cred();
1016 security_task_getsecid(current, &ps->secid);
1017 smp_wmb(); 1012 smp_wmb();
1018 list_add_tail(&ps->list, &dev->filelist); 1013 list_add_tail(&ps->list, &dev->filelist);
1019 file->private_data = ps; 1014 file->private_data = ps;
@@ -1727,7 +1722,6 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
1727 as->ifnum = ifnum; 1722 as->ifnum = ifnum;
1728 as->pid = get_pid(task_pid(current)); 1723 as->pid = get_pid(task_pid(current));
1729 as->cred = get_current_cred(); 1724 as->cred = get_current_cred();
1730 security_task_getsecid(current, &as->secid);
1731 snoop_urb(ps->dev, as->userurb, as->urb->pipe, 1725 snoop_urb(ps->dev, as->userurb, as->urb->pipe,
1732 as->urb->transfer_buffer_length, 0, SUBMIT, 1726 as->urb->transfer_buffer_length, 0, SUBMIT,
1733 NULL, 0); 1727 NULL, 0);
@@ -2617,7 +2611,7 @@ static void usbdev_remove(struct usb_device *udev)
2617 sinfo.si_code = SI_ASYNCIO; 2611 sinfo.si_code = SI_ASYNCIO;
2618 sinfo.si_addr = ps->disccontext; 2612 sinfo.si_addr = ps->disccontext;
2619 kill_pid_info_as_cred(ps->discsignr, &sinfo, 2613 kill_pid_info_as_cred(ps->discsignr, &sinfo,
2620 ps->disc_pid, ps->cred, ps->secid); 2614 ps->disc_pid, ps->cred);
2621 } 2615 }
2622 } 2616 }
2623} 2617}
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 7161d8e7ee79..e0ac011d07a5 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -672,7 +672,8 @@
672 * @p contains the task_struct for process. 672 * @p contains the task_struct for process.
673 * @info contains the signal information. 673 * @info contains the signal information.
674 * @sig contains the signal value. 674 * @sig contains the signal value.
675 * @secid contains the sid of the process where the signal originated 675 * @cred contains the cred of the process where the signal originated, or
676 * NULL if the current task is the originator.
676 * Return 0 if permission is granted. 677 * Return 0 if permission is granted.
677 * @task_prctl: 678 * @task_prctl:
678 * Check permission before performing a process control operation on the 679 * Check permission before performing a process control operation on the
@@ -1564,7 +1565,7 @@ union security_list_options {
1564 int (*task_getscheduler)(struct task_struct *p); 1565 int (*task_getscheduler)(struct task_struct *p);
1565 int (*task_movememory)(struct task_struct *p); 1566 int (*task_movememory)(struct task_struct *p);
1566 int (*task_kill)(struct task_struct *p, struct siginfo *info, 1567 int (*task_kill)(struct task_struct *p, struct siginfo *info,
1567 int sig, u32 secid); 1568 int sig, const struct cred *cred);
1568 int (*task_prctl)(int option, unsigned long arg2, unsigned long arg3, 1569 int (*task_prctl)(int option, unsigned long arg2, unsigned long arg3,
1569 unsigned long arg4, unsigned long arg5); 1570 unsigned long arg4, unsigned long arg5);
1570 void (*task_to_inode)(struct task_struct *p, struct inode *inode); 1571 void (*task_to_inode)(struct task_struct *p, struct inode *inode);
diff --git a/include/linux/sched/signal.h b/include/linux/sched/signal.h
index 23b4f9cb82db..a7ce74c74e49 100644
--- a/include/linux/sched/signal.h
+++ b/include/linux/sched/signal.h
@@ -319,7 +319,7 @@ extern int force_sig_info(int, struct siginfo *, struct task_struct *);
319extern int __kill_pgrp_info(int sig, struct siginfo *info, struct pid *pgrp); 319extern int __kill_pgrp_info(int sig, struct siginfo *info, struct pid *pgrp);
320extern int kill_pid_info(int sig, struct siginfo *info, struct pid *pid); 320extern int kill_pid_info(int sig, struct siginfo *info, struct pid *pid);
321extern int kill_pid_info_as_cred(int, struct siginfo *, struct pid *, 321extern int kill_pid_info_as_cred(int, struct siginfo *, struct pid *,
322 const struct cred *, u32); 322 const struct cred *);
323extern int kill_pgrp(struct pid *pid, int sig, int priv); 323extern int kill_pgrp(struct pid *pid, int sig, int priv);
324extern int kill_pid(struct pid *pid, int sig, int priv); 324extern int kill_pid(struct pid *pid, int sig, int priv);
325extern __must_check bool do_notify_parent(struct task_struct *, int); 325extern __must_check bool do_notify_parent(struct task_struct *, int);
diff --git a/include/linux/security.h b/include/linux/security.h
index 73f1ef625d40..3f5fd988ee87 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -347,7 +347,7 @@ int security_task_setscheduler(struct task_struct *p);
347int security_task_getscheduler(struct task_struct *p); 347int security_task_getscheduler(struct task_struct *p);
348int security_task_movememory(struct task_struct *p); 348int security_task_movememory(struct task_struct *p);
349int security_task_kill(struct task_struct *p, struct siginfo *info, 349int security_task_kill(struct task_struct *p, struct siginfo *info,
350 int sig, u32 secid); 350 int sig, const struct cred *cred);
351int security_task_prctl(int option, unsigned long arg2, unsigned long arg3, 351int security_task_prctl(int option, unsigned long arg2, unsigned long arg3,
352 unsigned long arg4, unsigned long arg5); 352 unsigned long arg4, unsigned long arg5);
353void security_task_to_inode(struct task_struct *p, struct inode *inode); 353void security_task_to_inode(struct task_struct *p, struct inode *inode);
@@ -1010,7 +1010,7 @@ static inline int security_task_movememory(struct task_struct *p)
1010 1010
1011static inline int security_task_kill(struct task_struct *p, 1011static inline int security_task_kill(struct task_struct *p,
1012 struct siginfo *info, int sig, 1012 struct siginfo *info, int sig,
1013 u32 secid) 1013 const struct cred *cred)
1014{ 1014{
1015 return 0; 1015 return 0;
1016} 1016}
diff --git a/kernel/signal.c b/kernel/signal.c
index c6e4c83dc090..b033292f4beb 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -770,7 +770,7 @@ static int check_kill_permission(int sig, struct siginfo *info,
770 } 770 }
771 } 771 }
772 772
773 return security_task_kill(t, info, sig, 0); 773 return security_task_kill(t, info, sig, NULL);
774} 774}
775 775
776/** 776/**
@@ -1361,7 +1361,7 @@ static int kill_as_cred_perm(const struct cred *cred,
1361 1361
1362/* like kill_pid_info(), but doesn't use uid/euid of "current" */ 1362/* like kill_pid_info(), but doesn't use uid/euid of "current" */
1363int kill_pid_info_as_cred(int sig, struct siginfo *info, struct pid *pid, 1363int kill_pid_info_as_cred(int sig, struct siginfo *info, struct pid *pid,
1364 const struct cred *cred, u32 secid) 1364 const struct cred *cred)
1365{ 1365{
1366 int ret = -EINVAL; 1366 int ret = -EINVAL;
1367 struct task_struct *p; 1367 struct task_struct *p;
@@ -1380,7 +1380,7 @@ int kill_pid_info_as_cred(int sig, struct siginfo *info, struct pid *pid,
1380 ret = -EPERM; 1380 ret = -EPERM;
1381 goto out_unlock; 1381 goto out_unlock;
1382 } 1382 }
1383 ret = security_task_kill(p, info, sig, secid); 1383 ret = security_task_kill(p, info, sig, cred);
1384 if (ret) 1384 if (ret)
1385 goto out_unlock; 1385 goto out_unlock;
1386 1386
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 9a65eeaf7dfa..77bdfa7f8428 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -717,16 +717,23 @@ static int apparmor_task_setrlimit(struct task_struct *task,
717} 717}
718 718
719static int apparmor_task_kill(struct task_struct *target, struct siginfo *info, 719static int apparmor_task_kill(struct task_struct *target, struct siginfo *info,
720 int sig, u32 secid) 720 int sig, const struct cred *cred)
721{ 721{
722 struct aa_label *cl, *tl; 722 struct aa_label *cl, *tl;
723 int error; 723 int error;
724 724
725 if (secid) 725 if (cred) {
726 /* TODO: after secid to label mapping is done. 726 /*
727 * Dealing with USB IO specific behavior 727 * Dealing with USB IO specific behavior
728 */ 728 */
729 return 0; 729 cl = aa_get_newest_cred_label(cred);
730 tl = aa_get_task_label(target);
731 error = aa_may_signal(cl, tl, sig);
732 aa_put_label(cl);
733 aa_put_label(tl);
734 return error;
735 }
736
730 cl = __begin_current_label_crit_section(); 737 cl = __begin_current_label_crit_section();
731 tl = aa_get_task_label(target); 738 tl = aa_get_task_label(target);
732 error = aa_may_signal(cl, tl, sig); 739 error = aa_may_signal(cl, tl, sig);
diff --git a/security/security.c b/security/security.c
index 1cd8526cb0b7..14c291910d25 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1114,9 +1114,9 @@ int security_task_movememory(struct task_struct *p)
1114} 1114}
1115 1115
1116int security_task_kill(struct task_struct *p, struct siginfo *info, 1116int security_task_kill(struct task_struct *p, struct siginfo *info,
1117 int sig, u32 secid) 1117 int sig, const struct cred *cred)
1118{ 1118{
1119 return call_int_hook(task_kill, 0, p, info, sig, secid); 1119 return call_int_hook(task_kill, 0, p, info, sig, cred);
1120} 1120}
1121 1121
1122int security_task_prctl(int option, unsigned long arg2, unsigned long arg3, 1122int security_task_prctl(int option, unsigned long arg2, unsigned long arg3,
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 8644d864e3c1..8abd542c6b7c 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4036,16 +4036,19 @@ static int selinux_task_movememory(struct task_struct *p)
4036} 4036}
4037 4037
4038static int selinux_task_kill(struct task_struct *p, struct siginfo *info, 4038static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
4039 int sig, u32 secid) 4039 int sig, const struct cred *cred)
4040{ 4040{
4041 u32 secid;
4041 u32 perm; 4042 u32 perm;
4042 4043
4043 if (!sig) 4044 if (!sig)
4044 perm = PROCESS__SIGNULL; /* null signal; existence test */ 4045 perm = PROCESS__SIGNULL; /* null signal; existence test */
4045 else 4046 else
4046 perm = signal_to_av(sig); 4047 perm = signal_to_av(sig);
4047 if (!secid) 4048 if (!cred)
4048 secid = current_sid(); 4049 secid = current_sid();
4050 else
4051 secid = cred_sid(cred);
4049 return avc_has_perm(secid, task_sid(p), SECCLASS_PROCESS, perm, NULL); 4052 return avc_has_perm(secid, task_sid(p), SECCLASS_PROCESS, perm, NULL);
4050} 4053}
4051 4054
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 03fdecba93bb..feada2665322 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -2228,15 +2228,13 @@ static int smack_task_movememory(struct task_struct *p)
2228 * @p: the task object 2228 * @p: the task object
2229 * @info: unused 2229 * @info: unused
2230 * @sig: unused 2230 * @sig: unused
2231 * @secid: identifies the smack to use in lieu of current's 2231 * @cred: identifies the cred to use in lieu of current's
2232 * 2232 *
2233 * Return 0 if write access is permitted 2233 * Return 0 if write access is permitted
2234 * 2234 *
2235 * The secid behavior is an artifact of an SELinux hack
2236 * in the USB code. Someday it may go away.
2237 */ 2235 */
2238static int smack_task_kill(struct task_struct *p, struct siginfo *info, 2236static int smack_task_kill(struct task_struct *p, struct siginfo *info,
2239 int sig, u32 secid) 2237 int sig, const struct cred *cred)
2240{ 2238{
2241 struct smk_audit_info ad; 2239 struct smk_audit_info ad;
2242 struct smack_known *skp; 2240 struct smack_known *skp;
@@ -2252,17 +2250,17 @@ static int smack_task_kill(struct task_struct *p, struct siginfo *info,
2252 * Sending a signal requires that the sender 2250 * Sending a signal requires that the sender
2253 * can write the receiver. 2251 * can write the receiver.
2254 */ 2252 */
2255 if (secid == 0) { 2253 if (cred == NULL) {
2256 rc = smk_curacc(tkp, MAY_DELIVER, &ad); 2254 rc = smk_curacc(tkp, MAY_DELIVER, &ad);
2257 rc = smk_bu_task(p, MAY_DELIVER, rc); 2255 rc = smk_bu_task(p, MAY_DELIVER, rc);
2258 return rc; 2256 return rc;
2259 } 2257 }
2260 /* 2258 /*
2261 * If the secid isn't 0 we're dealing with some USB IO 2259 * If the cred isn't NULL we're dealing with some USB IO
2262 * specific behavior. This is not clean. For one thing 2260 * specific behavior. This is not clean. For one thing
2263 * we can't take privilege into account. 2261 * we can't take privilege into account.
2264 */ 2262 */
2265 skp = smack_from_secid(secid); 2263 skp = smk_of_task(cred->security);
2266 rc = smk_access(skp, tkp, MAY_DELIVER, &ad); 2264 rc = smk_access(skp, tkp, MAY_DELIVER, &ad);
2267 rc = smk_bu_note("USB signal", skp, tkp, MAY_DELIVER, rc); 2265 rc = smk_bu_note("USB signal", skp, tkp, MAY_DELIVER, rc);
2268 return rc; 2266 return rc;