aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/signal.c
diff options
context:
space:
mode:
authorSerge Hallyn <serge.hallyn@canonical.com>2011-09-26 11:45:18 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2011-09-29 16:13:08 -0400
commitd178bc3a708f39cbfefc3fab37032d3f2511b4ec (patch)
treeaf492e92e140f1f6abad5a377a269ef7335824de /kernel/signal.c
parentedb2b255a0bebac5aeb17c7613aeb76ba4e6c63c (diff)
user namespace: usb: make usb urbs user namespace aware (v2)
Add to the dev_state and alloc_async structures the user namespace corresponding to the uid and euid. Pass these to kill_pid_info_as_uid(), which can then implement a proper, user-namespace-aware uid check. Changelog: Sep 20: Per Oleg's suggestion: Instead of caching and passing user namespace, uid, and euid each separately, pass a struct cred. Sep 26: Address Alan Stern's comments: don't define a struct cred at usbdev_open(), and take and put a cred at async_completed() to ensure it lasts for the duration of kill_pid_info_as_cred(). Signed-off-by: Serge Hallyn <serge.hallyn@canonical.com> Cc: Oleg Nesterov <oleg@redhat.com> Cc: "Eric W. Biederman" <ebiederm@xmission.com> Cc: Tejun Heo <tj@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'kernel/signal.c')
-rw-r--r--kernel/signal.c24
1 files changed, 16 insertions, 8 deletions
diff --git a/kernel/signal.c b/kernel/signal.c
index 291c9700be75..d252be2d3de5 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1344,13 +1344,24 @@ int kill_proc_info(int sig, struct siginfo *info, pid_t pid)
1344 return error; 1344 return error;
1345} 1345}
1346 1346
1347static int kill_as_cred_perm(const struct cred *cred,
1348 struct task_struct *target)
1349{
1350 const struct cred *pcred = __task_cred(target);
1351 if (cred->user_ns != pcred->user_ns)
1352 return 0;
1353 if (cred->euid != pcred->suid && cred->euid != pcred->uid &&
1354 cred->uid != pcred->suid && cred->uid != pcred->uid)
1355 return 0;
1356 return 1;
1357}
1358
1347/* like kill_pid_info(), but doesn't use uid/euid of "current" */ 1359/* like kill_pid_info(), but doesn't use uid/euid of "current" */
1348int kill_pid_info_as_uid(int sig, struct siginfo *info, struct pid *pid, 1360int kill_pid_info_as_cred(int sig, struct siginfo *info, struct pid *pid,
1349 uid_t uid, uid_t euid, u32 secid) 1361 const struct cred *cred, u32 secid)
1350{ 1362{
1351 int ret = -EINVAL; 1363 int ret = -EINVAL;
1352 struct task_struct *p; 1364 struct task_struct *p;
1353 const struct cred *pcred;
1354 unsigned long flags; 1365 unsigned long flags;
1355 1366
1356 if (!valid_signal(sig)) 1367 if (!valid_signal(sig))
@@ -1362,10 +1373,7 @@ int kill_pid_info_as_uid(int sig, struct siginfo *info, struct pid *pid,
1362 ret = -ESRCH; 1373 ret = -ESRCH;
1363 goto out_unlock; 1374 goto out_unlock;
1364 } 1375 }
1365 pcred = __task_cred(p); 1376 if (si_fromuser(info) && !kill_as_cred_perm(cred, p)) {
1366 if (si_fromuser(info) &&
1367 euid != pcred->suid && euid != pcred->uid &&
1368 uid != pcred->suid && uid != pcred->uid) {
1369 ret = -EPERM; 1377 ret = -EPERM;
1370 goto out_unlock; 1378 goto out_unlock;
1371 } 1379 }
@@ -1384,7 +1392,7 @@ out_unlock:
1384 rcu_read_unlock(); 1392 rcu_read_unlock();
1385 return ret; 1393 return ret;
1386} 1394}
1387EXPORT_SYMBOL_GPL(kill_pid_info_as_uid); 1395EXPORT_SYMBOL_GPL(kill_pid_info_as_cred);
1388 1396
1389/* 1397/*
1390 * kill_something_info() interprets pid in interesting ways just like kill(2). 1398 * kill_something_info() interprets pid in interesting ways just like kill(2).