All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/7] Backport to stable-3.4 for fix CVE-2014-0181
@ 2014-07-18  2:21 Wangyufen
  2014-07-18  2:21 ` [PATCH 1/7] netlink: Make the sending netlink socket availabe in NETLINK_CB Wangyufen
                   ` (7 more replies)
  0 siblings, 8 replies; 9+ messages in thread
From: Wangyufen @ 2014-07-18  2:21 UTC (permalink / raw)
  To: davem; +Cc: netdev

From: Wang Yufen <wangyufen@huawei.com>

Hi David,

This backport fix CVE-2014-0181 which would still be vulnerable in
stable-3.4, please add it.

patchset from 5187cd055b6e to 90f62cf30a78 fixed CVE-2014-0181,
which can't backport to stable-3.4 directly, 

Those three patches are needed:
commit 935d8aabd4331f47a89c3e1daa5779d23cf244ee 
commit 038e7332b8d4c0629a2965e3ede1a92e8e427bd6
commit 3fbc290540a1ed1a8a076ed8f53bee7a38a9f408 

and this patch is unneeded:
commit a53b72c83a4216f2eb883ed45a0cbce014b8e62d


 -- 
1.7.12

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/7] netlink: Make the sending netlink socket availabe in NETLINK_CB
  2014-07-18  2:21 [PATCH 0/7] Backport to stable-3.4 for fix CVE-2014-0181 Wangyufen
@ 2014-07-18  2:21 ` Wangyufen
  2014-07-18  2:21 ` [PATCH 2/7] userns: make each net (net_ns) belong to a user_ns Wangyufen
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Wangyufen @ 2014-07-18  2:21 UTC (permalink / raw)
  To: davem; +Cc: netdev

From: Wang Yufen <wangyufen@huawei.com>

The sending socket of an skb is already available by it's port id
in the NETLINK_CB.  If you want to know more like to examine the
credentials on the sending socket you have to look up the sending
socket by it's port id and all of the needed functions and data
structures are static inside of af_netlink.c.  So do the simple
thing and pass the sending socket to the receivers in the NETLINK_CB.

I intend to use this to get the user namespace of the sending socket
in inet_diag so that I can report uids in the context of the process
who opened the socket, the same way I report uids in the contect
of the process who opens files.
 
Acked-by: David S. Miller <davem@davemloft.net>
Acked-by: Serge Hallyn <serge.hallyn@canonical.com>
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Signed-off-by: Wang Yufen <wangyufen@huawei.com>
---
 include/linux/netlink.h  | 1 +
 net/netlink/af_netlink.c | 6 ++++--
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/include/linux/netlink.h b/include/linux/netlink.h
index b23e9cd..af6c763 100644
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h
@@ -166,6 +166,7 @@ struct netlink_skb_parms {
 	struct ucred		creds;		/* Skb credentials	*/
 	__u32			pid;
 	__u32			dst_group;
+	struct sock             *ssk;
 };
 
 #define NETLINK_CB(skb)		(*(struct netlink_skb_parms*)&((skb)->cb))
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index ff960b7..571fc2c 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -899,7 +899,8 @@ static void netlink_rcv_wake(struct sock *sk)
 		wake_up_interruptible(&nlk->wait);
 }
 
-static int netlink_unicast_kernel(struct sock *sk, struct sk_buff *skb)
+static int netlink_unicast_kernel(struct sock *sk, struct sk_buff *skb,
+				  struct sock *ssk)
 {
 	int ret;
 	struct netlink_sock *nlk = nlk_sk(sk);
@@ -908,6 +909,7 @@ static int netlink_unicast_kernel(struct sock *sk, struct sk_buff *skb)
 	if (nlk->netlink_rcv != NULL) {
 		ret = skb->len;
 		skb_set_owner_r(skb, sk);
+		NETLINK_CB(skb).ssk = ssk;
 		nlk->netlink_rcv(skb);
 	}
 	kfree_skb(skb);
@@ -932,7 +934,7 @@ retry:
 		return PTR_ERR(sk);
 	}
 	if (netlink_is_kernel(sk))
