[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <87zji6v2mk.fsf_-_@x220.int.ebiederm.org>
Date: Sat, 24 May 2014 22:38:59 -0700
From: ebiederm@...ssion.com (Eric W. Biederman)
To: "Jorge Boncompte \[DTI2\]" <jorge@...2.net>,
Jiri Benc <jbenc@...hat.com>
Cc: Andy Lutomirski <luto@...capital.net>,
David Miller <davem@...emloft.net>,
Vivek Goyal <vgoyal@...hat.com>,
Simo Sorce <ssorce@...hat.com>,
"security\@kernel.org" <security@...nel.org>,
Network Development <netdev@...r.kernel.org>,
"Serge E. Hallyn" <serge@...lyn.com>,
Linus Torvalds <torvalds@...ux-foundation.org>
Subject: [RFC][PATCH] netlink: Only check file credentials for implicit destinations
It was possible to get a setuid root or setcap executable to write to
it's stdout or stderr (which has been set made a netlink socket) and
inadvertently reconfigure the networking stack.
To prevent this we check that both the creator of the socket and
the currentl applications has permission to reconfigure the network
stack.
Unfortunately this breaks Zebra which always uses sendto/sendmsg
and creates it's socket without any privileges.
To keep Zebra working don't bother checking if the creator of the
socket has privilege when a destination address is specified. Instead
rely exclusively on the privileges of the sender of the socket.
Signed-off-by: "Eric W. Biederman" <ebiederm@...ssion.com>
---
Could someone please test and see if this fixes the Zebra case?
So far I have only compile tested this, but the code should work,
unless Zebra is doing something that is so absolutely weird that
there is no way to close the security holes and keep Zebra working.
include/linux/netlink.h | 1 +
net/netlink/af_netlink.c | 7 ++++++-
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/include/linux/netlink.h b/include/linux/netlink.h
index 7a28115dd396..f289d085f87f 100644
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h
@@ -19,6 +19,7 @@ enum netlink_skb_flags {
NETLINK_SKB_MMAPED = 0x1, /* Packet data is mmaped */
NETLINK_SKB_TX = 0x2, /* Packet was sent by userspace */
NETLINK_SKB_DELIVERED = 0x4, /* Packet was delivered */
+ NETLINK_SKB_DST = 0x8, /* Packet not socket destination */
};
struct netlink_skb_parms {
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index e0ccd84d4d67..15c731f03fa6 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1377,7 +1377,9 @@ retry:
bool __netlink_ns_capable(const struct netlink_skb_parms *nsp,
struct user_namespace *user_ns, int cap)
{
- return sk_ns_capable(nsp->sk, user_ns, cap);
+ return ((nsp->flags & NETLINK_SKB_DST) ||
+ file_ns_capable(nsp->sk->sk_socket->file, user_ns, cap)) &&
+ ns_capable(user_ns, cap);
}
EXPORT_SYMBOL(__netlink_ns_capable);
@@ -2323,6 +2325,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
struct sk_buff *skb;
int err;
struct scm_cookie scm;
+ u32 netlink_skb_flags = 0;
if (msg->msg_flags&MSG_OOB)
return -EOPNOTSUPP;
@@ -2344,6 +2347,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
if ((dst_group || dst_portid) &&
!netlink_allowed(sock, NL_CFG_F_NONROOT_SEND))
goto out;
+ netlink_skb_flags |= NETLINK_SKB_DST;
} else {
dst_portid = nlk->dst_portid;
dst_group = nlk->dst_group;
@@ -2373,6 +2377,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
NETLINK_CB(skb).portid = nlk->portid;
NETLINK_CB(skb).dst_group = dst_group;
NETLINK_CB(skb).creds = siocb->scm->creds;
+ NETLINK_CB(skb).flags = netlink_skb_flags;
err = -EFAULT;
if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) {
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists