diff options
Diffstat (limited to 'kernel/user_namespace.c')
-rw-r--r-- | kernel/user_namespace.c | 37 |
1 files changed, 28 insertions, 9 deletions
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c index 8b650837083e..e134d8f365dd 100644 --- a/kernel/user_namespace.c +++ b/kernel/user_namespace.c | |||
@@ -21,10 +21,12 @@ | |||
21 | #include <linux/uaccess.h> | 21 | #include <linux/uaccess.h> |
22 | #include <linux/ctype.h> | 22 | #include <linux/ctype.h> |
23 | #include <linux/projid.h> | 23 | #include <linux/projid.h> |
24 | #include <linux/fs_struct.h> | ||
24 | 25 | ||
25 | static struct kmem_cache *user_ns_cachep __read_mostly; | 26 | static struct kmem_cache *user_ns_cachep __read_mostly; |
26 | 27 | ||
27 | 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, | ||
28 | struct uid_gid_map *map); | 30 | struct uid_gid_map *map); |
29 | 31 | ||
30 | 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) |
@@ -60,6 +62,15 @@ int create_user_ns(struct cred *new) | |||
60 | kgid_t group = new->egid; | 62 | kgid_t group = new->egid; |
61 | int ret; | 63 | int ret; |
62 | 64 | ||
65 | /* | ||
66 | * Verify that we can not violate the policy of which files | ||
67 | * may be accessed that is specified by the root directory, | ||
68 | * by verifing that the root directory is at the root of the | ||
69 | * mount namespace which allows all files to be accessed. | ||
70 | */ | ||
71 | if (current_chrooted()) | ||
72 | return -EPERM; | ||
73 | |||
63 | /* The creator needs a mapping in the parent user namespace | 74 | /* The creator needs a mapping in the parent user namespace |
64 | * or else we won't be able to reasonably tell userspace who | 75 | * or else we won't be able to reasonably tell userspace who |
65 | * created a user_namespace. | 76 | * created a user_namespace. |
@@ -86,6 +97,8 @@ int create_user_ns(struct cred *new) | |||
86 | 97 | ||
87 | set_cred_user_ns(new, ns); | 98 | set_cred_user_ns(new, ns); |
88 | 99 | ||
100 | update_mnt_policy(ns); | ||
101 | |||
89 | return 0; | 102 | return 0; |
90 | } | 103 | } |
91 | 104 | ||
@@ -600,10 +613,10 @@ static ssize_t map_write(struct file *file, const char __user *buf, | |||
600 | if (map->nr_extents != 0) | 613 | if (map->nr_extents != 0) |
601 | goto out; | 614 | goto out; |
602 | 615 | ||
603 | /* Require the appropriate privilege CAP_SETUID or CAP_SETGID | 616 | /* |
604 | * over the user namespace in order to set the id mapping. | 617 | * Adjusting namespace settings requires capabilities on the target. |
605 | */ | 618 | */ |
606 | if (cap_valid(cap_setid) && !ns_capable(ns, cap_setid)) | 619 | if (cap_valid(cap_setid) && !file_ns_capable(file, ns, CAP_SYS_ADMIN)) |
607 | goto out; | 620 | goto out; |
608 | 621 | ||
609 | /* Get a buffer */ | 622 | /* Get a buffer */ |
@@ -688,7 +701,7 @@ static ssize_t map_write(struct file *file, const char __user *buf, | |||
688 | 701 | ||
689 | ret = -EPERM; | 702 | ret = -EPERM; |
690 | /* 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. */ |
691 | if (!new_idmap_permitted(ns, cap_setid, &new_map)) | 704 | if (!new_idmap_permitted(file, ns, cap_setid, &new_map)) |
692 | goto out; | 705 | goto out; |
693 | 706 | ||
694 | /* Map the lower ids from the parent user namespace to the | 707 | /* Map the lower ids from the parent user namespace to the |
@@ -775,7 +788,8 @@ ssize_t proc_projid_map_write(struct file *file, const char __user *buf, size_t | |||
775 | &ns->projid_map, &ns->parent->projid_map); | 788 | &ns->projid_map, &ns->parent->projid_map); |
776 | } | 789 | } |
777 | 790 | ||
778 | 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, | ||
779 | struct uid_gid_map *new_map) | 793 | struct uid_gid_map *new_map) |
780 | { | 794 | { |
781 | /* Allow mapping to your own filesystem ids */ | 795 | /* Allow mapping to your own filesystem ids */ |
@@ -783,12 +797,12 @@ static bool new_idmap_permitted(struct user_namespace *ns, int cap_setid, | |||
783 | u32 id = new_map->extent[0].lower_first; | 797 | u32 id = new_map->extent[0].lower_first; |
784 | if (cap_setid == CAP_SETUID) { | 798 | if (cap_setid == CAP_SETUID) { |
785 | kuid_t uid = make_kuid(ns->parent, id); | 799 | kuid_t uid = make_kuid(ns->parent, id); |
786 | if (uid_eq(uid, current_fsuid())) | 800 | if (uid_eq(uid, file->f_cred->fsuid)) |
787 | return true; | 801 | return true; |
788 | } | 802 | } |
789 | else if (cap_setid == CAP_SETGID) { | 803 | else if (cap_setid == CAP_SETGID) { |
790 | kgid_t gid = make_kgid(ns->parent, id); | 804 | kgid_t gid = make_kgid(ns->parent, id); |
791 | if (gid_eq(gid, current_fsgid())) | 805 | if (gid_eq(gid, file->f_cred->fsgid)) |
792 | return true; | 806 | return true; |
793 | } | 807 | } |
794 | } | 808 | } |
@@ -799,8 +813,10 @@ static bool new_idmap_permitted(struct user_namespace *ns, int cap_setid, | |||
799 | 813 | ||
800 | /* Allow the specified ids if we have the appropriate capability | 814 | /* Allow the specified ids if we have the appropriate capability |
801 | * (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. | ||
802 | */ | 817 | */ |
803 | if (ns_capable(ns->parent, cap_setid)) | 818 | if (ns_capable(ns->parent, cap_setid) && |
819 | file_ns_capable(file, ns->parent, cap_setid)) | ||
804 | return true; | 820 | return true; |
805 | 821 | ||
806 | return false; | 822 | return false; |
@@ -837,6 +853,9 @@ static int userns_install(struct nsproxy *nsproxy, void *ns) | |||
837 | if (atomic_read(¤t->mm->mm_users) > 1) | 853 | if (atomic_read(¤t->mm->mm_users) > 1) |
838 | return -EINVAL; | 854 | return -EINVAL; |
839 | 855 | ||
856 | if (current->fs->users != 1) | ||
857 | return -EINVAL; | ||
858 | |||
840 | if (!ns_capable(user_ns, CAP_SYS_ADMIN)) | 859 | if (!ns_capable(user_ns, CAP_SYS_ADMIN)) |
841 | return -EPERM; | 860 | return -EPERM; |
842 | 861 | ||