-		return netlink_unicast_kernel(sk, skb);
+		return netlink_unicast_kernel(sk, skb, ssk);
 
 	if (sk_filter(sk, skb)) {
 		err = skb->len;
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 2/7] userns: make each net (net_ns) belong to a user_ns
  2014-07-18  2:21 [PATCH 0/7] Backport to stable-3.4 for fix CVE-2014-0181 Wangyufen
  2014-07-18  2:21 ` [PATCH 1/7] netlink: Make the sending netlink socket availabe in NETLINK_CB Wangyufen
@ 2014-07-18  2:21 ` Wangyufen
  2014-07-18  2:21 ` [PATCH 3/7] Add file_ns_capable() helper function for open-time capability checking Wangyufen
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Wangyufen @ 2014-07-18  2:21 UTC (permalink / raw)
  To: davem; +Cc: netdev

From: Wang Yufen <wangyufen@huawei.com>

The user namespace which creates a new network namespace owns that
namespace and all resources created in it.  This way we can target
capability checks for privileged operations against network resources to
the user_ns which created the network namespace in which the resource
lives.  Privilege to the user namespace which owns the network
namespace, or any parent user namespace thereof, provides the same
privilege to the network resource.

This patch is reworked from a version originally by
Serge E. Hallyn <serge.hallyn@canonical.com>

Acked-by: Serge Hallyn <serge.hallyn@canonical.com>
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Signed-off-by: Wang Yufen <wangyufen@huawei.com>
---
 include/net/net_namespace.h |  9 +++++++--
 kernel/nsproxy.c            |  2 +-
 net/core/net_namespace.c    | 15 +++++++++++----
 3 files changed, 19 insertions(+), 7 deletions(-)

diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index ee547c1..9594ef9 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -22,6 +22,7 @@
 #endif
 #include <net/netns/xfrm.h>
 
+struct user_namespace;
 struct proc_dir_entry;
 struct net_device;
 struct sock;
@@ -52,6 +53,8 @@ struct net {
 	struct list_head	cleanup_list;	/* namespaces on death row */
 	struct list_head	exit_list;	/* Use only net_mutex */
 
+	struct user_namespace   *user_ns;       /* Owning user namespace */
+
 	struct proc_dir_entry 	*proc_net;
 	struct proc_dir_entry 	*proc_net_stat;
 
@@ -110,10 +113,12 @@ struct net {
 extern struct net init_net;
 
 #ifdef CONFIG_NET
-extern struct net *copy_net_ns(unsigned long flags, struct net *net_ns);
+extern struct net *copy_net_ns(unsigned long flags,
+			       struct user_namespace *user_ns, struct net *old_net);
 
 #else /* CONFIG_NET */
-static inline struct net *copy_net_ns(unsigned long flags, struct net *net_ns)
+static inline struct net *copy_net_ns(unsigned long flags,
+				      struct user_namespace *user_ns, struct net *old_net)
 {
 	/* There is nothing to copy so this is a noop */
 	return net_ns;
diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
index b576f7f..7e1c3de 100644
--- a/kernel/nsproxy.c
+++ b/kernel/nsproxy.c
@@ -90,7 +90,7 @@ static struct nsproxy *create_new_namespaces(unsigned long flags,
 		goto out_pid;
 	}
 
-	new_nsp->net_ns = copy_net_ns(flags, tsk->nsproxy->net_ns);
+	new_nsp->net_ns = copy_net_ns(flags, task_cred_xxx(tsk, user_ns), tsk->nsproxy->net_ns);
 	if (IS_ERR(new_nsp->net_ns)) {
 		err = PTR_ERR(new_nsp->net_ns);
 		goto out_net;
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index dd00b71..31cc840 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -11,6 +11,7 @@
 #include <linux/proc_fs.h>
 #include <linux/file.h>
 #include <linux/export.h>
+#include <linux/user_namespace.h>
 #include <net/net_namespace.h>
 #include <net/netns/generic.h>
 
@@ -143,7 +144,7 @@ static void ops_free_list(const struct pernet_operations *ops,
 /*
  * setup_net runs the initializers for the network namespace object.
  */
-static __net_init int setup_net(struct net *net)
+static __net_init int setup_net(struct net *net, struct user_namespace *user_ns)
 {
 	/* Must be called with net_mutex held */
 	const struct pernet_operations *ops, *saved_ops;
@@ -153,6 +154,7 @@ static __net_init int setup_net(struct net *net)
 	atomic_set(&net->count, 1);
 	atomic_set(&net->passive, 1);
 	net->dev_base_seq = 1;
+	net->user_ns = user_ns;
 
 #ifdef NETNS_REFCNT_DEBUG
 	atomic_set(&net->use_count, 0);
@@ -230,7 +232,8 @@ void net_drop_ns(void *p)
 		net_free(ns);
 }
 
-struct net *copy_net_ns(unsigned long flags, struct net *old_net)
+struct net *copy_net_ns(unsigned long flags,
+			struct user_namespace *user_ns, struct net *old_net)
 {
 	struct net *net;
 	int rv;
@@ -241,8 +244,11 @@ struct net *copy_net_ns(unsigned long flags, struct net *old_net)
 	net = net_alloc();
 	if (!net)
 		return ERR_PTR(-ENOMEM);
+
+	get_user_ns(user_ns);
+
 	mutex_lock(&net_mutex);
-	rv = setup_net(net);
+	rv = setup_net(net, user_ns);
 	if (rv == 0) {
 		rtnl_lock();
 		list_add_tail_rcu(&net->list, &net_namespace_list);
@@ -250,6 +256,7 @@ struct net *copy_net_ns(unsigned long flags, struct net *old_net)
 	}
 	mutex_unlock(&net_mutex);
 	if (rv < 0) {
+		put_user_ns(user_ns);
 		net_drop_ns(net);
 		return ERR_PTR(rv);
 	}
@@ -400,7 +407,7 @@ static int __init net_ns_init(void)
 	rcu_assign_pointer(init_net.gen, ng);
 
 	mutex_lock(&net_mutex);
-	if (setup_net(&init_net))
+	if (setup_net(&init_net, &init_user_ns))
 		panic("Could not setup the initial network namespace");
 
 	rtnl_lock();
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 3/7] Add file_ns_capable() helper function for open-time capability checking
  2014-07-18  2:21 [PATCH 0/7] Backport to stable-3.4 for fix CVE-2014-0181 Wangyufen
  2014-07-18  2:21 ` [PATCH 1/7] netlink: Make the sending netlink socket availabe in NETLINK_CB Wangyufen
  2014-07-18  2:21 ` [PATCH 2/7] userns: make each net (net_ns) belong to a user_ns Wangyufen
@ 2014-07-18  2:21 ` Wangyufen
  2014-07-18  2:21 ` [PATCH 4/7] netlink: Rename netlink_capable netlink_allowed Wangyufen
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Wangyufen @ 2014-07-18  2:21 UTC (permalink / raw)
  To: davem; +Cc: netdev

From: Wang Yufen <wangyufen@huawei.com>

Nothing is using it yet, but this will allow us to delay the open-time
checks to use time, without breaking the normal UNIX permission
semantics where permissions are determined by the opener (and the file
descriptor can then be passed to a different process, or the process can
drop capabilities).

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Wang Yufen <wangyufen@huawei.com>
---
 include/linux/capability.h |  3 ++-
 kernel/capability.c        | 24 ++++++++++++++++++++++++
 2 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/include/linux/capability.h b/include/linux/capability.h
index 12d52de..7273027 100644
--- a/include/linux/capability.h
+++ b/include/linux/capability.h
@@ -373,7 +373,7 @@ struct cpu_vfs_cap_data {
 #define CAP_TO_MASK(x)      (1 << ((x) & 31)) /* mask for indexed __u32 */
 
 #ifdef __KERNEL__
-
+struct file;
 struct dentry;
 struct user_namespace;
 
@@ -548,6 +548,7 @@ extern bool has_ns_capability_noaudit(struct task_struct *t,
 extern bool capable(int cap);
 extern bool ns_capable(struct user_namespace *ns, int cap);
 extern bool nsown_capable(int cap);
+extern bool file_ns_capable(const struct file *file, struct user_namespace *ns, int cap);
 
 /* audit system wants to get cap info from files as well */
 extern int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data *cpu_caps);
diff --git a/kernel/capability.c b/kernel/capability.c
index 3f1adb6..cc8c4845 100644
--- a/kernel/capability.c
+++ b/kernel/capability.c
@@ -393,6 +393,30 @@ bool ns_capable(struct user_namespace *ns, int cap)
 EXPORT_SYMBOL(ns_capable);
 
 /**
+ * file_ns_capable - Determine if the file's opener had a capability in effect
+ * @file:  The file we want to check
+ * @ns:  The usernamespace we want the capability in
+ * @cap: The capability to be tested for
+ *
+ * Return true if task that opened the file had a capability in effect
+ * when the file was opened.
+ *
+ * This does not set PF_SUPERPRIV because the caller may not
+ * actually be privileged.
+ */
+bool file_ns_capable(const struct file *file, struct user_namespace *ns, int cap)
+{
+	if (WARN_ON_ONCE(!cap_valid(cap)))
+		return false;
+
+	if (security_capable(file->f_cred, ns, cap) == 0)
+		return true;
+
+	return false;
+}
+EXPORT_SYMBOL(file_ns_capable);
+
+/**
  * capable - Determine if the current task has a superior capability in effect
  * @cap: The capability to be tested for
  *
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 4/7] netlink: Rename netlink_capable netlink_allowed
  2014-07-18  2:21 [PATCH 0/7] Backport to stable-3.4 for fix CVE-2014-0181 Wangyufen
                   ` (2 preceding siblings ...)
  2014-07-18  2:21 ` [PATCH 3/7] Add file_ns_capable() helper function for open-time capability checking Wangyufen
@ 2014-07-18  2:21 ` Wangyufen
  2014-07-18  2:21 ` [PATCH 5/7] net: Add variants of capable for use on on sockets Wangyufen
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Wangyufen @ 2014-07-18  2:21 UTC (permalink / raw)
  To: davem; +Cc: netdev

From: Wang Yufen <wangyufen@huawei.com>

netlink_capable is a static internal function in af_netlink.c and we
have better uses for the name netlink_capable.

Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Wang Yufen <wangyufen@huawei.com>
---
 net/netlink/af_netlink.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 571fc2c..18b4cc6 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -590,7 +590,7 @@ retry:
 	return err;
 }
 
-static inline int netlink_capable(const struct socket *sock, unsigned int flag)
+static inline int netlink_allowed(const struct socket *sock, unsigned int flag)
 {
 	return (nl_table[sock->sk->sk_protocol].nl_nonroot & flag) ||
 	       capable(CAP_NET_ADMIN);
@@ -655,7 +655,7 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr,
 
 	/* Only superuser is allowed to listen multicasts */
 	if (nladdr->nl_groups) {
-		if (!netlink_capable(sock, NL_NONROOT_RECV))
+		if (!netlink_allowed(sock, NL_NONROOT_RECV))
 			return -EPERM;
 		err = netlink_realloc_groups(sk);
 		if (err)
@@ -708,7 +708,7 @@ static int netlink_connect(struct socket *sock, struct sockaddr *addr,
 		return -EINVAL;
 
 	/* Only superuser is allowed to send multicasts */
-	if (nladdr->nl_groups && !netlink_capable(sock, NL_NONROOT_SEND))
+	if (nladdr->nl_groups && !netlink_allowed(sock, NL_NONROOT_SEND))
 		return -EPERM;
 
 	if (!nlk->pid)
@@ -1229,7 +1229,7 @@ static int netlink_setsockopt(struct socket *sock, int level, int optname,
 		break;
 	case NETLINK_ADD_MEMBERSHIP:
 	case NETLINK_DROP_MEMBERSHIP: {
-		if (!netlink_capable(sock, NL_NONROOT_RECV))
+		if (!netlink_allowed(sock, NL_NONROOT_RECV))
 			return -EPERM;
 		err = netlink_realloc_groups(sk);
 		if (err)
@@ -1356,7 +1356,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
 		dst_group = ffs(addr->nl_groups);
 		err =  -EPERM;
 		if ((dst_group || dst_pid) &&
-		    !netlink_capable(sock, NL_NONROOT_SEND))
+		    !netlink_allowed(sock, NL_NONROOT_SEND))
 			goto out;
 	} else {
 		dst_pid = nlk->dst_pid;
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 5/7] net: Add variants of capable for use on on sockets
  2014-07-18  2:21 [PATCH 0/7] Backport to stable-3.4 for fix CVE-2014-0181 Wangyufen
                   ` (3 preceding siblings ...)
  2014-07-18  2:21 ` [PATCH 4/7] netlink: Rename netlink_capable netlink_allowed Wangyufen
@ 2014-07-18  2:21 ` Wangyufen
  2014-07-18  2:21 ` [PATCH 6/7] net: Add variants of capable for use on netlink messages Wangyufen
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Wangyufen @ 2014-07-18  2:21 UTC (permalink / raw)
  To: davem; +Cc: netdev

From: Wang Yufen <wangyufen@huawei.com>

sk_net_capable - The common case, operations that are safe in a network namespace.
sk_capable - Operations that are not known to be safe in a network namespace
sk_ns_capable - The general case for special cases.

Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Wang Yufen <wangyufen@huawei.com>
---
 include/net/sock.h |  5 +++++
 net/core/sock.c    | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 54 insertions(+)

diff --git a/include/net/sock.h b/include/net/sock.h
index f673ba5..8d4046c 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -2148,6 +2148,11 @@ extern void sock_enable_timestamp(struct sock *sk, int flag);
 extern int sock_get_timestamp(struct sock *, struct timeval __user *);
 extern int sock_get_timestampns(struct sock *, struct timespec __user *);
 
+bool sk_ns_capable(const struct sock *sk,
+		   struct user_namespace *user_ns, int cap);
+bool sk_capable(const struct sock *sk, int cap);
+bool sk_net_capable(const struct sock *sk, int cap);
+
 /* 
  *	Enable debug/info messages 
  */
diff --git a/net/core/sock.c b/net/core/sock.c
index 832cf04..43854b0 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -139,6 +139,55 @@
 static DEFINE_MUTEX(proto_list_mutex);
 static LIST_HEAD(proto_list);
 
+/**
+ * sk_ns_capable - General socket capability test
+ * @sk: Socket to use a capability on or through
+ * @user_ns: The user namespace of the capability to use
+ * @cap: The capability to use
+ *
+ * Test to see if the opener of the socket had when the socket was
+ * created and the current process has the capability @cap in the user
+ * namespace @user_ns.
+ */
+bool sk_ns_capable(const struct sock *sk,
+		   struct user_namespace *user_ns, int cap)
+{
+	return file_ns_capable(sk->sk_socket->file, user_ns, cap) &&
+		ns_capable(user_ns, cap);
+}
+EXPORT_SYMBOL(sk_ns_capable);
+
+/**
+ * sk_capable - Socket global capability test
+ * @sk: Socket to use a capability on or through
+ * @cap: The global capbility to use
+ *
+ * Test to see if the opener of the socket had when the socket was
+ * created and the current process has the capability @cap in all user
+ * namespaces.
+ */
+bool sk_capable(const struct sock *sk, int cap)
+{
+	return sk_ns_capable(sk, &init_user_ns, cap);
+}
+EXPORT_SYMBOL(sk_capable);
+
+/**
+ * sk_net_capable - Network namespace socket capability test
+ * @sk: Socket to use a capability on or through
+ * @cap: The capability to use
+ *
+ * Test to see if the opener of the socket had when the socke was created
+ * and the current process has the capability @cap over the network namespace
+ * the socket is a member of.
+ */
+bool sk_net_capable(const struct sock *sk, int cap)
+{
+	return sk_ns_capable(sk, sock_net(sk)->user_ns, cap);
+}
+EXPORT_SYMBOL(sk_net_capable);
+
+
 #ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM
 int mem_cgroup_sockets_init(struct cgroup *cgrp, struct cgroup_subsys *ss)
 {
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 6/7] net: Add variants of capable for use on netlink messages
  2014-07-18  2:21 [PATCH 0/7] Backport to stable-3.4 for fix CVE-2014-0181 Wangyufen
                   ` (4 preceding siblings ...)
  2014-07-18  2:21 ` [PATCH 5/7] net: Add variants of capable for use on on sockets Wangyufen
@ 2014-07-18  2:21 ` Wangyufen
  2014-07-18  2:21 ` [PATCH 7/7] net: Use netlink_ns_capable to verify the permisions of " Wangyufen
  2014-07-24 23:06 ` [PATCH 0/7] Backport to stable-3.4 for fix CVE-2014-0181 David Miller
  7 siblings, 0 replies; 9+ messages in thread
