All of lore.kernel.org
 help / color / mirror / Atom feed
From: kernel test robot <lkp@intel.com>
To: kbuild-all@lists.01.org
Subject: Re: [RFC PATCH] fix xfrm MTU regression
Date: Fri, 30 Apr 2021 04:37:45 +0800	[thread overview]
Message-ID: <202104300409.iAhWmxup-lkp@intel.com> (raw)
In-Reply-To: <20210429170254.5grfgsz2hgy2qjhk@dwarf.suse.cz>

[-- Attachment #1: Type: text/plain, Size: 16600 bytes --]

Hi Jiri,

[FYI, it's a private test report for your RFC patch.]
[auto build test WARNING on linus/master]
[also build test WARNING on v5.12 next-20210429]
[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]

url:    https://github.com/0day-ci/linux/commits/Jiri-Bohac/fix-xfrm-MTU-regression/20210430-010412
base:   https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git d72cd4ad4174cfd2257c426ad51e4f53bcfde9c9
config: x86_64-randconfig-a015-20210429 (attached as .config)
compiler: clang version 13.0.0 (https://github.com/llvm/llvm-project 9131a078901b00e68248a27a4f8c4b11bb1db1ae)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # install x86_64 cross compiling tool for clang build
        # apt-get install binutils-x86-64-linux-gnu
        # https://github.com/0day-ci/linux/commit/f556543e005a1eb6567fc299e60f7d92dc508f88
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Jiri-Bohac/fix-xfrm-MTU-regression/20210430-010412
        git checkout f556543e005a1eb6567fc299e60f7d92dc508f88
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 ARCH=x86_64 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> net/ipv6/ip6_output.c:1467:6: warning: variable 'headersize' is used uninitialized whenever 'if' condition is true [-Wsometimes-uninitialized]
           if (mtu < fragheaderlen ||
               ^~~~~~~~~~~~~~~~~~~~~~
   net/ipv6/ip6_output.c:1501:27: note: uninitialized use occurs here
                   pmtu = max_t(int, mtu - headersize + sizeof(struct ipv6hdr), 0);
                                           ^~~~~~~~~~
   include/linux/minmax.h:118:48: note: expanded from macro 'max_t'
   #define max_t(type, x, y)       __careful_cmp((type)(x), (type)(y), >)
                                                        ^
   include/linux/minmax.h:44:14: note: expanded from macro '__careful_cmp'
                   __cmp_once(x, y, __UNIQUE_ID(__x), __UNIQUE_ID(__y), op))
                              ^
   include/linux/minmax.h:37:25: note: expanded from macro '__cmp_once'
                   typeof(x) unique_x = (x);               \
                                         ^
   net/ipv6/ip6_output.c:1467:2: note: remove the 'if' if its condition is always false
           if (mtu < fragheaderlen ||
           ^~~~~~~~~~~~~~~~~~~~~~~~~~
>> net/ipv6/ip6_output.c:1467:6: warning: variable 'headersize' is used uninitialized whenever '||' condition is true [-Wsometimes-uninitialized]
           if (mtu < fragheaderlen ||
               ^~~~~~~~~~~~~~~~~~~
   net/ipv6/ip6_output.c:1501:27: note: uninitialized use occurs here
                   pmtu = max_t(int, mtu - headersize + sizeof(struct ipv6hdr), 0);
                                           ^~~~~~~~~~
   include/linux/minmax.h:118:48: note: expanded from macro 'max_t'
   #define max_t(type, x, y)       __careful_cmp((type)(x), (type)(y), >)
                                                        ^
   include/linux/minmax.h:44:14: note: expanded from macro '__careful_cmp'
                   __cmp_once(x, y, __UNIQUE_ID(__x), __UNIQUE_ID(__y), op))
                              ^
   include/linux/minmax.h:37:25: note: expanded from macro '__cmp_once'
                   typeof(x) unique_x = (x);               \
                                         ^
   net/ipv6/ip6_output.c:1467:6: note: remove the '||' if its condition is always false
           if (mtu < fragheaderlen ||
               ^~~~~~~~~~~~~~~~~~~~~~
   net/ipv6/ip6_output.c:1444:41: note: initialize the variable 'headersize' to silence this warning
           unsigned int maxnonfragsize, headersize;
                                                  ^
                                                   = 0
   2 warnings generated.


vim +1467 net/ipv6/ip6_output.c

  1419	
  1420	static int __ip6_append_data(struct sock *sk,
  1421				     struct flowi6 *fl6,
  1422				     struct sk_buff_head *queue,
  1423				     struct inet_cork *cork,
  1424				     struct inet6_cork *v6_cork,
  1425				     struct page_frag *pfrag,
  1426				     int getfrag(void *from, char *to, int offset,
  1427						 int len, int odd, struct sk_buff *skb),
  1428				     void *from, int length, int transhdrlen,
  1429				     unsigned int flags, struct ipcm6_cookie *ipc6)
  1430	{
  1431		struct sk_buff *skb, *skb_prev = NULL;
  1432		unsigned int maxfraglen, fragheaderlen, mtu, orig_mtu, pmtu;
  1433		struct ubuf_info *uarg = NULL;
  1434		int exthdrlen = 0;
  1435		int dst_exthdrlen = 0;
  1436		int hh_len;
  1437		int copy;
  1438		int err;
  1439		int offset = 0;
  1440		u32 tskey = 0;
  1441		struct rt6_info *rt = (struct rt6_info *)cork->dst;
  1442		struct ipv6_txoptions *opt = v6_cork->opt;
  1443		int csummode = CHECKSUM_NONE;
  1444		unsigned int maxnonfragsize, headersize;
  1445		unsigned int wmem_alloc_delta = 0;
  1446		bool paged, extra_uref = false;
  1447	
  1448		skb = skb_peek_tail(queue);
  1449		if (!skb) {
  1450			exthdrlen = opt ? opt->opt_flen : 0;
  1451			dst_exthdrlen = rt->dst.header_len - rt->rt6i_nfheader_len;
  1452		}
  1453	
  1454		paged = !!cork->gso_size;
  1455		mtu = cork->gso_size ? IP6_MAX_MTU : cork->fragsize;
  1456		orig_mtu = mtu;
  1457	
  1458		if (cork->tx_flags & SKBTX_ANY_SW_TSTAMP &&
  1459		    sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID)
  1460			tskey = sk->sk_tskey++;
  1461	
  1462		hh_len = LL_RESERVED_SPACE(rt->dst.dev);
  1463	
  1464		fragheaderlen = sizeof(struct ipv6hdr) + rt->rt6i_nfheader_len +
  1465				(opt ? opt->opt_nflen : 0);
  1466	
> 1467		if (mtu < fragheaderlen ||
  1468		    ((mtu - fragheaderlen) & ~7) + fragheaderlen < sizeof(struct frag_hdr))
  1469			goto emsgsize;
  1470	
  1471		maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen -
  1472			     sizeof(struct frag_hdr);
  1473	
  1474		headersize = sizeof(struct ipv6hdr) +
  1475			     (opt ? opt->opt_flen + opt->opt_nflen : 0) +
  1476			     (dst_allfrag(&rt->dst) ?
  1477			      sizeof(struct frag_hdr) : 0) +
  1478			     rt->rt6i_nfheader_len;
  1479	
  1480		/* as per RFC 7112 section 5, the entire IPv6 Header Chain must fit
  1481		 * the first fragment
  1482		 */
  1483		if (headersize + transhdrlen > mtu)
  1484			goto emsgsize;
  1485	
  1486		if (cork->length + length > mtu - headersize && ipc6->dontfrag &&
  1487		    (sk->sk_protocol == IPPROTO_UDP ||
  1488		     sk->sk_protocol == IPPROTO_RAW)) {
  1489			ipv6_local_rxpmtu(sk, fl6, mtu - headersize +
  1490					sizeof(struct ipv6hdr));
  1491			goto emsgsize;
  1492		}
  1493	
  1494		if (ip6_sk_ignore_df(sk))
  1495			maxnonfragsize = sizeof(struct ipv6hdr) + IPV6_MAXPLEN;
  1496		else
  1497			maxnonfragsize = mtu;
  1498	
  1499		if (cork->length + length > maxnonfragsize - headersize) {
  1500	emsgsize:
  1501			pmtu = max_t(int, mtu - headersize + sizeof(struct ipv6hdr), 0);
  1502			ipv6_local_error(sk, EMSGSIZE, fl6, pmtu);
  1503			return -EMSGSIZE;
  1504		}
  1505	
  1506		/* CHECKSUM_PARTIAL only with no extension headers and when
  1507		 * we are not going to fragment
  1508		 */
  1509		if (transhdrlen && sk->sk_protocol == IPPROTO_UDP &&
  1510		    headersize == sizeof(struct ipv6hdr) &&
  1511		    length <= mtu - headersize &&
  1512		    (!(flags & MSG_MORE) || cork->gso_size) &&
  1513		    rt->dst.dev->features & (NETIF_F_IPV6_CSUM | NETIF_F_HW_CSUM))
  1514			csummode = CHECKSUM_PARTIAL;
  1515	
  1516		if (flags & MSG_ZEROCOPY && length && sock_flag(sk, SOCK_ZEROCOPY)) {
  1517			uarg = msg_zerocopy_realloc(sk, length, skb_zcopy(skb));
  1518			if (!uarg)
  1519				return -ENOBUFS;
  1520			extra_uref = !skb_zcopy(skb);	/* only ref on new uarg */
  1521			if (rt->dst.dev->features & NETIF_F_SG &&
  1522			    csummode == CHECKSUM_PARTIAL) {
  1523				paged = true;
  1524			} else {
  1525				uarg->zerocopy = 0;
  1526				skb_zcopy_set(skb, uarg, &extra_uref);
  1527			}
  1528		}
  1529	
  1530		/*
  1531		 * Let's try using as much space as possible.
  1532		 * Use MTU if total length of the message fits into the MTU.
  1533		 * Otherwise, we need to reserve fragment header and
  1534		 * fragment alignment (= 8-15 octects, in total).
  1535		 *
  1536		 * Note that we may need to "move" the data from the tail
  1537		 * of the buffer to the new fragment when we split
  1538		 * the message.
  1539		 *
  1540		 * FIXME: It may be fragmented into multiple chunks
  1541		 *        at once if non-fragmentable extension headers
  1542		 *        are too large.
  1543		 * --yoshfuji
  1544		 */
  1545	
  1546		cork->length += length;
  1547		if (!skb)
  1548			goto alloc_new_skb;
  1549	
  1550		while (length > 0) {
  1551			/* Check if the remaining data fits into current packet. */
  1552			copy = (cork->length <= mtu && !(cork->flags & IPCORK_ALLFRAG) ? mtu : maxfraglen) - skb->len;
  1553			if (copy < length)
  1554				copy = maxfraglen - skb->len;
  1555	
  1556			if (copy <= 0) {
  1557				char *data;
  1558				unsigned int datalen;
  1559				unsigned int fraglen;
  1560				unsigned int fraggap;
  1561				unsigned int alloclen;
  1562				unsigned int pagedlen;
  1563	alloc_new_skb:
  1564				/* There's no room in the current skb */
  1565				if (skb)
  1566					fraggap = skb->len - maxfraglen;
  1567				else
  1568					fraggap = 0;
  1569				/* update mtu and maxfraglen if necessary */
  1570				if (!skb || !skb_prev)
  1571					ip6_append_data_mtu(&mtu, &maxfraglen,
  1572							    fragheaderlen, skb, rt,
  1573							    orig_mtu);
  1574	
  1575				skb_prev = skb;
  1576	
  1577				/*
  1578				 * If remaining data exceeds the mtu,
  1579				 * we know we need more fragment(s).
  1580				 */
  1581				datalen = length + fraggap;
  1582	
  1583				if (datalen > (cork->length <= mtu && !(cork->flags & IPCORK_ALLFRAG) ? mtu : maxfraglen) - fragheaderlen)
  1584					datalen = maxfraglen - fragheaderlen - rt->dst.trailer_len;
  1585				fraglen = datalen + fragheaderlen;
  1586				pagedlen = 0;
  1587	
  1588				if ((flags & MSG_MORE) &&
  1589				    !(rt->dst.dev->features&NETIF_F_SG))
  1590					alloclen = mtu;
  1591				else if (!paged)
  1592					alloclen = fraglen;
  1593				else {
  1594					alloclen = min_t(int, fraglen, MAX_HEADER);
  1595					pagedlen = fraglen - alloclen;
  1596				}
  1597	
  1598				alloclen += dst_exthdrlen;
  1599	
  1600				if (datalen != length + fraggap) {
  1601					/*
  1602					 * this is not the last fragment, the trailer
  1603					 * space is regarded as data space.
  1604					 */
  1605					datalen += rt->dst.trailer_len;
  1606				}
  1607	
  1608				alloclen += rt->dst.trailer_len;
  1609				fraglen = datalen + fragheaderlen;
  1610	
  1611				/*
  1612				 * We just reserve space for fragment header.
  1613				 * Note: this may be overallocation if the message
  1614				 * (without MSG_MORE) fits into the MTU.
  1615				 */
  1616				alloclen += sizeof(struct frag_hdr);
  1617	
  1618				copy = datalen - transhdrlen - fraggap - pagedlen;
  1619				if (copy < 0) {
  1620					err = -EINVAL;
  1621					goto error;
  1622				}
  1623				if (transhdrlen) {
  1624					skb = sock_alloc_send_skb(sk,
  1625							alloclen + hh_len,
  1626							(flags & MSG_DONTWAIT), &err);
  1627				} else {
  1628					skb = NULL;
  1629					if (refcount_read(&sk->sk_wmem_alloc) + wmem_alloc_delta <=
  1630					    2 * sk->sk_sndbuf)
  1631						skb = alloc_skb(alloclen + hh_len,
  1632								sk->sk_allocation);
  1633					if (unlikely(!skb))
  1634						err = -ENOBUFS;
  1635				}
  1636				if (!skb)
  1637					goto error;
  1638				/*
  1639				 *	Fill in the control structures
  1640				 */
  1641				skb->protocol = htons(ETH_P_IPV6);
  1642				skb->ip_summed = csummode;
  1643				skb->csum = 0;
  1644				/* reserve for fragmentation and ipsec header */
  1645				skb_reserve(skb, hh_len + sizeof(struct frag_hdr) +
  1646					    dst_exthdrlen);
  1647	
  1648				/*
  1649				 *	Find where to start putting bytes
  1650				 */
  1651				data = skb_put(skb, fraglen - pagedlen);
  1652				skb_set_network_header(skb, exthdrlen);
  1653				data += fragheaderlen;
  1654				skb->transport_header = (skb->network_header +
  1655							 fragheaderlen);
  1656				if (fraggap) {
  1657					skb->csum = skb_copy_and_csum_bits(
  1658						skb_prev, maxfraglen,
  1659						data + transhdrlen, fraggap);
  1660					skb_prev->csum = csum_sub(skb_prev->csum,
  1661								  skb->csum);
  1662					data += fraggap;
  1663					pskb_trim_unique(skb_prev, maxfraglen);
  1664				}
  1665				if (copy > 0 &&
  1666				    getfrag(from, data + transhdrlen, offset,
  1667					    copy, fraggap, skb) < 0) {
  1668					err = -EFAULT;
  1669					kfree_skb(skb);
  1670					goto error;
  1671				}
  1672	
  1673				offset += copy;
  1674				length -= copy + transhdrlen;
  1675				transhdrlen = 0;
  1676				exthdrlen = 0;
  1677				dst_exthdrlen = 0;
  1678	
  1679				/* Only the initial fragment is time stamped */
  1680				skb_shinfo(skb)->tx_flags = cork->tx_flags;
  1681				cork->tx_flags = 0;
  1682				skb_shinfo(skb)->tskey = tskey;
  1683				tskey = 0;
  1684				skb_zcopy_set(skb, uarg, &extra_uref);
  1685	
  1686				if ((flags & MSG_CONFIRM) && !skb_prev)
  1687					skb_set_dst_pending_confirm(skb, 1);
  1688	
  1689				/*
  1690				 * Put the packet on the pending queue
  1691				 */
  1692				if (!skb->destructor) {
  1693					skb->destructor = sock_wfree;
  1694					skb->sk = sk;
  1695					wmem_alloc_delta += skb->truesize;
  1696				}
  1697				__skb_queue_tail(queue, skb);
  1698				continue;
  1699			}
  1700	
  1701			if (copy > length)
  1702				copy = length;
  1703	
  1704			if (!(rt->dst.dev->features&NETIF_F_SG) &&
  1705			    skb_tailroom(skb) >= copy) {
  1706				unsigned int off;
  1707	
  1708				off = skb->len;
  1709				if (getfrag(from, skb_put(skb, copy),
  1710							offset, copy, off, skb) < 0) {
  1711					__skb_trim(skb, off);
  1712					err = -EFAULT;
  1713					goto error;
  1714				}
  1715			} else if (!uarg || !uarg->zerocopy) {
  1716				int i = skb_shinfo(skb)->nr_frags;
  1717	
  1718				err = -ENOMEM;
  1719				if (!sk_page_frag_refill(sk, pfrag))
  1720					goto error;
  1721	
  1722				if (!skb_can_coalesce(skb, i, pfrag->page,
  1723						      pfrag->offset)) {
  1724					err = -EMSGSIZE;
  1725					if (i == MAX_SKB_FRAGS)
  1726						goto error;
  1727	
  1728					__skb_fill_page_desc(skb, i, pfrag->page,
  1729							     pfrag->offset, 0);
  1730					skb_shinfo(skb)->nr_frags = ++i;
  1731					get_page(pfrag->page);
  1732				}
  1733				copy = min_t(int, copy, pfrag->size - pfrag->offset);
  1734				if (getfrag(from,
  1735					    page_address(pfrag->page) + pfrag->offset,
  1736					    offset, copy, skb->len, skb) < 0)
  1737					goto error_efault;
  1738	
  1739				pfrag->offset += copy;
  1740				skb_frag_size_add(&skb_shinfo(skb)->frags[i - 1], copy);
  1741				skb->len += copy;
  1742				skb->data_len += copy;
  1743				skb->truesize += copy;
  1744				wmem_alloc_delta += copy;
  1745			} else {
  1746				err = skb_zerocopy_iter_dgram(skb, from, copy);
  1747				if (err < 0)
  1748					goto error;
  1749			}
  1750			offset += copy;
  1751			length -= copy;
  1752		}
  1753	
  1754		if (wmem_alloc_delta)
  1755			refcount_add(wmem_alloc_delta, &sk->sk_wmem_alloc);
  1756		return 0;
  1757	
  1758	error_efault:
  1759		err = -EFAULT;
  1760	error:
  1761		net_zcopy_put_abort(uarg, extra_uref);
  1762		cork->length -= length;
  1763		IP6_INC_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS);
  1764		refcount_add(wmem_alloc_delta, &sk->sk_wmem_alloc);
  1765		return err;
  1766	}
  1767	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 33314 bytes --]

  parent reply	other threads:[~2021-04-29 20:37 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-04-29 17:02 [RFC PATCH] fix xfrm MTU regression Jiri Bohac
2021-04-29 19:48 ` Sabrina Dubroca
2021-04-29 20:25   ` Jiri Bohac
2021-05-01 10:23     ` Sabrina Dubroca
2021-04-29 20:37 ` kernel test robot [this message]
2021-04-30  5:36 ` [RFC PATCH v2] " Jiri Bohac
  -- strict thread matches above, loose matches on Subject: below --
2021-04-29 23:17 [RFC PATCH] " kernel test robot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=202104300409.iAhWmxup-lkp@intel.com \
    --to=lkp@intel.com \
    --cc=kbuild-all@lists.01.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.