diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2013-04-14 16:47:02 -0400 |
---|---|---|
committer | Andy Lutomirski <luto@amacapital.net> | 2013-04-14 21:11:14 -0400 |
commit | 6708075f104c3c9b04b23336bb0366ca30c3931b (patch) | |
tree | 4e99cf865cea3d809bfadda9eec45dcf29454bee /kernel/user_namespace.c | |
parent | 6c4c4d4bdaff7ec0b7b26da67d741f639727c934 (diff) |
userns: Don't let unprivileged users trick privileged users into setting the id_map
When we require privilege for setting /proc/<pid>/uid_map or
/proc/<pid>/gid_map no longer allow an unprivileged user to
open the file and pass it to a privileged program to write
to the file.
Instead when privilege is required require both the opener and the
writer to have the necessary capabilities.
I have tested this code and verified that setting /proc/<pid>/uid_map
fails when an unprivileged user opens the file and a privielged user
attempts to set the mapping, that unprivileged users can still map
their own id, and that a privileged users can still setup an arbitrary
mapping.
Reported-by: Andy Lutomirski <luto@amacapital.net>
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: Andy Lutomirski <luto@amacapital.net>
Diffstat (limited to 'kernel/user_namespace.c')
-rw-r--r-- | kernel/user_namespace.c | 12 |
1 files changed, 8 insertions, 4 deletions
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c index a54f26f82eb2..e2d4ace4481b 100644 --- a/kernel/user_namespace.c +++ b/kernel/user_namespace.c | |||
@@ -25,7 +25,8 @@ | |||
25 | 25 | ||
26 | static struct kmem_cache *user_ns_cachep __read_mostly; | 26 | static struct kmem_cache *user_ns_cachep __read_mostly; |
27 | 27 | ||
28 | static bool new_idmap_permitted(struct user_namespace *ns, int cap_setid, | 28 | static bool new_idmap_permitted(const struct file *file, |
29 | struct user_namespace *ns, int cap_setid, | ||
29 | struct uid_gid_map *map); | 30 | struct uid_gid_map *map); |
30 | 31 | ||
31 | static void set_cred_user_ns(struct cred *cred, struct user_namespace *user_ns) | 32 | static void set_cred_user_ns(struct cred *cred, struct user_namespace *user_ns) |
@@ -700,7 +701,7 @@ static ssize_t map_write(struct file *file, const char __user *buf, | |||
700 | 701 | ||
701 | ret = -EPERM; | 702 | ret = -EPERM; |
702 | /* Validate the user is allowed to use user id's mapped to. */ | 703 | /* Validate the user is allowed to use user id's mapped to. */ |
703 | if (!new_idmap_permitted(ns, cap_setid, &new_map)) | 704 | if (!new_idmap_permitted(file, ns, cap_setid, &new_map)) |
704 | goto out; | 705 | goto out; |
705 | 706 | ||
706 | /* Map the lower ids from the parent user namespace to the | 707 | /* Map the lower ids from the parent user namespace to the |
@@ -787,7 +788,8 @@ ssize_t proc_projid_map_write(struct file *file, const char __user *buf, size_t | |||
787 | &ns->projid_map, &ns->parent->projid_map); | 788 | &ns->projid_map, &ns->parent->projid_map); |
788 | } | 789 | } |
789 | 790 | ||
790 | static bool new_idmap_permitted(struct user_namespace *ns, int cap_setid, | 791 | static bool new_idmap_permitted(const struct file *file, |
792 | struct user_namespace *ns, int cap_setid, | ||
791 | struct uid_gid_map *new_map) | 793 | struct uid_gid_map *new_map) |
792 | { | 794 | { |
793 | /* Allow mapping to your own filesystem ids */ | 795 | /* Allow mapping to your own filesystem ids */ |
@@ -811,8 +813,10 @@ static bool new_idmap_permitted(struct user_namespace *ns, int cap_setid, | |||
811 | 813 | ||
812 | /* Allow the specified ids if we have the appropriate capability | 814 | /* Allow the specified ids if we have the appropriate capability |
813 | * (CAP_SETUID or CAP_SETGID) over the parent user namespace. | 815 | * (CAP_SETUID or CAP_SETGID) over the parent user namespace. |
816 | * And the opener of the id file also had the approprpiate capability. | ||
814 | */ | 817 | */ |
815 | if (ns_capable(ns->parent, cap_setid)) | 818 | if (ns_capable(ns->parent, cap_setid) && |
819 | file_ns_capable(file, ns->parent, cap_setid)) | ||
816 | return true; | 820 | return true; |
817 | 821 | ||
818 | return false; | 822 | return false; |