diff options
-rw-r--r-- | fs/namespace.c | 25 | ||||
-rw-r--r-- | include/linux/fs_struct.h | 2 | ||||
-rw-r--r-- | kernel/user_namespace.c | 9 |
3 files changed, 36 insertions, 0 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index 7bdf7907413f..c48b0d3ba812 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -2681,3 +2681,28 @@ bool our_mnt(struct vfsmount *mnt) { return check_mnt(real_mount(mnt)); } + +bool current_chrooted(void) +{ + /* Does the current process have a non-standard root */ + struct path ns_root; + struct path fs_root; + bool chrooted; + + /* Find the namespace root */ + ns_root.mnt = ¤t->nsproxy->mnt_ns->root->mnt; + ns_root.dentry = ns_root.mnt->mnt_root; + path_get(&ns_root); + while (d_mountpoint(ns_root.dentry) && follow_down_one(&ns_root)) + ; + + get_fs_root(current->fs, &fs_root); + + chrooted = !path_equal(&fs_root, &ns_root); + + path_put(&fs_root); + path_put(&ns_root); + + return chrooted; +} + diff --git a/include/linux/fs_struct.h b/include/linux/fs_struct.h index 003dc0fd7347..961cdaadef49 100644 --- a/include/linux/fs_struct.h +++ b/include/linux/fs_struct.h @@ -51,4 +51,6 @@ static inline void get_fs_root_and_pwd(struct fs_struct *fs, struct path *root, spin_unlock(&fs->lock); } +extern bool current_chrooted(void); + #endif /* _LINUX_FS_STRUCT_H */ diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c index 86602316422d..a74dc5b9d16e 100644 --- a/kernel/user_namespace.c +++ b/kernel/user_namespace.c @@ -39,6 +39,15 @@ int create_user_ns(struct cred *new) kuid_t owner = new->euid; kgid_t group = new->egid; + /* + * Verify that we can not violate the policy of which files + * may be accessed that is specified by the root directory, + * by verifing that the root directory is at the root of the + * mount namespace which allows all files to be accessed. + */ + if (current_chrooted()) + return -EPERM; + /* The creator needs a mapping in the parent user namespace * or else we won't be able to reasonably tell userspace who * created a user_namespace. |