Skip to content

Commit 158f323

Browse files
edumazetdavem330
authored andcommitted
net: adjust skb->truesize in pskb_expand_head()
Slava Shwartsman reported a warning in skb_try_coalesce(), when we detect skb->truesize is completely wrong. In his case, issue came from IPv6 reassembly coping with malicious datagrams, that forced various pskb_may_pull() to reallocate a bigger skb->head than the one allocated by NIC driver before entering GRO layer. Current code does not change skb->truesize, leaving this burden to callers if they care enough. Blindly changing skb->truesize in pskb_expand_head() is not easy, as some producers might track skb->truesize, for example in xmit path for back pressure feedback (sk->sk_wmem_alloc) We can detect the cases where it should be safe to change skb->truesize : 1) skb is not attached to a socket. 2) If it is attached to a socket, destructor is sock_edemux() My audit gave only two callers doing their own skb->truesize manipulation. I had to remove skb parameter in sock_edemux macro when CONFIG_INET is not set to avoid a compile error. Signed-off-by: Eric Dumazet <[email protected]> Reported-by: Slava Shwartsman <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent b41fd8f commit 158f323

File tree

4 files changed

+15
-11
lines changed

4 files changed

+15
-11
lines changed

include/net/sock.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1534,7 +1534,7 @@ void sock_efree(struct sk_buff *skb);
15341534
#ifdef CONFIG_INET
15351535
void sock_edemux(struct sk_buff *skb);
15361536
#else
1537-
#define sock_edemux(skb) sock_efree(skb)
1537+
#define sock_edemux sock_efree
15381538
#endif
15391539

15401540
int sock_setsockopt(struct socket *sock, int level, int op,

net/core/skbuff.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1192,10 +1192,10 @@ EXPORT_SYMBOL(__pskb_copy_fclone);
11921192
int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,
11931193
gfp_t gfp_mask)
11941194
{
1195-
int i;
1196-
u8 *data;
1197-
int size = nhead + skb_end_offset(skb) + ntail;
1195+
int i, osize = skb_end_offset(skb);
1196+
int size = osize + nhead + ntail;
11981197
long off;
1198+
u8 *data;
11991199

12001200
BUG_ON(nhead < 0);
12011201

@@ -1257,6 +1257,14 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,
12571257
skb->hdr_len = 0;
12581258
skb->nohdr = 0;
12591259
atomic_set(&skb_shinfo(skb)->dataref, 1);
1260+
1261+
/* It is not generally safe to change skb->truesize.
1262+
* For the moment, we really care of rx path, or
1263+
* when skb is orphaned (not attached to a socket).
1264+
*/
1265+
if (!skb->sk || skb->destructor == sock_edemux)
1266+
skb->truesize += size - osize;
1267+
12601268
return 0;
12611269

12621270
nofrags:

net/netlink/af_netlink.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1210,11 +1210,9 @@ static struct sk_buff *netlink_trim(struct sk_buff *skb, gfp_t allocation)
12101210
skb = nskb;
12111211
}
12121212

1213-
if (!pskb_expand_head(skb, 0, -delta,
1214-
(allocation & ~__GFP_DIRECT_RECLAIM) |
1215-
__GFP_NOWARN | __GFP_NORETRY))
1216-
skb->truesize -= delta;
1217-
1213+
pskb_expand_head(skb, 0, -delta,
1214+
(allocation & ~__GFP_DIRECT_RECLAIM) |
1215+
__GFP_NOWARN | __GFP_NORETRY);
12181216
return skb;
12191217
}
12201218

net/wireless/util.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -618,8 +618,6 @@ int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr,
618618

619619
if (pskb_expand_head(skb, head_need, 0, GFP_ATOMIC))
620620
return -ENOMEM;
621-
622-
skb->truesize += head_need;
623621
}
624622

625623
if (encaps_data) {

0 commit comments

Comments
 (0)