From: Wangyufen @ 2014-07-18  2:21 UTC (permalink / raw)
  To: davem; +Cc: netdev

From: Wang Yufen <wangyufen@huawei.com>

netlink_net_capable - The common case use, for operations that are safe on a network namespace
netlink_capable - For operations that are only known to be safe for the global root
netlink_ns_capable - The general case of capable used to handle special cases

__netlink_ns_capable - Same as netlink_ns_capable except taking a netlink_skb_parms instead of
                       the skbuff of a netlink message.

Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Wang Yufen <wangyufen@huawei.com>
---
 include/linux/netlink.h  |  7 ++++++
 net/netlink/af_netlink.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 72 insertions(+)

diff --git a/include/linux/netlink.h b/include/linux/netlink.h
index af6c763..f4b56b7 100644
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h
@@ -279,6 +279,13 @@ static inline int netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
 #define NL_NONROOT_SEND 0x2
 extern void netlink_set_nonroot(int protocol, unsigned flag);
 
+bool __netlink_ns_capable(const struct netlink_skb_parms *nsp,
+			  struct user_namespace *ns, int cap);
+bool netlink_ns_capable(const struct sk_buff *skb,
+			struct user_namespace *ns, int cap);
+bool netlink_capable(const struct sk_buff *skb, int cap);
+bool netlink_net_capable(const struct sk_buff *skb, int cap);
+
 #endif /* __KERNEL__ */
 
 #endif	/* __LINUX_NETLINK_H */
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 18b4cc6..7d3cfc9 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -590,6 +590,71 @@ retry:
 	return err;
 }
 
