Re: fs/nfsd/nfs4xdr.c:4683:24: sparse: sparse: incorrect type in return expression (different base types)
From: Chuck Lever
Date: Wed Sep 23 2020 - 11:44:00 EST
> On Sep 23, 2020, at 11:42 AM, kernel test robot <lkp@xxxxxxxxx> wrote:
>
> tree: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master
> head: 805c6d3c19210c90c109107d189744e960eae025
> commit: 23e50fe3a5e6045a573c69d4b0e3d78aa6183323 nfsd: implement the xattr functions and en/decode logic
> date: 2 months ago
> config: m68k-randconfig-s032-20200923 (attached as .config)
> compiler: m68k-linux-gcc (GCC) 9.3.0
> reproduce:
> wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
> chmod +x ~/bin/make.cross
> # apt-get install sparse
> # sparse version: v0.6.2-201-g24bdaac6-dirty
> git checkout 23e50fe3a5e6045a573c69d4b0e3d78aa6183323
> # save the attached .config to linux build tree
> COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' ARCH=m68k
>
> If you fix the issue, kindly add following tag as appropriate
> Reported-by: kernel test robot <lkp@xxxxxxxxx>
I believe both of these robot reports are addressed by
patches I have sent to Bruce for v5.10.
> sparse warnings: (new ones prefixed by >>)
>
> fs/nfsd/nfs4xdr.c:1860:16: sparse: sparse: incorrect type in assignment (different base types) @@ expected int status @@ got restricted __be32 @@
> fs/nfsd/nfs4xdr.c:1860:16: sparse: expected int status
> fs/nfsd/nfs4xdr.c:1860:16: sparse: got restricted __be32
> fs/nfsd/nfs4xdr.c:1862:24: sparse: sparse: incorrect type in return expression (different base types) @@ expected restricted __be32 @@ got int status @@
> fs/nfsd/nfs4xdr.c:1862:24: sparse: expected restricted __be32
> fs/nfsd/nfs4xdr.c:1862:24: sparse: got int status
>>> fs/nfsd/nfs4xdr.c:4683:24: sparse: sparse: incorrect type in return expression (different base types) @@ expected int @@ got restricted __be32 [usertype] @@
>>> fs/nfsd/nfs4xdr.c:4683:24: sparse: expected int
>>> fs/nfsd/nfs4xdr.c:4683:24: sparse: got restricted __be32 [usertype]
> fs/nfsd/nfs4xdr.c:4693:32: sparse: sparse: incorrect type in return expression (different base types) @@ expected int @@ got restricted __be32 [usertype] @@
> fs/nfsd/nfs4xdr.c:4693:32: sparse: expected int
> fs/nfsd/nfs4xdr.c:4693:32: sparse: got restricted __be32 [usertype]
>>> fs/nfsd/nfs4xdr.c:4730:13: sparse: sparse: incorrect type in assignment (different base types) @@ expected restricted __be32 [usertype] err @@ got int @@
>>> fs/nfsd/nfs4xdr.c:4730:13: sparse: expected restricted __be32 [usertype] err
>>> fs/nfsd/nfs4xdr.c:4730:13: sparse: got int
>>> fs/nfsd/nfs4xdr.c:4882:15: sparse: sparse: incorrect type in assignment (different base types) @@ expected unsigned int [assigned] [usertype] count @@ got restricted __be32 [usertype] @@
>>> fs/nfsd/nfs4xdr.c:4882:15: sparse: expected unsigned int [assigned] [usertype] count
> fs/nfsd/nfs4xdr.c:4882:15: sparse: got restricted __be32 [usertype]
>
> # https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=23e50fe3a5e6045a573c69d4b0e3d78aa6183323
> git remote add linus https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
> git fetch --no-tags linus master
> git checkout 23e50fe3a5e6045a573c69d4b0e3d78aa6183323
> vim +4683 fs/nfsd/nfs4xdr.c
>
> 4669
> 4670 /*
> 4671 * Encode kmalloc-ed buffer in to XDR stream.
> 4672 */
> 4673 static int
> 4674 nfsd4_vbuf_to_stream(struct xdr_stream *xdr, char *buf, u32 buflen)
> 4675 {
> 4676 u32 cplen;
> 4677 __be32 *p;
> 4678
> 4679 cplen = min_t(unsigned long, buflen,
> 4680 ((void *)xdr->end - (void *)xdr->p));
> 4681 p = xdr_reserve_space(xdr, cplen);
> 4682 if (!p)
>> 4683 return nfserr_resource;
> 4684
> 4685 memcpy(p, buf, cplen);
> 4686 buf += cplen;
> 4687 buflen -= cplen;
> 4688
> 4689 while (buflen) {
> 4690 cplen = min_t(u32, buflen, PAGE_SIZE);
> 4691 p = xdr_reserve_space(xdr, cplen);
> 4692 if (!p)
> 4693 return nfserr_resource;
> 4694
> 4695 memcpy(p, buf, cplen);
> 4696
> 4697 if (cplen < PAGE_SIZE) {
> 4698 /*
> 4699 * We're done, with a length that wasn't page
> 4700 * aligned, so possibly not word aligned. Pad
> 4701 * any trailing bytes with 0.
> 4702 */
> 4703 xdr_encode_opaque_fixed(p, NULL, cplen);
> 4704 break;
> 4705 }
> 4706
> 4707 buflen -= PAGE_SIZE;
> 4708 buf += PAGE_SIZE;
> 4709 }
> 4710
> 4711 return 0;
> 4712 }
> 4713
> 4714 static __be32
> 4715 nfsd4_encode_getxattr(struct nfsd4_compoundres *resp, __be32 nfserr,
> 4716 struct nfsd4_getxattr *getxattr)
> 4717 {
> 4718 struct xdr_stream *xdr = &resp->xdr;
> 4719 __be32 *p, err;
> 4720
> 4721 p = xdr_reserve_space(xdr, 4);
> 4722 if (!p)
> 4723 return nfserr_resource;
> 4724
> 4725 *p = cpu_to_be32(getxattr->getxa_len);
> 4726
> 4727 if (getxattr->getxa_len == 0)
> 4728 return 0;
> 4729
>> 4730 err = nfsd4_vbuf_to_stream(xdr, getxattr->getxa_buf,
> 4731 getxattr->getxa_len);
> 4732
> 4733 kvfree(getxattr->getxa_buf);
> 4734
> 4735 return err;
> 4736 }
> 4737
> 4738 static __be32
> 4739 nfsd4_encode_setxattr(struct nfsd4_compoundres *resp, __be32 nfserr,
> 4740 struct nfsd4_setxattr *setxattr)
> 4741 {
> 4742 struct xdr_stream *xdr = &resp->xdr;
> 4743 __be32 *p;
> 4744
> 4745 p = xdr_reserve_space(xdr, 20);
> 4746 if (!p)
> 4747 return nfserr_resource;
> 4748
> 4749 encode_cinfo(p, &setxattr->setxa_cinfo);
> 4750
> 4751 return 0;
> 4752 }
> 4753
> 4754 /*
> 4755 * See if there are cookie values that can be rejected outright.
> 4756 */
> 4757 static __be32
> 4758 nfsd4_listxattr_validate_cookie(struct nfsd4_listxattrs *listxattrs,
> 4759 u32 *offsetp)
> 4760 {
> 4761 u64 cookie = listxattrs->lsxa_cookie;
> 4762
> 4763 /*
> 4764 * If the cookie is larger than the maximum number we can fit
> 4765 * in either the buffer we just got back from vfs_listxattr, or,
> 4766 * XDR-encoded, in the return buffer, it's invalid.
> 4767 */
> 4768 if (cookie > (listxattrs->lsxa_len) / (XATTR_USER_PREFIX_LEN + 2))
> 4769 return nfserr_badcookie;
> 4770
> 4771 if (cookie > (listxattrs->lsxa_maxcount /
> 4772 (XDR_QUADLEN(XATTR_USER_PREFIX_LEN + 2) + 4)))
> 4773 return nfserr_badcookie;
> 4774
> 4775 *offsetp = (u32)cookie;
> 4776 return 0;
> 4777 }
> 4778
> 4779 static __be32
> 4780 nfsd4_encode_listxattrs(struct nfsd4_compoundres *resp, __be32 nfserr,
> 4781 struct nfsd4_listxattrs *listxattrs)
> 4782 {
> 4783 struct xdr_stream *xdr = &resp->xdr;
> 4784 u32 cookie_offset, count_offset, eof;
> 4785 u32 left, xdrleft, slen, count;
> 4786 u32 xdrlen, offset;
> 4787 u64 cookie;
> 4788 char *sp;
> 4789 __be32 status;
> 4790 __be32 *p;
> 4791 u32 nuser;
> 4792
> 4793 eof = 1;
> 4794
> 4795 status = nfsd4_listxattr_validate_cookie(listxattrs, &offset);
> 4796 if (status)
> 4797 goto out;
> 4798
> 4799 /*
> 4800 * Reserve space for the cookie and the name array count. Record
> 4801 * the offsets to save them later.
> 4802 */
> 4803 cookie_offset = xdr->buf->len;
> 4804 count_offset = cookie_offset + 8;
> 4805 p = xdr_reserve_space(xdr, 12);
> 4806 if (!p) {
> 4807 status = nfserr_resource;
> 4808 goto out;
> 4809 }
> 4810
> 4811 count = 0;
> 4812 left = listxattrs->lsxa_len;
> 4813 sp = listxattrs->lsxa_buf;
> 4814 nuser = 0;
> 4815
> 4816 xdrleft = listxattrs->lsxa_maxcount;
> 4817
> 4818 while (left > 0 && xdrleft > 0) {
> 4819 slen = strlen(sp);
> 4820
> 4821 /*
> 4822 * Check if this a user. attribute, skip it if not.
> 4823 */
> 4824 if (strncmp(sp, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN))
> 4825 goto contloop;
> 4826
> 4827 slen -= XATTR_USER_PREFIX_LEN;
> 4828 xdrlen = 4 + ((slen + 3) & ~3);
> 4829 if (xdrlen > xdrleft) {
> 4830 if (count == 0) {
> 4831 /*
> 4832 * Can't even fit the first attribute name.
> 4833 */
> 4834 status = nfserr_toosmall;
> 4835 goto out;
> 4836 }
> 4837 eof = 0;
> 4838 goto wreof;
> 4839 }
> 4840
> 4841 left -= XATTR_USER_PREFIX_LEN;
> 4842 sp += XATTR_USER_PREFIX_LEN;
> 4843 if (nuser++ < offset)
> 4844 goto contloop;
> 4845
> 4846
> 4847 p = xdr_reserve_space(xdr, xdrlen);
> 4848 if (!p) {
> 4849 status = nfserr_resource;
> 4850 goto out;
> 4851 }
> 4852
> 4853 p = xdr_encode_opaque(p, sp, slen);
> 4854
> 4855 xdrleft -= xdrlen;
> 4856 count++;
> 4857 contloop:
> 4858 sp += slen + 1;
> 4859 left -= slen + 1;
> 4860 }
> 4861
> 4862 /*
> 4863 * If there were user attributes to copy, but we didn't copy
> 4864 * any, the offset was too large (e.g. the cookie was invalid).
> 4865 */
> 4866 if (nuser > 0 && count == 0) {
> 4867 status = nfserr_badcookie;
> 4868 goto out;
> 4869 }
> 4870
> 4871 wreof:
> 4872 p = xdr_reserve_space(xdr, 4);
> 4873 if (!p) {
> 4874 status = nfserr_resource;
> 4875 goto out;
> 4876 }
> 4877 *p = cpu_to_be32(eof);
> 4878
> 4879 cookie = offset + count;
> 4880
> 4881 write_bytes_to_xdr_buf(xdr->buf, cookie_offset, &cookie, 8);
>> 4882 count = htonl(count);
> 4883 write_bytes_to_xdr_buf(xdr->buf, count_offset, &count, 4);
> 4884 out:
> 4885 if (listxattrs->lsxa_len)
> 4886 kvfree(listxattrs->lsxa_buf);
> 4887 return status;
> 4888 }
> 4889
>
> ---
> 0-DAY CI Kernel Test Service, Intel Corporation
> https://lists.01.org/hyperkitty/list/kbuild-all@xxxxxxxxxxxx
> <.config.gz>
--
Chuck Lever