]>
Commit | Line | Data |
---|---|---|
91562c7b GKH |
1 | From foo@baz Wed 22 May 2019 08:37:51 AM CEST |
2 | From: Willem de Bruijn <willemb@google.com> | |
3 | Date: Wed, 15 May 2019 13:29:16 -0400 | |
4 | Subject: net: test nouarg before dereferencing zerocopy pointers | |
5 | ||
6 | From: Willem de Bruijn <willemb@google.com> | |
7 | ||
8 | [ Upstream commit 185ce5c38ea76f29b6bd9c7c8c7a5e5408834920 ] | |
9 | ||
10 | Zerocopy skbs without completion notification were added for packet | |
11 | sockets with PACKET_TX_RING user buffers. Those signal completion | |
12 | through the TP_STATUS_USER bit in the ring. Zerocopy annotation was | |
13 | added only to avoid premature notification after clone or orphan, by | |
14 | triggering a copy on these paths for these packets. | |
15 | ||
16 | The mechanism had to define a special "no-uarg" mode because packet | |
17 | sockets already use skb_uarg(skb) == skb_shinfo(skb)->destructor_arg | |
18 | for a different pointer. | |
19 | ||
20 | Before deferencing skb_uarg(skb), verify that it is a real pointer. | |
21 | ||
22 | Fixes: 5cd8d46ea1562 ("packet: copy user buffers before orphan or clone") | |
23 | Signed-off-by: Willem de Bruijn <willemb@google.com> | |
24 | Signed-off-by: David S. Miller <davem@davemloft.net> | |
25 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
26 | --- | |
27 | include/linux/skbuff.h | 9 ++++++--- | |
28 | 1 file changed, 6 insertions(+), 3 deletions(-) | |
29 | ||
30 | --- a/include/linux/skbuff.h | |
31 | +++ b/include/linux/skbuff.h | |
32 | @@ -1333,10 +1333,12 @@ static inline void skb_zcopy_clear(struc | |
33 | struct ubuf_info *uarg = skb_zcopy(skb); | |
34 | ||
35 | if (uarg) { | |
36 | - if (uarg->callback == sock_zerocopy_callback) { | |
37 | + if (skb_zcopy_is_nouarg(skb)) { | |
38 | + /* no notification callback */ | |
39 | + } else if (uarg->callback == sock_zerocopy_callback) { | |
40 | uarg->zerocopy = uarg->zerocopy && zerocopy; | |
41 | sock_zerocopy_put(uarg); | |
42 | - } else if (!skb_zcopy_is_nouarg(skb)) { | |
43 | + } else { | |
44 | uarg->callback(uarg, zerocopy); | |
45 | } | |
46 | ||
47 | @@ -2587,7 +2589,8 @@ static inline int skb_orphan_frags(struc | |
48 | { | |
49 | if (likely(!skb_zcopy(skb))) | |
50 | return 0; | |
51 | - if (skb_uarg(skb)->callback == sock_zerocopy_callback) | |
52 | + if (!skb_zcopy_is_nouarg(skb) && | |
53 | + skb_uarg(skb)->callback == sock_zerocopy_callback) | |
54 | return 0; | |
55 | return skb_copy_ubufs(skb, gfp_mask); | |
56 | } |