+/**
+ * __netlink_ns_capable - General netlink message capability test
+ * @nsp: NETLINK_CB of the socket buffer holding a netlink command from userspace.
+ * @user_ns: The user namespace of the capability to use
+ * @cap: The capability to use
+ *
+ * Test to see if the opener of the socket we received the message
+ * from had when the netlink socket was created and the sender of the
+ * message has has the capability @cap in the user namespace @user_ns.
+ */
+bool __netlink_ns_capable(const struct netlink_skb_parms *nsp,
+			struct user_namespace *user_ns, int cap)
+{
+	return sk_ns_capable(nsp->ssk, user_ns, cap);
+}
+EXPORT_SYMBOL(__netlink_ns_capable);
+
+/**
+ * netlink_ns_capable - General netlink message capability test
+ * @skb: socket buffer holding a netlink command from userspace
+ * @user_ns: The user namespace of the capability to use
+ * @cap: The capability to use
+ *
+ * Test to see if the opener of the socket we received the message
+ * from had when the netlink socket was created and the sender of the
+ * message has has the capability @cap in the user namespace @user_ns.
+ */
+bool netlink_ns_capable(const struct sk_buff *skb,
+			struct user_namespace *user_ns, int cap)
+{
+	return __netlink_ns_capable(&NETLINK_CB(skb), user_ns, cap);
+}
+EXPORT_SYMBOL(netlink_ns_capable);
+
+/**
+ * netlink_capable - Netlink global message capability test
+ * @skb: socket buffer holding a netlink command from userspace
+ * @cap: The capability to use
+ *
+ * Test to see if the opener of the socket we received the message
+ * from had when the netlink socket was created and the sender of the
+ * message has has the capability @cap in all user namespaces.
+ */
+bool netlink_capable(const struct sk_buff *skb, int cap)
+{
+	return netlink_ns_capable(skb, &init_user_ns, cap);
+}
+EXPORT_SYMBOL(netlink_capable);
+
+/**
+ * netlink_net_capable - Netlink network namespace message capability test
+ * @skb: socket buffer holding a netlink command from userspace
+ * @cap: The capability to use
+ *
+ * Test to see if the opener of the socket we received the message
+ * from had when the netlink socket was created and the sender of the
+ * message has has the capability @cap over the network namespace of
+ * the socket we received the message from.
+ */
+bool netlink_net_capable(const struct sk_buff *skb, int cap)
+{
+	return netlink_ns_capable(skb, sock_net(skb->sk)->user_ns, cap);
+}
+EXPORT_SYMBOL(netlink_net_capable);
+
 static inline int netlink_allowed(const struct socket *sock, unsigned int flag)
 {
 	return (nl_table[sock->sk->sk_protocol].nl_nonroot & flag) ||
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 7/7] net: Use netlink_ns_capable to verify the permisions of netlink messages
  2014-07-18  2:21 [PATCH 0/7] Backport to stable-3.4 for fix CVE-2014-0181 Wangyufen
                   ` (5 preceding siblings ...)
  2014-07-18  2:21 ` [PATCH 6/7] net: Add variants of capable for use on netlink messages Wangyufen
