aboutsummaryrefslogtreecommitdiffstats
path: root/ipc/util.c
diff options
context:
space:
mode:
authorSerge E. Hallyn <serge@hallyn.com>2011-03-23 19:43:24 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-03-23 22:47:08 -0400
commitb0e77598f87107001a00b8a4ece9c95e4254ccc4 (patch)
tree2738276570e4faa7c92a64521c192f04dca93801 /ipc/util.c
parentb515498f5bb5f38fc0e390b4ff7d00b6077de127 (diff)
userns: user namespaces: convert several capable() calls
CAP_IPC_OWNER and CAP_IPC_LOCK can be checked against current_user_ns(), because the resource comes from current's own ipc namespace. setuid/setgid are to uids in own namespace, so again checks can be against current_user_ns(). Changelog: Jan 11: Use task_ns_capable() in place of sched_capable(). Jan 11: Use nsown_capable() as suggested by Bastian Blank. Jan 11: Clarify (hopefully) some logic in futex and sched.c Feb 15: use ns_capable for ipc, not nsown_capable Feb 23: let copy_ipcs handle setting ipc_ns->user_ns Feb 23: pass ns down rather than taking it from current [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Serge E. Hallyn <serge.hallyn@canonical.com> Acked-by: "Eric W. Biederman" <ebiederm@xmission.com> Acked-by: Daniel Lezcano <daniel.lezcano@free.fr> Acked-by: David Howells <dhowells@redhat.com> Cc: James Morris <jmorris@namei.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'ipc/util.c')
-rw-r--r--ipc/util.c26
1 files changed, 16 insertions, 10 deletions
diff --git a/ipc/util.c b/ipc/util.c
index 69a0cc13d966..8fd1b891ec0c 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -329,12 +329,14 @@ retry:
329 * 329 *
330 * It is called with ipc_ids.rw_mutex and ipcp->lock held. 330 * It is called with ipc_ids.rw_mutex and ipcp->lock held.
331 */ 331 */
332static int ipc_check_perms(struct kern_ipc_perm *ipcp, struct ipc_ops *ops, 332static int ipc_check_perms(struct ipc_namespace *ns,
333 struct ipc_params *params) 333 struct kern_ipc_perm *ipcp,
334 struct ipc_ops *ops,
335 struct ipc_params *params)
334{ 336{
335 int err; 337 int err;
336 338
337 if (ipcperms(ipcp, params->flg)) 339 if (ipcperms(ns, ipcp, params->flg))
338 err = -EACCES; 340 err = -EACCES;
339 else { 341 else {
340 err = ops->associate(ipcp, params->flg); 342 err = ops->associate(ipcp, params->flg);
@@ -396,7 +398,7 @@ retry:
396 * ipc_check_perms returns the IPC id on 398 * ipc_check_perms returns the IPC id on
397 * success 399 * success
398 */ 400 */
399 err = ipc_check_perms(ipcp, ops, params); 401 err = ipc_check_perms(ns, ipcp, ops, params);
400 } 402 }
401 ipc_unlock(ipcp); 403 ipc_unlock(ipcp);
402 } 404 }
@@ -610,10 +612,12 @@ void ipc_rcu_putref(void *ptr)
610 * 612 *
611 * Check user, group, other permissions for access 613 * Check user, group, other permissions for access
612 * to ipc resources. return 0 if allowed 614 * to ipc resources. return 0 if allowed
615 *
616 * @flag will most probably be 0 or S_...UGO from <linux/stat.h>
613 */ 617 */
614 618
615int ipcperms (struct kern_ipc_perm *ipcp, short flag) 619int ipcperms(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp, short flag)
616{ /* flag will most probably be 0 or S_...UGO from <linux/stat.h> */ 620{
617 uid_t euid = current_euid(); 621 uid_t euid = current_euid();
618 int requested_mode, granted_mode; 622 int requested_mode, granted_mode;
619 623
@@ -627,7 +631,7 @@ int ipcperms (struct kern_ipc_perm *ipcp, short flag)
627 granted_mode >>= 3; 631 granted_mode >>= 3;
628 /* is there some bit set in requested_mode but not in granted_mode? */ 632 /* is there some bit set in requested_mode but not in granted_mode? */
629 if ((requested_mode & ~granted_mode & 0007) && 633 if ((requested_mode & ~granted_mode & 0007) &&
630 !capable(CAP_IPC_OWNER)) 634 !ns_capable(ns->user_ns, CAP_IPC_OWNER))
631 return -1; 635 return -1;
632 636
633 return security_ipc_permission(ipcp, flag); 637 return security_ipc_permission(ipcp, flag);
@@ -765,6 +769,7 @@ void ipc_update_perm(struct ipc64_perm *in, struct kern_ipc_perm *out)
765 769
766/** 770/**
767 * ipcctl_pre_down - retrieve an ipc and check permissions for some IPC_XXX cmd 771 * ipcctl_pre_down - retrieve an ipc and check permissions for some IPC_XXX cmd
772 * @ids: the ipc namespace
768 * @ids: the table of ids where to look for the ipc 773 * @ids: the table of ids where to look for the ipc
769 * @id: the id of the ipc to retrieve 774 * @id: the id of the ipc to retrieve
770 * @cmd: the cmd to check 775 * @cmd: the cmd to check
@@ -779,7 +784,8 @@ void ipc_update_perm(struct ipc64_perm *in, struct kern_ipc_perm *out)
779 * - returns the ipc with both ipc and rw_mutex locks held in case of success 784 * - returns the ipc with both ipc and rw_mutex locks held in case of success
780 * or an err-code without any lock held otherwise. 785 * or an err-code without any lock held otherwise.
781 */ 786 */
782struct kern_ipc_perm *ipcctl_pre_down(struct ipc_ids *ids, int id, int cmd, 787struct kern_ipc_perm *ipcctl_pre_down(struct ipc_namespace *ns,
788 struct ipc_ids *ids, int id, int cmd,
783 struct ipc64_perm *perm, int extra_perm) 789 struct ipc64_perm *perm, int extra_perm)
784{ 790{
785 struct kern_ipc_perm *ipcp; 791 struct kern_ipc_perm *ipcp;
@@ -799,8 +805,8 @@ struct kern_ipc_perm *ipcctl_pre_down(struct ipc_ids *ids, int id, int cmd,
799 perm->gid, perm->mode); 805 perm->gid, perm->mode);
800 806
801 euid = current_euid(); 807 euid = current_euid();
802 if (euid == ipcp->cuid || 808 if (euid == ipcp->cuid || euid == ipcp->uid ||
803 euid == ipcp->uid || capable(CAP_SYS_ADMIN)) 809 ns_capable(ns->user_ns, CAP_SYS_ADMIN))
804 return ipcp; 810 return ipcp;
805 811
806 err = -EPERM; 812 err = -EPERM;