• D
    ipv6: handle -EFAULT from skb_copy_bits · a98f9175
    Dave Jones 提交于
    By setting certain socket options on ipv6 raw sockets, we can confuse the
    length calculation in rawv6_push_pending_frames triggering a BUG_ON.
    
    RIP: 0010:[<ffffffff817c6390>] [<ffffffff817c6390>] rawv6_sendmsg+0xc30/0xc40
    RSP: 0018:ffff881f6c4a7c18  EFLAGS: 00010282
    RAX: 00000000fffffff2 RBX: ffff881f6c681680 RCX: 0000000000000002
    RDX: ffff881f6c4a7cf8 RSI: 0000000000000030 RDI: ffff881fed0f6a00
    RBP: ffff881f6c4a7da8 R08: 0000000000000000 R09: 0000000000000009
    R10: ffff881fed0f6a00 R11: 0000000000000009 R12: 0000000000000030
    R13: ffff881fed0f6a00 R14: ffff881fee39ba00 R15: ffff881fefa93a80
    
    Call Trace:
     [<ffffffff8118ba23>] ? unmap_page_range+0x693/0x830
     [<ffffffff81772697>] inet_sendmsg+0x67/0xa0
     [<ffffffff816d93f8>] sock_sendmsg+0x38/0x50
     [<ffffffff816d982f>] SYSC_sendto+0xef/0x170
     [<ffffffff816da27e>] SyS_sendto+0xe/0x10
     [<ffffffff81002910>] do_syscall_64+0x50/0xa0
     [<ffffffff817f7cbc>] entry_SYSCALL64_slow_path+0x25/0x25
    
    Handle by jumping to the failure path if skb_copy_bits gets an EFAULT.
    
    Reproducer:
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    
    #define LEN 504
    
    int main(int argc, char* argv[])
    {
    	int fd;
    	int zero = 0;
    	char buf[LEN];
    
    	memset(buf, 0, LEN);
    
    	fd = socket(AF_INET6, SOCK_RAW, 7);
    
    	setsockopt(fd, SOL_IPV6, IPV6_CHECKSUM, &zero, 4);
    	setsockopt(fd, SOL_IPV6, IPV6_DSTOPTS, &buf, LEN);
    
    	sendto(fd, buf, 1, 0, (struct sockaddr *) buf, 110);
    }
    Signed-off-by: NDave Jones <davej@codemonkey.org.uk>
    Signed-off-by: NDavid S. Miller <davem@davemloft.net>
    a98f9175
raw.c 31.0 KB