@ 2014-07-18  2:21 ` Wangyufen
  2014-07-24 23:06 ` [PATCH 0/7] Backport to stable-3.4 for fix CVE-2014-0181 David Miller
  7 siblings, 0 replies; 9+ messages in thread
From: Wangyufen @ 2014-07-18  2:21 UTC (permalink / raw)
  To: davem; +Cc: netdev

From: Wang Yufen <wangyufen@huawei.com>

It is possible by passing a netlink socket to a more privileged
executable and then to fool that executable into writing to the socket
data that happens to be valid netlink message to do something that
privileged executable did not intend to do.

To keep this from happening replace bare capable and ns_capable calls
with netlink_capable, netlink_net_calls and netlink_ns_capable calls.
Which act the same as the previous calls except they verify that the
opener of the socket had the desired permissions as well.

Reported-by: Andy Lutomirski <luto@amacapital.net>
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Wang Yufen <wangyufen@huawei.com>
---
 crypto/crypto_user.c            | 2 +-
 drivers/connector/cn_proc.c     | 2 +-
 drivers/scsi/scsi_netlink.c     | 2 +-
 kernel/audit.c                  | 4 ++--
 net/core/rtnetlink.c            | 2 +-
 net/decnet/dn_dev.c             | 2 +-
 net/decnet/netfilter/dn_rtmsg.c | 2 +-
 net/netfilter/nfnetlink.c       | 2 +-
 net/netlink/genetlink.c         | 2 +-
 net/phonet/pn_netlink.c         | 4 ++--
 net/tipc/netlink.c              | 2 +-
 net/xfrm/xfrm_user.c            | 2 +-
 12 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c
