diff options
author | Eric Dumazet <edumazet@google.com> | 2016-12-02 09:44:53 -0800 |
---|---|---|
committer | Andreas Blaesius <skate4life@gmx.de> | 2017-03-17 11:03:06 +0100 |
commit | f6b319646d369ce7091246bc0a0296665a86e001 (patch) | |
tree | e0640cd0568667056b0c6233ecb19047df836aa8 /net | |
parent | 19920e2d711b3705b45205e866aa886359121ba6 (diff) | |
download | kernel_samsung_espresso10-f6b319646d369ce7091246bc0a0296665a86e001.zip kernel_samsung_espresso10-f6b319646d369ce7091246bc0a0296665a86e001.tar.gz kernel_samsung_espresso10-f6b319646d369ce7091246bc0a0296665a86e001.tar.bz2 |
net: avoid signed overflows for SO_{SND|RCV}BUFFORCE
CAP_NET_ADMIN users should not be allowed to set negative
sk_sndbuf or sk_rcvbuf values, as it can lead to various memory
corruptions, crashes, OOM...
Note that before commit 82981930125a ("net: cleanups in
sock_setsockopt()"), the bug was even more serious, since SO_SNDBUF
and SO_RCVBUF were vulnerable.
This needs to be backported to all known linux kernels.
Again, many thanks to syzkaller team for discovering this gem.
Change-Id: I93f4b9b1e6d93747a096ab26b73d24c7911b21b4
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reported-by: Andrey Konovalov <andreyknvl@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/core/sock.c | 10 |
1 files changed, 2 insertions, 8 deletions
diff --git a/net/core/sock.c b/net/core/sock.c index b43e260..590e7a7 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -535,10 +535,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname, val = sysctl_wmem_max; set_sndbuf: sk->sk_userlocks |= SOCK_SNDBUF_LOCK; - if ((val * 2) < SOCK_MIN_SNDBUF) - sk->sk_sndbuf = SOCK_MIN_SNDBUF; - else - sk->sk_sndbuf = val * 2; + sk->sk_sndbuf = max_t(int, val * 2, SOCK_MIN_SNDBUF); /* * Wake up sending tasks if we @@ -579,10 +576,7 @@ set_rcvbuf: * returning the value we actually used in getsockopt * is the most desirable behavior. */ - if ((val * 2) < SOCK_MIN_RCVBUF) - sk->sk_rcvbuf = SOCK_MIN_RCVBUF; - else - sk->sk_rcvbuf = val * 2; + sk->sk_rcvbuf = max_t(int, val * 2, SOCK_MIN_RCVBUF); break; case SO_RCVBUFFORCE: |