diff options
Diffstat (limited to 'common/recipes-kernel/linux/linux-amd/CVE-2014-8989/0001-userns-Kill-nsown_capable-it-makes-the-wrong-thing-e.patch')
-rw-r--r-- | common/recipes-kernel/linux/linux-amd/CVE-2014-8989/0001-userns-Kill-nsown_capable-it-makes-the-wrong-thing-e.patch | 281 |
1 files changed, 281 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/linux-amd/CVE-2014-8989/0001-userns-Kill-nsown_capable-it-makes-the-wrong-thing-e.patch b/common/recipes-kernel/linux/linux-amd/CVE-2014-8989/0001-userns-Kill-nsown_capable-it-makes-the-wrong-thing-e.patch new file mode 100644 index 00000000..b3ec4472 --- /dev/null +++ b/common/recipes-kernel/linux/linux-amd/CVE-2014-8989/0001-userns-Kill-nsown_capable-it-makes-the-wrong-thing-e.patch @@ -0,0 +1,281 @@ +From c7b96acf1456ef127fef461fcfedb54b81fecfbb Mon Sep 17 00:00:00 2001 +From: "Eric W. Biederman" <ebiederm@xmission.com> +Date: Wed, 20 Mar 2013 12:49:49 -0700 +Subject: [PATCH] userns: Kill nsown_capable it makes the wrong thing easy + +nsown_capable is a special case of ns_capable essentially for just CAP_SETUID and +CAP_SETGID. For the existing users it doesn't noticably simplify things and +from the suggested patches I have seen it encourages people to do the wrong +thing. So remove nsown_capable. + +Acked-by: Serge Hallyn <serge.hallyn@canonical.com> +Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com> +--- + fs/namespace.c | 4 ++-- + fs/open.c | 2 +- + include/linux/capability.h | 1 - + ipc/namespace.c | 2 +- + kernel/capability.c | 12 ------------ + kernel/groups.c | 2 +- + kernel/pid_namespace.c | 2 +- + kernel/sys.c | 20 ++++++++++---------- + kernel/uid16.c | 2 +- + kernel/utsname.c | 2 +- + net/core/net_namespace.c | 2 +- + net/core/scm.c | 4 ++-- + 12 files changed, 21 insertions(+), 34 deletions(-) + +diff --git a/fs/namespace.c b/fs/namespace.c +index 877e427..dc519a1 100644 +--- a/fs/namespace.c ++++ b/fs/namespace.c +@@ -2929,8 +2929,8 @@ static int mntns_install(struct nsproxy *nsproxy, void *ns) + struct path root; + + if (!ns_capable(mnt_ns->user_ns, CAP_SYS_ADMIN) || +- !nsown_capable(CAP_SYS_CHROOT) || +- !nsown_capable(CAP_SYS_ADMIN)) ++ !ns_capable(current_user_ns(), CAP_SYS_CHROOT) || ++ !ns_capable(current_user_ns(), CAP_SYS_ADMIN)) + return -EPERM; + + if (fs->users != 1) +diff --git a/fs/open.c b/fs/open.c +index 9156cb0..1c9d23f 100644 +--- a/fs/open.c ++++ b/fs/open.c +@@ -443,7 +443,7 @@ retry: + goto dput_and_out; + + error = -EPERM; +- if (!nsown_capable(CAP_SYS_CHROOT)) ++ if (!ns_capable(current_user_ns(), CAP_SYS_CHROOT)) + goto dput_and_out; + error = security_path_chroot(&path); + if (error) +diff --git a/include/linux/capability.h b/include/linux/capability.h +index d9a4f7f..a6ee1f9 100644 +--- a/include/linux/capability.h ++++ b/include/linux/capability.h +@@ -210,7 +210,6 @@ extern bool has_ns_capability_noaudit(struct task_struct *t, + struct user_namespace *ns, int cap); + extern bool capable(int cap); + extern bool ns_capable(struct user_namespace *ns, int cap); +-extern bool nsown_capable(int cap); + extern bool inode_capable(const struct inode *inode, int cap); + extern bool file_ns_capable(const struct file *file, struct user_namespace *ns, int cap); + +diff --git a/ipc/namespace.c b/ipc/namespace.c +index 7ee61bf..4be6581 100644 +--- a/ipc/namespace.c ++++ b/ipc/namespace.c +@@ -171,7 +171,7 @@ static int ipcns_install(struct nsproxy *nsproxy, void *new) + { + struct ipc_namespace *ns = new; + if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN) || +- !nsown_capable(CAP_SYS_ADMIN)) ++ !ns_capable(current_user_ns(), CAP_SYS_ADMIN)) + return -EPERM; + + /* Ditch state from the old ipc namespace */ +diff --git a/kernel/capability.c b/kernel/capability.c +index f6c2ce5..6fc1c8a 100644 +--- a/kernel/capability.c ++++ b/kernel/capability.c +@@ -433,18 +433,6 @@ bool capable(int cap) + EXPORT_SYMBOL(capable); + + /** +- * nsown_capable - Check superior capability to one's own user_ns +- * @cap: The capability in question +- * +- * Return true if the current task has the given superior capability +- * targeted at its own user namespace. +- */ +-bool nsown_capable(int cap) +-{ +- return ns_capable(current_user_ns(), cap); +-} +- +-/** + * inode_capable - Check superior capability over inode + * @inode: The inode in question + * @cap: The capability in question +diff --git a/kernel/groups.c b/kernel/groups.c +index 6b2588d..90cf1c3 100644 +--- a/kernel/groups.c ++++ b/kernel/groups.c +@@ -233,7 +233,7 @@ SYSCALL_DEFINE2(setgroups, int, gidsetsize, gid_t __user *, grouplist) + struct group_info *group_info; + int retval; + +- if (!nsown_capable(CAP_SETGID)) ++ if (!ns_capable(current_user_ns(), CAP_SETGID)) + return -EPERM; + if ((unsigned)gidsetsize > NGROUPS_MAX) + return -EINVAL; +diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c +index 6917e8e..ee1f6bb 100644 +--- a/kernel/pid_namespace.c ++++ b/kernel/pid_namespace.c +@@ -329,7 +329,7 @@ static int pidns_install(struct nsproxy *nsproxy, void *ns) + struct pid_namespace *ancestor, *new = ns; + + if (!ns_capable(new->user_ns, CAP_SYS_ADMIN) || +- !nsown_capable(CAP_SYS_ADMIN)) ++ !ns_capable(current_user_ns(), CAP_SYS_ADMIN)) + return -EPERM; + + /* +diff --git a/kernel/sys.c b/kernel/sys.c +index 771129b..c18ecca 100644 +--- a/kernel/sys.c ++++ b/kernel/sys.c +@@ -337,7 +337,7 @@ SYSCALL_DEFINE2(setregid, gid_t, rgid, gid_t, egid) + if (rgid != (gid_t) -1) { + if (gid_eq(old->gid, krgid) || + gid_eq(old->egid, krgid) || +- nsown_capable(CAP_SETGID)) ++ ns_capable(old->user_ns, CAP_SETGID)) + new->gid = krgid; + else + goto error; +@@ -346,7 +346,7 @@ SYSCALL_DEFINE2(setregid, gid_t, rgid, gid_t, egid) + if (gid_eq(old->gid, kegid) || + gid_eq(old->egid, kegid) || + gid_eq(old->sgid, kegid) || +- nsown_capable(CAP_SETGID)) ++ ns_capable(old->user_ns, CAP_SETGID)) + new->egid = kegid; + else + goto error; +@@ -387,7 +387,7 @@ SYSCALL_DEFINE1(setgid, gid_t, gid) + old = current_cred(); + + retval = -EPERM; +- if (nsown_capable(CAP_SETGID)) ++ if (ns_capable(old->user_ns, CAP_SETGID)) + new->gid = new->egid = new->sgid = new->fsgid = kgid; + else if (gid_eq(kgid, old->gid) || gid_eq(kgid, old->sgid)) + new->egid = new->fsgid = kgid; +@@ -471,7 +471,7 @@ SYSCALL_DEFINE2(setreuid, uid_t, ruid, uid_t, euid) + new->uid = kruid; + if (!uid_eq(old->uid, kruid) && + !uid_eq(old->euid, kruid) && +- !nsown_capable(CAP_SETUID)) ++ !ns_capable(old->user_ns, CAP_SETUID)) + goto error; + } + +@@ -480,7 +480,7 @@ SYSCALL_DEFINE2(setreuid, uid_t, ruid, uid_t, euid) + if (!uid_eq(old->uid, keuid) && + !uid_eq(old->euid, keuid) && + !uid_eq(old->suid, keuid) && +- !nsown_capable(CAP_SETUID)) ++ !ns_capable(old->user_ns, CAP_SETUID)) + goto error; + } + +@@ -534,7 +534,7 @@ SYSCALL_DEFINE1(setuid, uid_t, uid) + old = current_cred(); + + retval = -EPERM; +- if (nsown_capable(CAP_SETUID)) { ++ if (ns_capable(old->user_ns, CAP_SETUID)) { + new->suid = new->uid = kuid; + if (!uid_eq(kuid, old->uid)) { + retval = set_user(new); +@@ -591,7 +591,7 @@ SYSCALL_DEFINE3(setresuid, uid_t, ruid, uid_t, euid, uid_t, suid) + old = current_cred(); + + retval = -EPERM; +- if (!nsown_capable(CAP_SETUID)) { ++ if (!ns_capable(old->user_ns, CAP_SETUID)) { + if (ruid != (uid_t) -1 && !uid_eq(kruid, old->uid) && + !uid_eq(kruid, old->euid) && !uid_eq(kruid, old->suid)) + goto error; +@@ -673,7 +673,7 @@ SYSCALL_DEFINE3(setresgid, gid_t, rgid, gid_t, egid, gid_t, sgid) + old = current_cred(); + + retval = -EPERM; +- if (!nsown_capable(CAP_SETGID)) { ++ if (!ns_capable(old->user_ns, CAP_SETGID)) { + if (rgid != (gid_t) -1 && !gid_eq(krgid, old->gid) && + !gid_eq(krgid, old->egid) && !gid_eq(krgid, old->sgid)) + goto error; +@@ -744,7 +744,7 @@ SYSCALL_DEFINE1(setfsuid, uid_t, uid) + + if (uid_eq(kuid, old->uid) || uid_eq(kuid, old->euid) || + uid_eq(kuid, old->suid) || uid_eq(kuid, old->fsuid) || +- nsown_capable(CAP_SETUID)) { ++ ns_capable(old->user_ns, CAP_SETUID)) { + if (!uid_eq(kuid, old->fsuid)) { + new->fsuid = kuid; + if (security_task_fix_setuid(new, old, LSM_SETID_FS) == 0) +@@ -783,7 +783,7 @@ SYSCALL_DEFINE1(setfsgid, gid_t, gid) + + if (gid_eq(kgid, old->gid) || gid_eq(kgid, old->egid) || + gid_eq(kgid, old->sgid) || gid_eq(kgid, old->fsgid) || +- nsown_capable(CAP_SETGID)) { ++ ns_capable(old->user_ns, CAP_SETGID)) { + if (!gid_eq(kgid, old->fsgid)) { + new->fsgid = kgid; + goto change_okay; +diff --git a/kernel/uid16.c b/kernel/uid16.c +index f6c83d7..602e5bb 100644 +--- a/kernel/uid16.c ++++ b/kernel/uid16.c +@@ -176,7 +176,7 @@ SYSCALL_DEFINE2(setgroups16, int, gidsetsize, old_gid_t __user *, grouplist) + struct group_info *group_info; + int retval; + +- if (!nsown_capable(CAP_SETGID)) ++ if (!ns_capable(current_user_ns(), CAP_SETGID)) + return -EPERM; + if ((unsigned)gidsetsize > NGROUPS_MAX) + return -EINVAL; +diff --git a/kernel/utsname.c b/kernel/utsname.c +index 2fc8576..fd39312 100644 +--- a/kernel/utsname.c ++++ b/kernel/utsname.c +@@ -114,7 +114,7 @@ static int utsns_install(struct nsproxy *nsproxy, void *new) + struct uts_namespace *ns = new; + + if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN) || +- !nsown_capable(CAP_SYS_ADMIN)) ++ !ns_capable(current_user_ns(), CAP_SYS_ADMIN)) + return -EPERM; + + get_uts_ns(ns); +diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c +index f9765203..81d3a9a 100644 +--- a/net/core/net_namespace.c ++++ b/net/core/net_namespace.c +@@ -651,7 +651,7 @@ static int netns_install(struct nsproxy *nsproxy, void *ns) + struct net *net = ns; + + if (!ns_capable(net->user_ns, CAP_SYS_ADMIN) || +- !nsown_capable(CAP_SYS_ADMIN)) ++ !ns_capable(current_user_ns(), CAP_SYS_ADMIN)) + return -EPERM; + + put_net(nsproxy->net_ns); +diff --git a/net/core/scm.c b/net/core/scm.c +index 03795d0..c346f58 100644 +--- a/net/core/scm.c ++++ b/net/core/scm.c +@@ -56,9 +56,9 @@ static __inline__ int scm_check_creds(struct ucred *creds) + if ((creds->pid == task_tgid_vnr(current) || + ns_capable(current->nsproxy->pid_ns->user_ns, CAP_SYS_ADMIN)) && + ((uid_eq(uid, cred->uid) || uid_eq(uid, cred->euid) || +- uid_eq(uid, cred->suid)) || nsown_capable(CAP_SETUID)) && ++ uid_eq(uid, cred->suid)) || ns_capable(cred->user_ns, CAP_SETUID)) && + ((gid_eq(gid, cred->gid) || gid_eq(gid, cred->egid) || +- gid_eq(gid, cred->sgid)) || nsown_capable(CAP_SETGID))) { ++ gid_eq(gid, cred->sgid)) || ns_capable(cred->user_ns, CAP_SETGID))) { + return 0; + } + return -EPERM; +-- +1.9.1 + |