index 910497b..c86969e 100644
--- a/crypto/crypto_user.c
+++ b/crypto/crypto_user.c
@@ -452,7 +452,7 @@ static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 	type -= CRYPTO_MSG_BASE;
 	link = &crypto_dispatch[type];
 
-	if (!capable(CAP_NET_ADMIN))
+	if (!netlink_capable(skb, CAP_NET_ADMIN))
 		return -EPERM;
 
 	if ((type == (CRYPTO_MSG_GETALG - CRYPTO_MSG_BASE) &&
diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c
index 094a710..46856ae 100644
--- a/drivers/connector/cn_proc.c
+++ b/drivers/connector/cn_proc.c
@@ -332,7 +332,7 @@ static void cn_proc_mcast_ctl(struct cn_msg *msg,
 		return;
 
 	/* Can only change if privileged. */
-	if (!capable(CAP_NET_ADMIN)) {
+	if (!__netlink_ns_capable(nsp, &init_user_ns, CAP_NET_ADMIN)) {
 		err = EPERM;
 		goto out;
 	}
diff --git a/drivers/scsi/scsi_netlink.c b/drivers/scsi/scsi_netlink.c
index c77628a..a930b66 100644
--- a/drivers/scsi/scsi_netlink.c
+++ b/drivers/scsi/scsi_netlink.c
@@ -112,7 +112,7 @@ scsi_nl_rcv_msg(struct sk_buff *skb)
 			goto next_msg;
 		}
 
-		if (!capable(CAP_SYS_ADMIN)) {
+		if (!netlink_capable(skb, CAP_SYS_ADMIN)) {
 			err = -EPERM;
 			goto next_msg;
 		}
diff --git a/kernel/audit.c b/kernel/audit.c
index b4efae8..3c3a31c 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -601,13 +601,13 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type)
 	case AUDIT_TTY_SET:
 	case AUDIT_TRIM:
 	case AUDIT_MAKE_EQUIV:
-		if (!capable(CAP_AUDIT_CONTROL))
+		if (!netlink_capable(skb, CAP_AUDIT_CONTROL))
 			err = -EPERM;
 		break;
 	case AUDIT_USER:
 	case AUDIT_FIRST_USER_MSG ... AUDIT_LAST_USER_MSG:
 	case AUDIT_FIRST_USER_MSG2 ... AUDIT_LAST_USER_MSG2:
-		if (!capable(CAP_AUDIT_WRITE))
+		if (!netlink_capable(skb, CAP_AUDIT_WRITE))
 			err = -EPERM;
 		break;
 	default:  /* bad msg */
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index a133427..d3ac150 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -2010,7 +2010,7 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 	sz_idx = type>>2;
 	kind = type&3;
 
-	if (kind != 2 && !capable(CAP_NET_ADMIN))
+	if (kind != 2 && !netlink_net_capable(skb, CAP_NET_ADMIN))
 		return -EPERM;
 
 	if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) {
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
index c00e307..b79ce1e 100644
--- a/net/decnet/dn_dev.c
+++ b/net/decnet/dn_dev.c
@@ -440,7 +440,7 @@ int dn_dev_ioctl(unsigned int cmd, void __user *arg)
 	case SIOCGIFADDR:
 		break;
 	case SIOCSIFADDR:
-		if (!capable(CAP_NET_ADMIN))
+		if (!netlink_capable(skb, CAP_NET_ADMIN))
 			return -EACCES;
 		if (sdn->sdn_family != AF_DECnet)
 			return -EINVAL;
diff --git a/net/decnet/netfilter/dn_rtmsg.c b/net/decnet/netfilter/dn_rtmsg.c
index 1531135..dc750e2 100644
--- a/net/decnet/netfilter/dn_rtmsg.c
+++ b/net/decnet/netfilter/dn_rtmsg.c
@@ -108,7 +108,7 @@ static inline void dnrmg_receive_user_skb(struct sk_buff *skb)
 	if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len)
 		return;
 
-	if (!capable(CAP_NET_ADMIN))
+	if (!netlink_capable(skb, CAP_NET_ADMIN))
 		RCV_SKB_FAIL(-EPERM);
 
 	/* Eventually we might send routing messages too */
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c
index e6ddde1..5cfc865 100644
--- a/net/netfilter/nfnetlink.c
+++ b/net/netfilter/nfnetlink.c
@@ -129,7 +129,7 @@ static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 	const struct nfnetlink_subsystem *ss;
 	int type, err;
 
-	if (!capable(CAP_NET_ADMIN))
+	if (!netlink_net_capable(skb, CAP_NET_ADMIN))
 		return -EPERM;
 
 	/* All the messages must at least contain nfgenmsg */
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index 73d3f0c..dff8562 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -556,7 +556,7 @@ static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 		return -EOPNOTSUPP;
 
 	if ((ops->flags & GENL_ADMIN_PERM) &&
-	    !capable(CAP_NET_ADMIN))
+	    !netlink_capable(skb, CAP_NET_ADMIN))
 		return -EPERM;
 
 	if (nlh->nlmsg_flags & NLM_F_DUMP) {
diff --git a/net/phonet/pn_netlink.c b/net/phonet/pn_netlink.c
index d61f676..18485cd 100644
--- a/net/phonet/pn_netlink.c
+++ b/net/phonet/pn_netlink.c
@@ -70,7 +70,7 @@ static int addr_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *attr)
 	int err;
 	u8 pnaddr;
 
-	if (!capable(CAP_SYS_ADMIN))
+	if (!netlink_capable(skb, CAP_SYS_ADMIN))
 		return -EPERM;
 
 	ASSERT_RTNL();
@@ -228,7 +228,7 @@ static int route_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *attr)
 	int err;
 	u8 dst;
 
