71 lines
2.1 KiB
Diff
71 lines
2.1 KiB
Diff
From: Mohamed Ghannam <simo.ghannam@gmail.com>
|
|
Date: Sun, 10 Dec 2017 03:50:58 +0000
|
|
Subject: net: ipv4: fix for a race condition in raw_sendmsg
|
|
Origin: https://git.kernel.org/linus/8f659a03a0ba9289b9aeb9b4470e6fb263d6f483
|
|
Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2017-17712
|
|
|
|
inet->hdrincl is racy, and could lead to uninitialized stack pointer
|
|
usage, so its value should be read only once.
|
|
|
|
Fixes: c008ba5bdc9f ("ipv4: Avoid reading user iov twice after raw_probe_proto_opt")
|
|
Signed-off-by: Mohamed Ghannam <simo.ghannam@gmail.com>
|
|
Reviewed-by: Eric Dumazet <edumazet@google.com>
|
|
Signed-off-by: David S. Miller <davem@davemloft.net>
|
|
---
|
|
net/ipv4/raw.c | 15 ++++++++++-----
|
|
1 file changed, 10 insertions(+), 5 deletions(-)
|
|
|
|
--- a/net/ipv4/raw.c
|
|
+++ b/net/ipv4/raw.c
|
|
@@ -513,11 +513,16 @@ static int raw_sendmsg(struct sock *sk,
|
|
int err;
|
|
struct ip_options_data opt_copy;
|
|
struct raw_frag_vec rfv;
|
|
+ int hdrincl;
|
|
|
|
err = -EMSGSIZE;
|
|
if (len > 0xFFFF)
|
|
goto out;
|
|
|
|
+ /* hdrincl should be READ_ONCE(inet->hdrincl)
|
|
+ * but READ_ONCE() doesn't work with bit fields
|
|
+ */
|
|
+ hdrincl = inet->hdrincl;
|
|
/*
|
|
* Check the flags.
|
|
*/
|
|
@@ -593,7 +598,7 @@ static int raw_sendmsg(struct sock *sk,
|
|
/* Linux does not mangle headers on raw sockets,
|
|
* so that IP options + IP_HDRINCL is non-sense.
|
|
*/
|
|
- if (inet->hdrincl)
|
|
+ if (hdrincl)
|
|
goto done;
|
|
if (ipc.opt->opt.srr) {
|
|
if (!daddr)
|
|
@@ -615,12 +620,12 @@ static int raw_sendmsg(struct sock *sk,
|
|
|
|
flowi4_init_output(&fl4, ipc.oif, sk->sk_mark, tos,
|
|
RT_SCOPE_UNIVERSE,
|
|
- inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol,
|
|
+ hdrincl ? IPPROTO_RAW : sk->sk_protocol,
|
|
inet_sk_flowi_flags(sk) |
|
|
- (inet->hdrincl ? FLOWI_FLAG_KNOWN_NH : 0),
|
|
+ (hdrincl ? FLOWI_FLAG_KNOWN_NH : 0),
|
|
daddr, saddr, 0, 0, sk->sk_uid);
|
|
|
|
- if (!inet->hdrincl) {
|
|
+ if (!hdrincl) {
|
|
rfv.msg = msg;
|
|
rfv.hlen = 0;
|
|
|
|
@@ -645,7 +650,7 @@ static int raw_sendmsg(struct sock *sk,
|
|
goto do_confirm;
|
|
back_from_confirm:
|
|
|
|
- if (inet->hdrincl)
|
|
+ if (hdrincl)
|
|
err = raw_send_hdrinc(sk, &fl4, msg, len,
|
|
&rt, msg->msg_flags, &ipc.sockc);
|
|
|