diff options
author | Serge E. Hallyn <serge@hallyn.com> | 2011-03-23 19:43:24 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-23 22:47:08 -0400 |
commit | b0e77598f87107001a00b8a4ece9c95e4254ccc4 (patch) | |
tree | 2738276570e4faa7c92a64521c192f04dca93801 /ipc/util.c | |
parent | b515498f5bb5f38fc0e390b4ff7d00b6077de127 (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.c | 26 |
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 | */ |
332 | static int ipc_check_perms(struct kern_ipc_perm *ipcp, struct ipc_ops *ops, | 332 | static 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 | ||
615 | int ipcperms (struct kern_ipc_perm *ipcp, short flag) | 619 | int 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 | */ |
782 | struct kern_ipc_perm *ipcctl_pre_down(struct ipc_ids *ids, int id, int cmd, | 787 | struct 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; |