[lvc-project] [PATCH] net: missing check

kernel test robot lkp at intel.com
Fri Jun 7 09:56:13 MSK 2024


Hi Denis,

kernel test robot noticed the following build warnings:

[auto build test WARNING on linus/master]
[also build test WARNING on v6.10-rc2 next-20240607]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Denis-Arefev/net-missing-check/20240606-230540
base:   linus/master
patch link:    https://lore.kernel.org/r/20240606141450.44709-1-arefev%40swemel.ru
patch subject: [PATCH] net: missing check
config: x86_64-randconfig-121-20240607 (https://download.01.org/0day-ci/archive/20240607/202406071404.OiLHfOHM-lkp@intel.com/config)
compiler: gcc-13 (Ubuntu 13.2.0-4ubuntu3) 13.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240607/202406071404.OiLHfOHM-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202406071404.OiLHfOHM-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
   drivers/net/virtio_net.c: note: in included file:
>> include/linux/virtio_net.h:103:58: sparse: sparse: incorrect type in argument 2 (different base types) @@     expected unsigned long long [usertype] divisor @@     got restricted __virtio16 const [usertype] gso_size @@
   include/linux/virtio_net.h:103:58: sparse:     expected unsigned long long [usertype] divisor
   include/linux/virtio_net.h:103:58: sparse:     got restricted __virtio16 const [usertype] gso_size
>> include/linux/virtio_net.h:104:42: sparse: sparse: restricted __virtio16 degrades to integer

vim +103 include/linux/virtio_net.h

    49	
    50	static inline int virtio_net_hdr_to_skb(struct sk_buff *skb,
    51						const struct virtio_net_hdr *hdr,
    52						bool little_endian)
    53	{
    54		unsigned int nh_min_len = sizeof(struct iphdr);
    55		unsigned int gso_type = 0;
    56		unsigned int thlen = 0;
    57		unsigned int p_off = 0;
    58		unsigned int ip_proto;
    59		u64 ret, remainder;
    60	
    61		if (hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) {
    62			switch (hdr->gso_type & ~VIRTIO_NET_HDR_GSO_ECN) {
    63			case VIRTIO_NET_HDR_GSO_TCPV4:
    64				gso_type = SKB_GSO_TCPV4;
    65				ip_proto = IPPROTO_TCP;
    66				thlen = sizeof(struct tcphdr);
    67				break;
    68			case VIRTIO_NET_HDR_GSO_TCPV6:
    69				gso_type = SKB_GSO_TCPV6;
    70				ip_proto = IPPROTO_TCP;
    71				thlen = sizeof(struct tcphdr);
    72				nh_min_len = sizeof(struct ipv6hdr);
    73				break;
    74			case VIRTIO_NET_HDR_GSO_UDP:
    75				gso_type = SKB_GSO_UDP;
    76				ip_proto = IPPROTO_UDP;
    77				thlen = sizeof(struct udphdr);
    78				break;
    79			case VIRTIO_NET_HDR_GSO_UDP_L4:
    80				gso_type = SKB_GSO_UDP_L4;
    81				ip_proto = IPPROTO_UDP;
    82				thlen = sizeof(struct udphdr);
    83				break;
    84			default:
    85				return -EINVAL;
    86			}
    87	
    88			if (hdr->gso_type & VIRTIO_NET_HDR_GSO_ECN)
    89				gso_type |= SKB_GSO_TCP_ECN;
    90	
    91			if (hdr->gso_size == 0)
    92				return -EINVAL;
    93		}
    94	
    95		skb_reset_mac_header(skb);
    96	
    97		if (hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) {
    98			u32 start = __virtio16_to_cpu(little_endian, hdr->csum_start);
    99			u32 off = __virtio16_to_cpu(little_endian, hdr->csum_offset);
   100			u32 needed = start + max_t(u32, thlen, off + sizeof(__sum16));
   101	
   102			if (hdr->gso_size) {
 > 103				ret = div64_u64_rem(skb->len, hdr->gso_size, &remainder);
 > 104				if (!(ret && (hdr->gso_size > needed) &&
   105							((remainder > needed) || (remainder == 0)))) {
   106					return -EINVAL;
   107				}
   108				skb_shinfo(skb)->tx_flags |= SKBFL_SHARED_FRAG;
   109			}
   110	
   111			if (!pskb_may_pull(skb, needed))
   112				return -EINVAL;
   113	
   114			if (!skb_partial_csum_set(skb, start, off))
   115				return -EINVAL;
   116	
   117			nh_min_len = max_t(u32, nh_min_len, skb_transport_offset(skb));
   118			p_off = nh_min_len + thlen;
   119			if (!pskb_may_pull(skb, p_off))
   120				return -EINVAL;
   121		} else {
   122			/* gso packets without NEEDS_CSUM do not set transport_offset.
   123			 * probe and drop if does not match one of the above types.
   124			 */
   125			if (gso_type && skb->network_header) {
   126				struct flow_keys_basic keys;
   127	
   128				if (!skb->protocol) {
   129					__be16 protocol = dev_parse_header_protocol(skb);
   130	
   131					if (!protocol)
   132						virtio_net_hdr_set_proto(skb, hdr);
   133					else if (!virtio_net_hdr_match_proto(protocol, hdr->gso_type))
   134						return -EINVAL;
   135					else
   136						skb->protocol = protocol;
   137				}
   138	retry:
   139				if (!skb_flow_dissect_flow_keys_basic(NULL, skb, &keys,
   140								      NULL, 0, 0, 0,
   141								      0)) {
   142					/* UFO does not specify ipv4 or 6: try both */
   143					if (gso_type & SKB_GSO_UDP &&
   144					    skb->protocol == htons(ETH_P_IP)) {
   145						skb->protocol = htons(ETH_P_IPV6);
   146						goto retry;
   147					}
   148					return -EINVAL;
   149				}
   150	
   151				p_off = keys.control.thoff + thlen;
   152				if (!pskb_may_pull(skb, p_off) ||
   153				    keys.basic.ip_proto != ip_proto)
   154					return -EINVAL;
   155	
   156				skb_set_transport_header(skb, keys.control.thoff);
   157			} else if (gso_type) {
   158				p_off = nh_min_len + thlen;
   159				if (!pskb_may_pull(skb, p_off))
   160					return -EINVAL;
   161			}
   162		}
   163	
   164		if (hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) {
   165			u16 gso_size = __virtio16_to_cpu(little_endian, hdr->gso_size);
   166			unsigned int nh_off = p_off;
   167			struct skb_shared_info *shinfo = skb_shinfo(skb);
   168	
   169			switch (gso_type & ~SKB_GSO_TCP_ECN) {
   170			case SKB_GSO_UDP:
   171				/* UFO may not include transport header in gso_size. */
   172				nh_off -= thlen;
   173				break;
   174			case SKB_GSO_UDP_L4:
   175				if (!(hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM))
   176					return -EINVAL;
   177				if (skb->csum_offset != offsetof(struct udphdr, check))
   178					return -EINVAL;
   179				if (skb->len - p_off > gso_size * UDP_MAX_SEGMENTS)
   180					return -EINVAL;
   181				if (gso_type != SKB_GSO_UDP_L4)
   182					return -EINVAL;
   183				break;
   184			}
   185	
   186			/* Kernel has a special handling for GSO_BY_FRAGS. */
   187			if (gso_size == GSO_BY_FRAGS)
   188				return -EINVAL;
   189	
   190			/* Too small packets are not really GSO ones. */
   191			if (skb->len - nh_off > gso_size) {
   192				shinfo->gso_size = gso_size;
   193				shinfo->gso_type = gso_type;
   194	
   195				/* Header must be checked, and gso_segs computed. */
   196				shinfo->gso_type |= SKB_GSO_DODGY;
   197				shinfo->gso_segs = 0;
   198			}
   199		}
   200	
   201		return 0;
   202	}
   203	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki



More information about the lvc-project mailing list