net/packet: check length in getsockopt() called with PACKET_HDRLEN
authorAlexander Potapenko <glider@google.com>
Tue, 25 Apr 2017 16:51:46 +0000 (18:51 +0200)
committerDanny Wood <danwood76@gmail.com>
Tue, 29 Jan 2019 13:18:24 +0000 (13:18 +0000)
commit fd2c83b35752f0a8236b976978ad4658df14a59f upstream.

In the case getsockopt() is called with PACKET_HDRLEN and optlen < 4
|val| remains uninitialized and the syscall may behave differently
depending on its value, and even copy garbage to userspace on certain
architectures. To fix this we now return -EINVAL if optlen is too small.

This bug has been detected with KMSAN.

Signed-off-by: Alexander Potapenko <glider@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Willy Tarreau <w@1wt.eu>
net/packet/af_packet.c

index 0dbbe52defbeff8d5bbdb41285edf655a2af672d..e3711c8b7bc5cbc5b85f5f2dec00d24c56fd0295 100644 (file)
@@ -3356,6 +3356,8 @@ static int packet_getsockopt(struct socket *sock, int level, int optname,
        case PACKET_HDRLEN:
                if (len > sizeof(int))
                        len = sizeof(int);
+               if (len < sizeof(int))
+                       return -EINVAL;
                if (copy_from_user(&val, optval, len))
                        return -EFAULT;
                switch (val) {