aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/user_namespace.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/user_namespace.c')
-rw-r--r--kernel/user_namespace.c37
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
25static struct kmem_cache *user_ns_cachep __read_mostly; 26static struct kmem_cache *user_ns_cachep __read_mostly;
26 27
27static bool new_idmap_permitted(struct user_namespace *ns, int cap_setid, 28static 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
30static void set_cred_user_ns(struct cred *cred, struct user_namespace *user_ns) 32static 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
778static bool new_idmap_permitted(struct user_namespace *ns, int cap_setid, 791static 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(&current->mm->mm_users) > 1) 853 if (atomic_read(&current->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