lkml.org 
[lkml]   [2017]   [Jan]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 3.12 133/235] ipv6: handle -EFAULT from skb_copy_bits
    Date
    From: Dave Jones <davej@codemonkey.org.uk>

    3.12-stable review patch. If anyone has any objections, please let me know.

    ===============

    [ Upstream commit a98f91758995cb59611e61318dddd8a6956b52c3 ]

    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: Dave Jones <davej@codemonkey.org.uk>
    Signed-off-by: David S. Miller <davem@davemloft.net>
    Signed-off-by: Jiri Slaby <jslaby@suse.cz>
    ---
    net/ipv6/raw.c | 7 +++++--
    1 file changed, 5 insertions(+), 2 deletions(-)

    diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
    index c4e69763c602..c2afb29dc1d7 100644
    --- a/net/ipv6/raw.c
    +++ b/net/ipv6/raw.c
    @@ -585,8 +585,11 @@ static int rawv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6,
    }

    offset += skb_transport_offset(skb);
    - if (skb_copy_bits(skb, offset, &csum, 2))
    - BUG();
    + err = skb_copy_bits(skb, offset, &csum, 2);
    + if (err < 0) {
    + ip6_flush_pending_frames(sk);
    + goto out;
    + }

    /* in case cksum was not initialized */
    if (unlikely(csum))
    --
    2.11.0
    \
     
     \ /
      Last update: 2017-01-27 12:13    [W:4.306 / U:0.056 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site