Skip to content

Commit

Permalink
udp: fix linear skb reception with PEEK_OFF
Browse files Browse the repository at this point in the history
copy_linear_skb() is broken; both of its callers actually
expect 'len' to be the amount we are trying to copy,
not the offset of the end.
Fix it keeping the meanings of arguments in sync with what the
callers (both of them) expect.
Also restore a saner behavior on EFAULT (i.e. preserving
the iov_iter position in case of failure):

The commit fd851ba ("udp: harden copy_linear_skb()")
avoids the more destructive effect of the buggy
copy_linear_skb(), e.g. no more invalid memory access, but
said function still behaves incorrectly: when peeking with
offset it can fail with EINVAL instead of copying the
appropriate amount of memory.

Reported-by: Sasha Levin <[email protected]>
Fixes: b65ac44 ("udp: try to avoid 2 cache miss on dequeue")
Fixes: fd851ba ("udp: harden copy_linear_skb()")
Signed-off-by: Al Viro <[email protected]>
Acked-by: Paolo Abeni <[email protected]>
Tested-by: Sasha Levin <[email protected]>
Acked-by: Eric Dumazet <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
Al Viro authored and davem330 committed Aug 15, 2017
1 parent e5645f5 commit 42b7305
Showing 1 changed file with 4 additions and 5 deletions.
9 changes: 4 additions & 5 deletions include/net/udp.h
Original file line number Diff line number Diff line change
Expand Up @@ -366,14 +366,13 @@ static inline bool udp_skb_is_linear(struct sk_buff *skb)
static inline int copy_linear_skb(struct sk_buff *skb, int len, int off,
struct iov_iter *to)
{
int n, copy = len - off;
int n;

if (copy < 0)
return -EINVAL;
n = copy_to_iter(skb->data + off, copy, to);
if (n == copy)
n = copy_to_iter(skb->data + off, len, to);
if (n == len)
return 0;

iov_iter_revert(to, n);
return -EFAULT;
}

Expand Down

0 comments on commit 42b7305

Please sign in to comment.