@@ -778,6 +778,26 @@ static unsigned int mergeable_ctx_to_truesize(void *mrg_ctx)
778
778
return (unsigned long )mrg_ctx & ((1 << MRG_CTX_HEADER_SHIFT ) - 1 );
779
779
}
780
780
781
+ static int check_mergeable_len (struct net_device * dev , void * mrg_ctx ,
782
+ unsigned int len )
783
+ {
784
+ unsigned int headroom , tailroom , room , truesize ;
785
+
786
+ truesize = mergeable_ctx_to_truesize (mrg_ctx );
787
+ headroom = mergeable_ctx_to_headroom (mrg_ctx );
788
+ tailroom = headroom ? sizeof (struct skb_shared_info ) : 0 ;
789
+ room = SKB_DATA_ALIGN (headroom + tailroom );
790
+
791
+ if (len > truesize - room ) {
792
+ pr_debug ("%s: rx error: len %u exceeds truesize %lu\n" ,
793
+ dev -> name , len , (unsigned long )(truesize - room ));
794
+ DEV_STATS_INC (dev , rx_length_errors );
795
+ return -1 ;
796
+ }
797
+
798
+ return 0 ;
799
+ }
800
+
781
801
static struct sk_buff * virtnet_build_skb (void * buf , unsigned int buflen ,
782
802
unsigned int headroom ,
783
803
unsigned int len )
@@ -1797,7 +1817,8 @@ static unsigned int virtnet_get_headroom(struct virtnet_info *vi)
1797
1817
* across multiple buffers (num_buf > 1), and we make sure buffers
1798
1818
* have enough headroom.
1799
1819
*/
1800
- static struct page * xdp_linearize_page (struct receive_queue * rq ,
1820
+ static struct page * xdp_linearize_page (struct net_device * dev ,
1821
+ struct receive_queue * rq ,
1801
1822
int * num_buf ,
1802
1823
struct page * p ,
1803
1824
int offset ,
@@ -1817,18 +1838,27 @@ static struct page *xdp_linearize_page(struct receive_queue *rq,
1817
1838
memcpy (page_address (page ) + page_off , page_address (p ) + offset , * len );
1818
1839
page_off += * len ;
1819
1840
1841
+ /* Only mergeable mode can go inside this while loop. In small mode,
1842
+ * *num_buf == 1, so it cannot go inside.
1843
+ */
1820
1844
while (-- * num_buf ) {
1821
1845
unsigned int buflen ;
1822
1846
void * buf ;
1847
+ void * ctx ;
1823
1848
int off ;
1824
1849
1825
- buf = virtnet_rq_get_buf (rq , & buflen , NULL );
1850
+ buf = virtnet_rq_get_buf (rq , & buflen , & ctx );
1826
1851
if (unlikely (!buf ))
1827
1852
goto err_buf ;
1828
1853
1829
1854
p = virt_to_head_page (buf );
1830
1855
off = buf - page_address (p );
1831
1856
1857
+ if (check_mergeable_len (dev , ctx , buflen )) {
1858
+ put_page (p );
1859
+ goto err_buf ;
1860
+ }
1861
+
1832
1862
/* guard against a misconfigured or uncooperative backend that
1833
1863
* is sending packet larger than the MTU.
1834
1864
*/
@@ -1917,7 +1947,7 @@ static struct sk_buff *receive_small_xdp(struct net_device *dev,
1917
1947
headroom = vi -> hdr_len + header_offset ;
1918
1948
buflen = SKB_DATA_ALIGN (GOOD_PACKET_LEN + headroom ) +
1919
1949
SKB_DATA_ALIGN (sizeof (struct skb_shared_info ));
1920
- xdp_page = xdp_linearize_page (rq , & num_buf , page ,
1950
+ xdp_page = xdp_linearize_page (dev , rq , & num_buf , page ,
1921
1951
offset , header_offset ,
1922
1952
& tlen );
1923
1953
if (!xdp_page )
@@ -2126,10 +2156,9 @@ static int virtnet_build_xdp_buff_mrg(struct net_device *dev,
2126
2156
struct virtnet_rq_stats * stats )
2127
2157
{
2128
2158
struct virtio_net_hdr_mrg_rxbuf * hdr = buf ;
2129
- unsigned int headroom , tailroom , room ;
2130
- unsigned int truesize , cur_frag_size ;
2131
2159
struct skb_shared_info * shinfo ;
2132
2160
unsigned int xdp_frags_truesz = 0 ;
2161
+ unsigned int truesize ;
2133
2162
struct page * page ;
2134
2163
skb_frag_t * frag ;
2135
2164
int offset ;
@@ -2172,21 +2201,14 @@ static int virtnet_build_xdp_buff_mrg(struct net_device *dev,
2172
2201
page = virt_to_head_page (buf );
2173
2202
offset = buf - page_address (page );
2174
2203
2175
- truesize = mergeable_ctx_to_truesize (ctx );
2176
- headroom = mergeable_ctx_to_headroom (ctx );
2177
- tailroom = headroom ? sizeof (struct skb_shared_info ) : 0 ;
2178
- room = SKB_DATA_ALIGN (headroom + tailroom );
2179
-
2180
- cur_frag_size = truesize ;
2181
- xdp_frags_truesz += cur_frag_size ;
2182
- if (unlikely (len > truesize - room || cur_frag_size > PAGE_SIZE )) {
2204
+ if (check_mergeable_len (dev , ctx , len )) {
2183
2205
put_page (page );
2184
- pr_debug ("%s: rx error: len %u exceeds truesize %lu\n" ,
2185
- dev -> name , len , (unsigned long )(truesize - room ));
2186
- DEV_STATS_INC (dev , rx_length_errors );
2187
2206
goto err ;
2188
2207
}
2189
2208
2209
+ truesize = mergeable_ctx_to_truesize (ctx );
2210
+ xdp_frags_truesz += truesize ;
2211
+
2190
2212
frag = & shinfo -> frags [shinfo -> nr_frags ++ ];
2191
2213
skb_frag_fill_page_desc (frag , page , offset , len );
2192
2214
if (page_is_pfmemalloc (page ))
@@ -2252,7 +2274,7 @@ static void *mergeable_xdp_get_buf(struct virtnet_info *vi,
2252
2274
*/
2253
2275
if (!xdp_prog -> aux -> xdp_has_frags ) {
2254
2276
/* linearize data for XDP */
2255
- xdp_page = xdp_linearize_page (rq , num_buf ,
2277
+ xdp_page = xdp_linearize_page (vi -> dev , rq , num_buf ,
2256
2278
* page , offset ,
2257
2279
XDP_PACKET_HEADROOM ,
2258
2280
len );
@@ -2400,18 +2422,12 @@ static struct sk_buff *receive_mergeable(struct net_device *dev,
2400
2422
struct sk_buff * head_skb , * curr_skb ;
2401
2423
unsigned int truesize = mergeable_ctx_to_truesize (ctx );
2402
2424
unsigned int headroom = mergeable_ctx_to_headroom (ctx );
2403
- unsigned int tailroom = headroom ? sizeof (struct skb_shared_info ) : 0 ;
2404
- unsigned int room = SKB_DATA_ALIGN (headroom + tailroom );
2405
2425
2406
2426
head_skb = NULL ;
2407
2427
u64_stats_add (& stats -> bytes , len - vi -> hdr_len );
2408
2428
2409
- if (unlikely (len > truesize - room )) {
2410
- pr_debug ("%s: rx error: len %u exceeds truesize %lu\n" ,
2411
- dev -> name , len , (unsigned long )(truesize - room ));
2412
- DEV_STATS_INC (dev , rx_length_errors );
2429
+ if (check_mergeable_len (dev , ctx , len ))
2413
2430
goto err_skb ;
2414
- }
2415
2431
2416
2432
if (unlikely (vi -> xdp_enabled )) {
2417
2433
struct bpf_prog * xdp_prog ;
@@ -2446,17 +2462,10 @@ static struct sk_buff *receive_mergeable(struct net_device *dev,
2446
2462
u64_stats_add (& stats -> bytes , len );
2447
2463
page = virt_to_head_page (buf );
2448
2464
2449
- truesize = mergeable_ctx_to_truesize (ctx );
2450
- headroom = mergeable_ctx_to_headroom (ctx );
2451
- tailroom = headroom ? sizeof (struct skb_shared_info ) : 0 ;
2452
- room = SKB_DATA_ALIGN (headroom + tailroom );
2453
- if (unlikely (len > truesize - room )) {
2454
- pr_debug ("%s: rx error: len %u exceeds truesize %lu\n" ,
2455
- dev -> name , len , (unsigned long )(truesize - room ));
2456
- DEV_STATS_INC (dev , rx_length_errors );
2465
+ if (check_mergeable_len (dev , ctx , len ))
2457
2466
goto err_skb ;
2458
- }
2459
2467
2468
+ truesize = mergeable_ctx_to_truesize (ctx );
2460
2469
curr_skb = virtnet_skb_append_frag (head_skb , curr_skb , page ,
2461
2470
buf , len , truesize );
2462
2471
if (!curr_skb )
0 commit comments