aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2012-08-21 02:21:17 -0400
committerDavid S. Miller <davem@davemloft.net>2012-08-21 17:53:01 -0400
commite0e3cea46d31d23dc40df0a49a7a2c04fe8edfea (patch)
treed3a95cc25dd504fecc807dbb8a9e9c3501c90edf
parenta9915a1b52df52ad87f3b33422da95cf25372f09 (diff)
af_netlink: force credentials passing [CVE-2012-3520]
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>
-rw-r--r--include/net/scm.h4
-rw-r--r--net/netlink/af_netlink.c2
-rw-r--r--net/unix/af_unix.c4
3 files changed, 6 insertions, 4 deletions
diff --git a/include/net/scm.h b/include/net/scm.h
index 079d7887dac1..7dc0854f0b38 100644
--- a/include/net/scm.h
+++ b/include/net/scm.h
@@ -70,9 +70,11 @@ static __inline__ void scm_destroy(struct scm_cookie *scm)
70} 70}
71 71
72static __inline__ int scm_send(struct socket *sock, struct msghdr *msg, 72static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
73 struct scm_cookie *scm) 73 struct scm_cookie *scm, bool forcecreds)
74{ 74{
75 memset(scm, 0, sizeof(*scm)); 75 memset(scm, 0, sizeof(*scm));
76 if (forcecreds)
77 scm_set_cred(scm, task_tgid(current), current_cred());
76 unix_get_peersec_dgram(sock, scm); 78 unix_get_peersec_dgram(sock, scm);
77 if (msg->msg_controllen <= 0) 79 if (msg->msg_controllen <= 0)
78 return 0; 80 return 0;
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 5463969da45b..1445d73533ed 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1362,7 +1362,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
1362 if (NULL == siocb->scm) 1362 if (NULL == siocb->scm)
1363 siocb->scm = &scm; 1363 siocb->scm = &scm;
1364 1364
1365 err = scm_send(sock, msg, siocb->scm); 1365 err = scm_send(sock, msg, siocb->scm, true);
1366 if (err < 0) 1366 if (err < 0)
1367 return err; 1367 return err;
1368 1368
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index e4768c180da2..c5ee4ff61364 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -1450,7 +1450,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
1450 if (NULL == siocb->scm) 1450 if (NULL == siocb->scm)
1451 siocb->scm = &tmp_scm; 1451 siocb->scm = &tmp_scm;
1452 wait_for_unix_gc(); 1452 wait_for_unix_gc();
1453 err = scm_send(sock, msg, siocb->scm); 1453 err = scm_send(sock, msg, siocb->scm, false);
1454 if (err < 0) 1454 if (err < 0)
1455 return err; 1455 return err;
1456 1456
@@ -1619,7 +1619,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
1619 if (NULL == siocb->scm) 1619 if (NULL == siocb->scm)
1620 siocb->scm = &tmp_scm; 1620 siocb->scm = &tmp_scm;
1621 wait_for_unix_gc(); 1621 wait_for_unix_gc();
1622 err = scm_send(sock, msg, siocb->scm); 1622 err = scm_send(sock, msg, siocb->scm, false);
1623 if (err < 0) 1623 if (err < 0)
1624 return err; 1624 return err;
1625 1625