-	if (!capable(CAP_SYS_ADMIN))
+	if (!netlink_capable(skb, CAP_SYS_ADMIN))
 		return -EPERM;
 
 	ASSERT_RTNL();
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c
index 7bda8e3..0b4cf4f 100644
--- a/net/tipc/netlink.c
+++ b/net/tipc/netlink.c
@@ -47,7 +47,7 @@ static int handle_cmd(struct sk_buff *skb, struct genl_info *info)
 	int hdr_space = NLMSG_SPACE(GENL_HDRLEN + TIPC_GENL_HDRLEN);
 	u16 cmd;
 
-	if ((req_userhdr->cmd & 0xC000) && (!capable(CAP_NET_ADMIN)))
+	if ((req_userhdr->cmd & 0xC000) && (!netlink_capable(skb, CAP_NET_ADMIN)))
 		cmd = TIPC_CMD_NOT_NET_ADMIN;
 	else
 		cmd = req_userhdr->cmd;
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index c8b903d..ce16eba 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -2317,7 +2317,7 @@ static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 	link = &xfrm_dispatch[type];
 
 	/* All operations require privileges, even GET */
-	if (!capable(CAP_NET_ADMIN))
+	if (!netlink_net_capable(skb, CAP_NET_ADMIN))
 		return -EPERM;
 
 	if ((type == (XFRM_MSG_GETSA - XFRM_MSG_BASE) ||
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 0/7] Backport to stable-3.4 for fix CVE-2014-0181
  2014-07-18  2:21 [PATCH 0/7] Backport to stable-3.4 for fix CVE-2014-0181 Wangyufen
                   ` (6 preceding siblings ...)
  2014-07-18  2:21 ` [PATCH 7/7] net: Use netlink_ns_capable to verify the permisions of " Wangyufen
@ 2014-07-24 23:06 ` David Miller
  7 siblings, 0 replies; 9+ messages in thread
From: David Miller @ 2014-07-24 23:06 UTC (permalink / raw)
  To: wangyufen; +Cc: netdev

From: Wangyufen <wangyufen@huawei.com>
Date: Fri, 18 Jul 2014 10:21:19 +0800

> This backport fix CVE-2014-0181 which would still be vulnerable in
> stable-3.4, please add it.
> 
> patchset from 5187cd055b6e to 90f62cf30a78 fixed CVE-2014-0181,
> which can't backport to stable-3.4 directly, 
> 
> Those three patches are needed:
> commit 935d8aabd4331f47a89c3e1daa5779d23cf244ee 
> commit 038e7332b8d4c0629a2965e3ede1a92e8e427bd6
> commit 3fbc290540a1ed1a8a076ed8f53bee7a38a9f408 
> 
> and this patch is unneeded:
> commit a53b72c83a4216f2eb883ed45a0cbce014b8e62d

Unfortunately this backport has two very serious problems.

1) The From: is set to you for each patch, but you are not the author
   of these patches.  Most of them are written by Eric Biederman and
   one is written by Linus Torvalds.

   Having to do some backporting when putting together some -stable
   submissions does not mean you can just usurp authorship from the
   person who wrote the original change.

2) You failed to include the patch:

	commit 2d7a85f4b06e9c27ff629f07a524c48074f07f81
	Author: Eric W. Biederman <ebiederm@xmission.com>
	Date:   Fri May 30 11:04:00 2014 -0700

	    netlink: Only check file credentials for implicit destinations

   which fixes this series to not break applications like Zebra.

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2014-07-24 23:06 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-07-18  2:21 [PATCH 0/7] Backport to stable-3.4 for fix CVE-2014-0181 Wangyufen
2014-07-18  2:21 ` [PATCH 1/7] netlink: Make the sending netlink socket availabe in NETLINK_CB Wangyufen
2014-07-18  2:21 ` [PATCH 2/7] userns: make each net (net_ns) belong to a user_ns Wangyufen
2014-07-18  2:21 ` [PATCH 3/7] Add file_ns_capable() helper function for open-time capability checking Wangyufen
2014-07-18  2:21 ` [PATCH 4/7] netlink: Rename netlink_capable netlink_allowed Wangyufen
2014-07-18  2:21 ` [PATCH 5/7] net: Add variants of capable for use on on sockets Wangyufen
2014-07-18  2:21 ` [PATCH 6/7] net: Add variants of capable for use on netlink messages Wangyufen
2014-07-18  2:21 ` [PATCH 7/7] net: Use netlink_ns_capable to verify the permisions of " Wangyufen
2014-07-24 23:06 ` [PATCH 0/7] Backport to stable-3.4 for fix CVE-2014-0181 David Miller

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.