@@ -1960,6 +1960,64 @@ static unsigned int run_filter(struct sk_buff *skb,
1960
1960
return res ;
1961
1961
}
1962
1962
1963
+ static int __packet_rcv_vnet (const struct sk_buff * skb ,
1964
+ struct virtio_net_hdr * vnet_hdr )
1965
+ {
1966
+ * vnet_hdr = (const struct virtio_net_hdr ) { 0 };
1967
+
1968
+ if (skb_is_gso (skb )) {
1969
+ struct skb_shared_info * sinfo = skb_shinfo (skb );
1970
+
1971
+ /* This is a hint as to how much should be linear. */
1972
+ vnet_hdr -> hdr_len =
1973
+ __cpu_to_virtio16 (vio_le (), skb_headlen (skb ));
1974
+ vnet_hdr -> gso_size =
1975
+ __cpu_to_virtio16 (vio_le (), sinfo -> gso_size );
1976
+
1977
+ if (sinfo -> gso_type & SKB_GSO_TCPV4 )
1978
+ vnet_hdr -> gso_type = VIRTIO_NET_HDR_GSO_TCPV4 ;
1979
+ else if (sinfo -> gso_type & SKB_GSO_TCPV6 )
1980
+ vnet_hdr -> gso_type = VIRTIO_NET_HDR_GSO_TCPV6 ;
1981
+ else if (sinfo -> gso_type & SKB_GSO_UDP )
1982
+ vnet_hdr -> gso_type = VIRTIO_NET_HDR_GSO_UDP ;
1983
+ else if (sinfo -> gso_type & SKB_GSO_FCOE )
1984
+ return - EINVAL ;
1985
+ else
1986
+ BUG ();
1987
+
1988
+ if (sinfo -> gso_type & SKB_GSO_TCP_ECN )
1989
+ vnet_hdr -> gso_type |= VIRTIO_NET_HDR_GSO_ECN ;
1990
+ } else
1991
+ vnet_hdr -> gso_type = VIRTIO_NET_HDR_GSO_NONE ;
1992
+
1993
+ if (skb -> ip_summed == CHECKSUM_PARTIAL ) {
1994
+ vnet_hdr -> flags = VIRTIO_NET_HDR_F_NEEDS_CSUM ;
1995
+ vnet_hdr -> csum_start = __cpu_to_virtio16 (vio_le (),
1996
+ skb_checksum_start_offset (skb ));
1997
+ vnet_hdr -> csum_offset = __cpu_to_virtio16 (vio_le (),
1998
+ skb -> csum_offset );
1999
+ } else if (skb -> ip_summed == CHECKSUM_UNNECESSARY ) {
2000
+ vnet_hdr -> flags = VIRTIO_NET_HDR_F_DATA_VALID ;
2001
+ } /* else everything is zero */
2002
+
2003
+ return 0 ;
2004
+ }
2005
+
2006
+ static int packet_rcv_vnet (struct msghdr * msg , const struct sk_buff * skb ,
2007
+ size_t * len )
2008
+ {
2009
+ struct virtio_net_hdr vnet_hdr ;
2010
+
2011
+ if (* len < sizeof (vnet_hdr ))
2012
+ return - EINVAL ;
2013
+ * len -= sizeof (vnet_hdr );
2014
+
2015
+ if (__packet_rcv_vnet (skb , & vnet_hdr ))
2016
+ return - EINVAL ;
2017
+
2018
+ return memcpy_to_msg (msg , (void * )& vnet_hdr , sizeof (vnet_hdr ));
2019
+ }
2020
+
1963
2021
/*
1964
2022
* This function makes lazy skb cloning in hope that most of packets
1965
2023
* are discarded by BPF.
@@ -2347,6 +2405,84 @@ static void tpacket_set_protocol(const struct net_device *dev,
2347
2405
}
2348
2406
}
2349
2407
2408
+ static int __packet_snd_vnet_parse (struct virtio_net_hdr * vnet_hdr , size_t len )
2409
+ {
2410
+ unsigned short gso_type = 0 ;
2411
+
2412
+ if ((vnet_hdr -> flags & VIRTIO_NET_HDR_F_NEEDS_CSUM ) &&
2413
+ (__virtio16_to_cpu (vio_le (), vnet_hdr -> csum_start ) +
2414
+ __virtio16_to_cpu (vio_le (), vnet_hdr -> csum_offset ) + 2 >
2415
+ __virtio16_to_cpu (vio_le (), vnet_hdr -> hdr_len )))
2416
+ vnet_hdr -> hdr_len = __cpu_to_virtio16 (vio_le (),
2417
+ __virtio16_to_cpu (vio_le (), vnet_hdr -> csum_start ) +
2418
+ __virtio16_to_cpu (vio_le (), vnet_hdr -> csum_offset ) + 2 );
2419
+
2420
+ if (__virtio16_to_cpu (vio_le (), vnet_hdr -> hdr_len ) > len )
2421
+ return - EINVAL ;
2422
+
2423
+ if (vnet_hdr -> gso_type != VIRTIO_NET_HDR_GSO_NONE ) {
2424
+ switch (vnet_hdr -> gso_type & ~VIRTIO_NET_HDR_GSO_ECN ) {
2425
+ case VIRTIO_NET_HDR_GSO_TCPV4 :
2426
+ gso_type = SKB_GSO_TCPV4 ;
2427
+ break ;
2428
+ case VIRTIO_NET_HDR_GSO_TCPV6 :
2429
+ gso_type = SKB_GSO_TCPV6 ;
2430
+ break ;
2431
+ case VIRTIO_NET_HDR_GSO_UDP :
2432
+ gso_type = SKB_GSO_UDP ;
2433
+ break ;
2434
+ default :
2435
+ return - EINVAL ;
2436
+ }
2437
+
2438
+ if (vnet_hdr -> gso_type & VIRTIO_NET_HDR_GSO_ECN )
2439
+ gso_type |= SKB_GSO_TCP_ECN ;
2440
+
2441
+ if (vnet_hdr -> gso_size == 0 )
2442
+ return - EINVAL ;
2443
+ }
2444
+
2445
+ vnet_hdr -> gso_type = gso_type ; /* changes type, temporary storage */
2446
+ return 0 ;
2447
+ }
2448
+
2449
+ static int packet_snd_vnet_parse (struct msghdr * msg , size_t * len ,
2450
+ struct virtio_net_hdr * vnet_hdr )
2451
+ {
2452
+ int n ;
2453
+
2454
+ if (* len < sizeof (* vnet_hdr ))
2455
+ return - EINVAL ;
2456
+ * len -= sizeof (* vnet_hdr );
2457
+
2458
+ n = copy_from_iter (vnet_hdr , sizeof (* vnet_hdr ), & msg -> msg_iter );
2459
+ if (n != sizeof (* vnet_hdr ))
2460
+ return - EFAULT ;
2461
+
2462
+ return __packet_snd_vnet_parse (vnet_hdr , * len );
2463
+ }
2464
+
2465
+ static int packet_snd_vnet_gso (struct sk_buff * skb ,
2466
+ struct virtio_net_hdr * vnet_hdr )
2467
+ {
2468
+ if (vnet_hdr -> flags & VIRTIO_NET_HDR_F_NEEDS_CSUM ) {
2469
+ u16 s = __virtio16_to_cpu (vio_le (), vnet_hdr -> csum_start );
2470
+ u16 o = __virtio16_to_cpu (vio_le (), vnet_hdr -> csum_offset );
2471
+
2472
+ if (!skb_partial_csum_set (skb , s , o ))
2473
+ return - EINVAL ;
2474
+ }
2475
+
2476
+ skb_shinfo (skb )-> gso_size =
2477
+ __virtio16_to_cpu (vio_le (), vnet_hdr -> gso_size );
2478
+ skb_shinfo (skb )-> gso_type = vnet_hdr -> gso_type ;
2479
+
2480
+ /* Header must be checked, and gso_segs computed. */
2481
+ skb_shinfo (skb )-> gso_type |= SKB_GSO_DODGY ;
2482
+ skb_shinfo (skb )-> gso_segs = 0 ;
2483
+ return 0 ;
2484
+ }
2485
+
2350
2486
static int tpacket_fill_skb (struct packet_sock * po , struct sk_buff * skb ,
2351
2487
void * frame , struct net_device * dev , int size_max ,
2352
2488
__be16 proto , unsigned char * addr , int hlen )
@@ -2643,12 +2779,9 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
2643
2779
struct sockcm_cookie sockc ;
2644
2780
struct virtio_net_hdr vnet_hdr = { 0 };
2645
2781
int offset = 0 ;
2646
- int vnet_hdr_len ;
2647
2782
struct packet_sock * po = pkt_sk (sk );
2648
- unsigned short gso_type = 0 ;
2649
2783
int hlen , tlen ;
2650
2784
int extra_len = 0 ;
2651
- ssize_t n ;
2652
2785
2653
2786
/*
2654
2787
* Get and verify the address.
@@ -2686,53 +2819,9 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
2686
2819
if (sock -> type == SOCK_RAW )
2687
2820
reserve = dev -> hard_header_len ;
2688
2821
if (po -> has_vnet_hdr ) {
2689
- vnet_hdr_len = sizeof (vnet_hdr );
2690
-
2691
- err = - EINVAL ;
2692
- if (len < vnet_hdr_len )
2693
- goto out_unlock ;
2694
-
2695
- len -= vnet_hdr_len ;
2696
-
2697
- err = - EFAULT ;
2698
- n = copy_from_iter (& vnet_hdr , vnet_hdr_len , & msg -> msg_iter );
2699
- if (n != vnet_hdr_len )
2700
- goto out_unlock ;
2701
-
2702
- if ((vnet_hdr .flags & VIRTIO_NET_HDR_F_NEEDS_CSUM ) &&
2703
- (__virtio16_to_cpu (vio_le (), vnet_hdr .csum_start ) +
2704
- __virtio16_to_cpu (vio_le (), vnet_hdr .csum_offset ) + 2 >
2705
- __virtio16_to_cpu (vio_le (), vnet_hdr .hdr_len )))
2706
- vnet_hdr .hdr_len = __cpu_to_virtio16 (vio_le (),
2707
- __virtio16_to_cpu (vio_le (), vnet_hdr .csum_start ) +
2708
- __virtio16_to_cpu (vio_le (), vnet_hdr .csum_offset ) + 2 );
2709
-
2710
- err = - EINVAL ;
2711
- if (__virtio16_to_cpu (vio_le (), vnet_hdr .hdr_len ) > len )
2822
+ err = packet_snd_vnet_parse (msg , & len , & vnet_hdr );
2823
+ if (err )
2712
2824
goto out_unlock ;
2713
-
2714
- if (vnet_hdr .gso_type != VIRTIO_NET_HDR_GSO_NONE ) {
2715
- switch (vnet_hdr .gso_type & ~VIRTIO_NET_HDR_GSO_ECN ) {
2716
- case VIRTIO_NET_HDR_GSO_TCPV4 :
2717
- gso_type = SKB_GSO_TCPV4 ;
2718
- break ;
2719
- case VIRTIO_NET_HDR_GSO_TCPV6 :
2720
- gso_type = SKB_GSO_TCPV6 ;
2721
- break ;
2722
- case VIRTIO_NET_HDR_GSO_UDP :
2723
- gso_type = SKB_GSO_UDP ;
2724
- break ;
2725
- default :
2726
- goto out_unlock ;
2727
- }
2728
-
2729
- if (vnet_hdr .gso_type & VIRTIO_NET_HDR_GSO_ECN )
2730
- gso_type |= SKB_GSO_TCP_ECN ;
2731
-
2732
- if (vnet_hdr .gso_size == 0 )
2733
- goto out_unlock ;
2734
-
2735
- }
2736
2825
}
2737
2826
2738
2827
if (unlikely (sock_flag (sk , SOCK_NOFCS ))) {
@@ -2744,7 +2833,8 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
2744
2833
}
2745
2834
2746
2835
err = - EMSGSIZE ;
2747
- if (!gso_type && (len > dev -> mtu + reserve + VLAN_HLEN + extra_len ))
2836
+ if (!vnet_hdr .gso_type &&
2837
+ (len > dev -> mtu + reserve + VLAN_HLEN + extra_len ))
2748
2838
goto out_unlock ;
2749
2839
2750
2840
err = - ENOBUFS ;
@@ -2775,7 +2865,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
2775
2865
2776
2866
sock_tx_timestamp (sk , & skb_shinfo (skb )-> tx_flags );
2777
2867
2778
- if (!gso_type && (len > dev -> mtu + reserve + extra_len ) &&
2868
+ if (!vnet_hdr . gso_type && (len > dev -> mtu + reserve + extra_len ) &&
2779
2869
!packet_extra_vlan_len_allowed (dev , skb )) {
2780
2870
err = - EMSGSIZE ;
2781
2871
goto out_free ;
@@ -2789,24 +2879,10 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
2789
2879
packet_pick_tx_queue (dev , skb );
2790
2880
2791
2881
if (po -> has_vnet_hdr ) {
2792
- if (vnet_hdr .flags & VIRTIO_NET_HDR_F_NEEDS_CSUM ) {
2793
- u16 s = __virtio16_to_cpu (vio_le (), vnet_hdr .csum_start );
2794
- u16 o = __virtio16_to_cpu (vio_le (), vnet_hdr .csum_offset );
2795
- if (!skb_partial_csum_set (skb , s , o )) {
2796
- err = - EINVAL ;
2797
- goto out_free ;
2798
- }
2799
- }
2800
-
2801
- skb_shinfo (skb )-> gso_size =
2802
- __virtio16_to_cpu (vio_le (), vnet_hdr .gso_size );
2803
- skb_shinfo (skb )-> gso_type = gso_type ;
2804
-
2805
- /* Header must be checked, and gso_segs computed. */
2806
- skb_shinfo (skb )-> gso_type |= SKB_GSO_DODGY ;
2807
- skb_shinfo (skb )-> gso_segs = 0 ;
2808
-
2809
- len += vnet_hdr_len ;
2882
+ err = packet_snd_vnet_gso (skb , & vnet_hdr );
2883
+ if (err )
2884
+ goto out_free ;
2885
+ len += sizeof (vnet_hdr );
2810
2886
}
2811
2887
2812
2888
skb_probe_transport_header (skb , reserve );
@@ -3177,51 +3253,10 @@ static int packet_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
3177
3253
packet_rcv_has_room (pkt_sk (sk ), NULL );
3178
3254
3179
3255
if (pkt_sk (sk )-> has_vnet_hdr ) {
3180
- struct virtio_net_hdr vnet_hdr = { 0 };
3181
-
3182
- err = - EINVAL ;
3183
- vnet_hdr_len = sizeof (vnet_hdr );
3184
- if (len < vnet_hdr_len )
3185
- goto out_free ;
3186
-
3187
- len -= vnet_hdr_len ;
3188
-
3189
- if (skb_is_gso (skb )) {
3190
- struct skb_shared_info * sinfo = skb_shinfo (skb );
3191
-
3192
- /* This is a hint as to how much should be linear. */
3193
- vnet_hdr .hdr_len =
3194
- __cpu_to_virtio16 (vio_le (), skb_headlen (skb ));
3195
- vnet_hdr .gso_size =
3196
- __cpu_to_virtio16 (vio_le (), sinfo -> gso_size );
3197
- if (sinfo -> gso_type & SKB_GSO_TCPV4 )
3198
- vnet_hdr .gso_type = VIRTIO_NET_HDR_GSO_TCPV4 ;
3199
- else if (sinfo -> gso_type & SKB_GSO_TCPV6 )
3200
- vnet_hdr .gso_type = VIRTIO_NET_HDR_GSO_TCPV6 ;
3201
- else if (sinfo -> gso_type & SKB_GSO_UDP )
3202
- vnet_hdr .gso_type = VIRTIO_NET_HDR_GSO_UDP ;
3203
- else if (sinfo -> gso_type & SKB_GSO_FCOE )
3204
- goto out_free ;
3205
- else
3206
- BUG ();
3207
- if (sinfo -> gso_type & SKB_GSO_TCP_ECN )
3208
- vnet_hdr .gso_type |= VIRTIO_NET_HDR_GSO_ECN ;
3209
- } else
3210
- vnet_hdr .gso_type = VIRTIO_NET_HDR_GSO_NONE ;
3211
-
3212
- if (skb -> ip_summed == CHECKSUM_PARTIAL ) {
3213
- vnet_hdr .flags = VIRTIO_NET_HDR_F_NEEDS_CSUM ;
3214
- vnet_hdr .csum_start = __cpu_to_virtio16 (vio_le (),
3215
- skb_checksum_start_offset (skb ));
3216
- vnet_hdr .csum_offset = __cpu_to_virtio16 (vio_le (),
3217
- skb -> csum_offset );
3218
- } else if (skb -> ip_summed == CHECKSUM_UNNECESSARY ) {
3219
- vnet_hdr .flags = VIRTIO_NET_HDR_F_DATA_VALID ;
3220
- } /* else everything is zero */
3221
-
3222
- err = memcpy_to_msg (msg , (void * )& vnet_hdr , vnet_hdr_len );
3223
- if (err < 0 )
3256
+ err = packet_rcv_vnet (msg , skb , & len );
3257
+ if (err )
3224
3258
goto out_free ;
3259
+ vnet_hdr_len = sizeof (struct virtio_net_hdr );
3225
3260
}
3226
3261
3227
3262
/* You lose any data beyond the buffer you gave. If it worries
0 commit comments