[djwong-xfs:vectorized-scrub 154/352] fs/remap_range.c:629 generic_xchg_file_range_checks() warn: unsigned 'fxr->length' is never less than zero.

From: kernel test robot
Date: Sat Jul 03 2021 - 09:05:39 EST


tree: https://git.kernel.org/pub/scm/linux/kernel/git/djwong/xfs-linux.git vectorized-scrub
head: 9716b2732a485c80e6988c5bdf42bd53d337773f
commit: 6420f9fb66b09f0f0dfa8c1bd45d010ce76adedc [154/352] vfs: introduce new file range exchange ioctl
config: h8300-randconfig-m031-20210702 (attached as .config)
compiler: h8300-linux-gcc (GCC) 9.3.0

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

smatch warnings:
fs/remap_range.c:629 generic_xchg_file_range_checks() warn: unsigned 'fxr->length' is never less than zero.

vim +629 fs/remap_range.c

583
584 /* Performs necessary checks before doing a range exchange. */
585 static int generic_xchg_file_range_checks(struct file *file1,
586 struct file *file2,
587 struct file_xchg_range *fxr,
588 unsigned int blocksize)
589 {
590 struct inode *inode1 = file1->f_mapping->host;
591 struct inode *inode2 = file2->f_mapping->host;
592 uint64_t blkmask = blocksize - 1;
593 int64_t test_len;
594 uint64_t blen;
595 loff_t size1, size2;
596 int ret;
597
598 /* Don't touch certain kinds of inodes */
599 if (IS_IMMUTABLE(inode1) || IS_IMMUTABLE(inode2))
600 return -EPERM;
601 if (IS_SWAPFILE(inode1) || IS_SWAPFILE(inode2))
602 return -ETXTBSY;
603
604 size1 = i_size_read(inode1);
605 size2 = i_size_read(inode2);
606
607 /* Ranges cannot start after EOF. */
608 if (fxr->file1_offset > size1 || fxr->file2_offset > size2)
609 return -EINVAL;
610
611 /*
612 * If the caller asked for full files, check that the offset/length
613 * values cover all of both files.
614 */
615 if ((fxr->flags & FILE_XCHG_RANGE_FULL_FILES) &&
616 (fxr->file1_offset != 0 || fxr->file2_offset != 0 ||
617 fxr->length != size1 || fxr->length != size2))
618 return -EDOM;
619
620 /*
621 * If the caller said to exchange to EOF, we set the length of the
622 * request large enough to cover everything to the end of both files.
623 */
624 if (fxr->flags & FILE_XCHG_RANGE_TO_EOF)
625 fxr->length = max_t(int64_t, size1 - fxr->file1_offset,
626 size2 - fxr->file2_offset);
627
628 /* No negative lengths */
> 629 if (fxr->length < 0)
630 return -EINVAL;
631
632 /* The start of both ranges must be aligned to an fs block. */
633 if (!IS_ALIGNED(fxr->file1_offset, blocksize) ||
634 !IS_ALIGNED(fxr->file2_offset, blocksize))
635 return -EINVAL;
636
637 /* Ensure offsets don't wrap. */
638 if (fxr->file1_offset + fxr->length < fxr->file1_offset ||
639 fxr->file2_offset + fxr->length < fxr->file2_offset)
640 return -EINVAL;
641
642 /*
643 * We require both ranges to be within EOF, unless we're exchanging
644 * to EOF. generic_xchg_range_prep already checked that both
645 * fxr->file1_offset and fxr->file2_offset are within EOF.
646 */
647 if (!(fxr->flags & FILE_XCHG_RANGE_TO_EOF) &&
648 (fxr->file1_offset + fxr->length > size1 ||
649 fxr->file2_offset + fxr->length > size2))
650 return -EINVAL;
651
652 /*
653 * Make sure we don't hit any file size limits. If we hit any size
654 * limits such that test_length was adjusted, we abort the whole
655 * operation.
656 */
657 test_len = fxr->length;
658 ret = generic_write_check_limits(file2, fxr->file2_offset, &test_len);
659 if (ret)
660 return ret;
661 ret = generic_write_check_limits(file1, fxr->file1_offset, &test_len);
662 if (ret)
663 return ret;
664 if (test_len != fxr->length)
665 return -EINVAL;
666
667 /*
668 * If the user wanted us to exchange up to the infile's EOF, round up
669 * to the next block boundary for this check. Do the same for the
670 * outfile.
671 *
672 * Otherwise, reject the range length if it's not block aligned. We
673 * already confirmed the starting offsets' block alignment.
674 */
675 if (fxr->file1_offset + fxr->length == size1)
676 blen = ALIGN(size1, blocksize) - fxr->file1_offset;
677 else if (fxr->file2_offset + fxr->length == size2)
678 blen = ALIGN(size2, blocksize) - fxr->file2_offset;
679 else if (!IS_ALIGNED(fxr->length, blocksize))
680 return -EINVAL;
681 else
682 blen = fxr->length;
683
684 /* Don't allow overlapped exchanges within the same file. */
685 if (inode1 == inode2 &&
686 fxr->file2_offset + blen > fxr->file1_offset &&
687 fxr->file1_offset + blen > fxr->file2_offset)
688 return -EINVAL;
689
690 /* If we already failed the freshness check, we're done. */
691 ret = generic_xchg_file_range_check_fresh(inode2, fxr);
692 if (ret)
693 return ret;
694
695 /*
696 * Ensure that we don't exchange a partial EOF block into the middle of
697 * another file.
698 */
699 if ((fxr->length & blkmask) == 0)
700 return 0;
701
702 blen = fxr->length;
703 if (fxr->file2_offset + blen < size2)
704 blen &= ~blkmask;
705
706 if (fxr->file1_offset + blen < size1)
707 blen &= ~blkmask;
708
709 return blen == fxr->length ? 0 : -EINVAL;
710 }
711

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

Attachment: .config.gz
Description: application/gzip