92 lines
3.0 KiB
Diff
92 lines
3.0 KiB
Diff
|
From: Eric Dumazet <edumazet@google.com>
|
||
|
Date: Tue, 21 Aug 2012 06:21:17 +0000
|
||
|
Subject: af_netlink: force credentials passing [CVE-2012-3520]
|
||
|
|
||
|
[ Upstream commit e0e3cea46d31d23dc40df0a49a7a2c04fe8edfea ]
|
||
|
|
||
|
Pablo Neira Ayuso discovered that avahi and
|
||
|
potentially NetworkManager accept spoofed Netlink messages because of a
|
||
|
kernel bug. The kernel passes all-zero SCM_CREDENTIALS ancillary data
|
||
|
to the receiver if the sender did not provide such data, instead of not
|
||
|
including any such data at all or including the correct data from the
|
||
|
peer (as it is the case with AF_UNIX).
|
||
|
|
||
|
This bug was introduced in commit 16e572626961
|
||
|
(af_unix: dont send SCM_CREDENTIALS by default)
|
||
|
|
||
|
This patch forces passing credentials for netlink, as
|
||
|
before the regression.
|
||
|
|
||
|
Another fix would be to not add SCM_CREDENTIALS in
|
||
|
netlink messages if not provided by the sender, but it
|
||
|
might break some programs.
|
||
|
|
||
|
With help from Florian Weimer & Petr Matousek
|
||
|
|
||
|
This issue is designated as CVE-2012-3520
|
||
|
|
||
|
Signed-off-by: Eric Dumazet <edumazet@google.com>
|
||
|
Cc: Petr Matousek <pmatouse@redhat.com>
|
||
|
Cc: Florian Weimer <fweimer@redhat.com>
|
||
|
Cc: Pablo Neira Ayuso <pablo@netfilter.org>
|
||
|
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||
|
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
|
||
|
---
|
||
|
include/net/scm.h | 4 +++-
|
||
|
net/netlink/af_netlink.c | 2 +-
|
||
|
net/unix/af_unix.c | 4 ++--
|
||
|
3 files changed, 6 insertions(+), 4 deletions(-)
|
||
|
|
||
|
diff --git a/include/net/scm.h b/include/net/scm.h
|
||
|
index d456f4c..0c0017c 100644
|
||
|
--- a/include/net/scm.h
|
||
|
+++ b/include/net/scm.h
|
||
|
@@ -71,9 +71,11 @@ static __inline__ void scm_destroy(struct scm_cookie *scm)
|
||
|
}
|
||
|
|
||
|
static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
|
||
|
- struct scm_cookie *scm)
|
||
|
+ struct scm_cookie *scm, bool forcecreds)
|
||
|
{
|
||
|
memset(scm, 0, sizeof(*scm));
|
||
|
+ if (forcecreds)
|
||
|
+ scm_set_cred(scm, task_tgid(current), current_cred());
|
||
|
unix_get_peersec_dgram(sock, scm);
|
||
|
if (msg->msg_controllen <= 0)
|
||
|
return 0;
|
||
|
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
|
||
|
index a99fb41..1af8542 100644
|
||
|
--- a/net/netlink/af_netlink.c
|
||
|
+++ b/net/netlink/af_netlink.c
|
||
|
@@ -1333,7 +1333,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
|
||
|
if (NULL == siocb->scm)
|
||
|
siocb->scm = &scm;
|
||
|
|
||
|
- err = scm_send(sock, msg, siocb->scm);
|
||
|
+ err = scm_send(sock, msg, siocb->scm, true);
|
||
|
if (err < 0)
|
||
|
return err;
|
||
|
|
||
|
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
|
||
|
index d99678a..317bfe3 100644
|
||
|
--- a/net/unix/af_unix.c
|
||
|
+++ b/net/unix/af_unix.c
|
||
|
@@ -1435,7 +1435,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
|
||
|
if (NULL == siocb->scm)
|
||
|
siocb->scm = &tmp_scm;
|
||
|
wait_for_unix_gc();
|
||
|
- err = scm_send(sock, msg, siocb->scm);
|
||
|
+ err = scm_send(sock, msg, siocb->scm, false);
|
||
|
if (err < 0)
|
||
|
return err;
|
||
|
|
||
|
@@ -1596,7 +1596,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
|
||
|
if (NULL == siocb->scm)
|
||
|
siocb->scm = &tmp_scm;
|
||
|
wait_for_unix_gc();
|
||
|
- err = scm_send(sock, msg, siocb->scm);
|
||
|
+ err = scm_send(sock, msg, siocb->scm, false);
|
||
|
if (err < 0)
|
||
|
return err;
|
||
|
|