Skip to content

Commit 677bf08

Browse files
Florian Westphaldavem330
authored andcommitted
udp: drop skb extensions before marking skb stateless
Once udp stack has set the UDP_SKB_IS_STATELESS flag, later skb free assumes all skb head state has been dropped already. This will leak the extension memory in case the skb has extensions other than the ipsec secpath, e.g. bridge nf data. To fix this, set the UDP_SKB_IS_STATELESS flag only if we don't have extensions or if the extension space can be free'd. Fixes: 895b5c9 ("netfilter: drop bridge nf reset from nf_reset") Cc: Paolo Abeni <[email protected]> Reported-by: Byron Stanoszek <[email protected]> Signed-off-by: Florian Westphal <[email protected]> Acked-by: Paolo Abeni <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent ff08ddb commit 677bf08

File tree

2 files changed

+28
-5
lines changed

2 files changed

+28
-5
lines changed

include/linux/skbuff.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4169,12 +4169,18 @@ static inline void skb_ext_reset(struct sk_buff *skb)
41694169
skb->active_extensions = 0;
41704170
}
41714171
}
4172+
4173+
static inline bool skb_has_extensions(struct sk_buff *skb)
4174+
{
4175+
return unlikely(skb->active_extensions);
4176+
}
41724177
#else
41734178
static inline void skb_ext_put(struct sk_buff *skb) {}
41744179
static inline void skb_ext_reset(struct sk_buff *skb) {}
41754180
static inline void skb_ext_del(struct sk_buff *skb, int unused) {}
41764181
static inline void __skb_ext_copy(struct sk_buff *d, const struct sk_buff *s) {}
41774182
static inline void skb_ext_copy(struct sk_buff *dst, const struct sk_buff *s) {}
4183+
static inline bool skb_has_extensions(struct sk_buff *skb) { return false; }
41784184
#endif /* CONFIG_SKB_EXTENSIONS */
41794185

41804186
static inline void nf_reset_ct(struct sk_buff *skb)

net/ipv4/udp.c

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1297,6 +1297,27 @@ int udp_sendpage(struct sock *sk, struct page *page, int offset,
12971297

12981298
#define UDP_SKB_IS_STATELESS 0x80000000
12991299

1300+
/* all head states (dst, sk, nf conntrack) except skb extensions are
1301+
* cleared by udp_rcv().
1302+
*
1303+
* We need to preserve secpath, if present, to eventually process
1304+
* IP_CMSG_PASSSEC at recvmsg() time.
1305+
*
1306+
* Other extensions can be cleared.
1307+
*/
1308+
static bool udp_try_make_stateless(struct sk_buff *skb)
1309+
{
1310+
if (!skb_has_extensions(skb))
1311+
return true;
1312+
1313+
if (!secpath_exists(skb)) {
1314+
skb_ext_reset(skb);
1315+
return true;
1316+
}
1317+
1318+
return false;
1319+
}
1320+
13001321
static void udp_set_dev_scratch(struct sk_buff *skb)
13011322
{
13021323
struct udp_dev_scratch *scratch = udp_skb_scratch(skb);
@@ -1308,11 +1329,7 @@ static void udp_set_dev_scratch(struct sk_buff *skb)
13081329
scratch->csum_unnecessary = !!skb_csum_unnecessary(skb);
13091330
scratch->is_linear = !skb_is_nonlinear(skb);
13101331
#endif
1311-
/* all head states execept sp (dst, sk, nf) are always cleared by
1312-
* udp_rcv() and we need to preserve secpath, if present, to eventually
1313-
* process IP_CMSG_PASSSEC at recvmsg() time
1314-
*/
1315-
if (likely(!skb_sec_path(skb)))
1332+
if (udp_try_make_stateless(skb))
13161333
scratch->_tsize_state |= UDP_SKB_IS_STATELESS;
13171334
}
13181335

0 commit comments

Comments
 (0)