• Matthew Dawson's avatar
    datagram: When peeking datagrams with offset < 0 don't skip empty skbs · a0917e0b
    Matthew Dawson authored
    Due to commit e6afc8ac ("udp: remove
    headers from UDP packets before queueing"), when udp packets are being
    peeked the requested extra offset is always 0 as there is no need to skip
    the udp header.  However, when the offset is 0 and the next skb is
    of length 0, it is only returned once.  The behaviour can be seen with
    the following python script:
    
    from socket import *;
    f=socket(AF_INET6, SOCK_DGRAM | SOCK_NONBLOCK, 0);
    g=socket(AF_INET6, SOCK_DGRAM | SOCK_NONBLOCK, 0);
    f.bind(('::', 0));
    addr=('::1', f.getsockname()[1]);
    g.sendto(b'', addr)
    g.sendto(b'b', addr)
    print(f.recvfrom(10, MSG_PEEK));
    print(f.recvfrom(10, MSG_PEEK));
    
    Where the expected output should be the empty string twice.
    
    Instead, make sk_peek_offset return negative values, and pass those values
    to __skb_try_recv_datagram/__skb_try_recv_from_queue.  If the passed offset
    to __skb_try_recv_from_queue is negative, the checked skb is never skipped.
    __skb_try_recv_from_queue will then ensure the offset is reset back to 0
    if a peek is requested without an offset, unless no packets are found.
    
    Also simplify the if condition in __skb_try_recv_from_queue.  If _off is
    greater then 0, and off is greater then or equal to skb->len, then
    (_off || skb->len) must always be true assuming skb->len >= 0 is always
    true.
    
    Also remove a redundant check around a call to sk_peek_offset in af_unix.c,
    as it double checked if MSG_PEEK was set in the flags.
    
    V2:
     - Moved the negative fixup into __skb_try_recv_from_queue, and remove now
    redundant checks
     - Fix peeking in udp{,v6}_recvmsg to report the right value when the
    offset is 0
    
    V3:
     - Marked new branch in __skb_try_recv_from_queue as unlikely.
    Signed-off-by: default avatarMatthew Dawson <matthew@mjdsystems.ca>
    Acked-by: default avatarWillem de Bruijn <willemb@google.com>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    a0917e0b
af_unix.c 68.5 KB