xfs: kill the XFS_IOC_{ALLOC,FREE}SP* ioctls

According to the glibc compat header for Irix 4, these ioctls originated
in April 1991 as a (somewhat clunky) way to preallocate space at the end
of a file on an EFS filesystem. XFS, which was released in Irix 5.3 in
December 1993, picked up these ioctls to maintain compatibility and they
were ported to Linux in the early 2000s.

Recently it was pointed out to me they still lurk in the kernel, even
though the Linux fallocate syscall supplanted the functionality a long
time ago. fstests doesn't seem to include any real functional or stress
tests for these ioctls, which means that the code quality is ... very
questionable. Most notably, it was a stale disk block exposure vector
for 21 years and nobody noticed or complained. As mature programmers
say, "If you're not testing it, it's broken."

Given all that, let's withdraw these ioctls from the XFS userspace API.
Normally we'd set a long deprecation process, but I estimate that there
aren't any real users, so let's trigger a warning in dmesg and return
-ENOTTY.

See: CVE-2021-4155

Augments: 983d8e60f508 ("xfs: map unwritten blocks in XFS_IOC_{ALLOC,FREE}SP just like fallocate")
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>

+10 -127
+3 -4
fs/xfs/xfs_bmap_util.c
··· 771 xfs_alloc_file_space( 772 struct xfs_inode *ip, 773 xfs_off_t offset, 774 - xfs_off_t len, 775 - int alloc_type) 776 { 777 xfs_mount_t *mp = ip->i_mount; 778 xfs_off_t count; ··· 864 goto error; 865 866 error = xfs_bmapi_write(tp, ip, startoffset_fsb, 867 - allocatesize_fsb, alloc_type, 0, imapp, 868 - &nimaps); 869 if (error) 870 goto error; 871
··· 771 xfs_alloc_file_space( 772 struct xfs_inode *ip, 773 xfs_off_t offset, 774 + xfs_off_t len) 775 { 776 xfs_mount_t *mp = ip->i_mount; 777 xfs_off_t count; ··· 865 goto error; 866 867 error = xfs_bmapi_write(tp, ip, startoffset_fsb, 868 + allocatesize_fsb, XFS_BMAPI_PREALLOC, 0, imapp, 869 + &nimaps); 870 if (error) 871 goto error; 872
+1 -1
fs/xfs/xfs_bmap_util.h
··· 54 55 /* preallocation and hole punch interface */ 56 int xfs_alloc_file_space(struct xfs_inode *ip, xfs_off_t offset, 57 - xfs_off_t len, int alloc_type); 58 int xfs_free_file_space(struct xfs_inode *ip, xfs_off_t offset, 59 xfs_off_t len); 60 int xfs_collapse_file_space(struct xfs_inode *, xfs_off_t offset,
··· 54 55 /* preallocation and hole punch interface */ 56 int xfs_alloc_file_space(struct xfs_inode *ip, xfs_off_t offset, 57 + xfs_off_t len); 58 int xfs_free_file_space(struct xfs_inode *ip, xfs_off_t offset, 59 xfs_off_t len); 60 int xfs_collapse_file_space(struct xfs_inode *, xfs_off_t offset,
+1 -2
fs/xfs/xfs_file.c
··· 1052 } 1053 1054 if (!xfs_is_always_cow_inode(ip)) { 1055 - error = xfs_alloc_file_space(ip, offset, len, 1056 - XFS_BMAPI_PREALLOC); 1057 if (error) 1058 goto out_unlock; 1059 }
··· 1052 } 1053 1054 if (!xfs_is_always_cow_inode(ip)) { 1055 + error = xfs_alloc_file_space(ip, offset, len); 1056 if (error) 1057 goto out_unlock; 1058 }
+5 -87
fs/xfs/xfs_ioctl.c
··· 627 return error; 628 } 629 630 - int 631 - xfs_ioc_space( 632 - struct file *filp, 633 - xfs_flock64_t *bf) 634 - { 635 - struct inode *inode = file_inode(filp); 636 - struct xfs_inode *ip = XFS_I(inode); 637 - struct iattr iattr; 638 - enum xfs_prealloc_flags flags = XFS_PREALLOC_CLEAR; 639 - uint iolock = XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL; 640 - int error; 641 - 642 - if (inode->i_flags & (S_IMMUTABLE|S_APPEND)) 643 - return -EPERM; 644 - 645 - if (!(filp->f_mode & FMODE_WRITE)) 646 - return -EBADF; 647 - 648 - if (!S_ISREG(inode->i_mode)) 649 - return -EINVAL; 650 - 651 - if (xfs_is_always_cow_inode(ip)) 652 - return -EOPNOTSUPP; 653 - 654 - if (filp->f_flags & O_DSYNC) 655 - flags |= XFS_PREALLOC_SYNC; 656 - if (filp->f_mode & FMODE_NOCMTIME) 657 - flags |= XFS_PREALLOC_INVISIBLE; 658 - 659 - error = mnt_want_write_file(filp); 660 - if (error) 661 - return error; 662 - 663 - xfs_ilock(ip, iolock); 664 - error = xfs_break_layouts(inode, &iolock, BREAK_UNMAP); 665 - if (error) 666 - goto out_unlock; 667 - inode_dio_wait(inode); 668 - 669 - switch (bf->l_whence) { 670 - case 0: /*SEEK_SET*/ 671 - break; 672 - case 1: /*SEEK_CUR*/ 673 - bf->l_start += filp->f_pos; 674 - break; 675 - case 2: /*SEEK_END*/ 676 - bf->l_start += XFS_ISIZE(ip); 677 - break; 678 - default: 679 - error = -EINVAL; 680 - goto out_unlock; 681 - } 682 - 683 - if (bf->l_start < 0 || bf->l_start > inode->i_sb->s_maxbytes) { 684 - error = -EINVAL; 685 - goto out_unlock; 686 - } 687 - 688 - if (bf->l_start > XFS_ISIZE(ip)) { 689 - error = xfs_alloc_file_space(ip, XFS_ISIZE(ip), 690 - bf->l_start - XFS_ISIZE(ip), 0); 691 - if (error) 692 - goto out_unlock; 693 - } 694 - 695 - iattr.ia_valid = ATTR_SIZE; 696 - iattr.ia_size = bf->l_start; 697 - error = xfs_vn_setattr_size(file_mnt_user_ns(filp), file_dentry(filp), 698 - &iattr); 699 - if (error) 700 - goto out_unlock; 701 - 702 - error = xfs_update_prealloc_flags(ip, flags); 703 - 704 - out_unlock: 705 - xfs_iunlock(ip, iolock); 706 - mnt_drop_write_file(filp); 707 - return error; 708 - } 709 - 710 /* Return 0 on success or positive error */ 711 int 712 xfs_fsbulkstat_one_fmt( ··· 1884 case XFS_IOC_ALLOCSP: 1885 case XFS_IOC_FREESP: 1886 case XFS_IOC_ALLOCSP64: 1887 - case XFS_IOC_FREESP64: { 1888 - xfs_flock64_t bf; 1889 - 1890 - if (copy_from_user(&bf, arg, sizeof(bf))) 1891 - return -EFAULT; 1892 - return xfs_ioc_space(filp, &bf); 1893 - } 1894 case XFS_IOC_DIOINFO: { 1895 struct xfs_buftarg *target = xfs_inode_buftarg(ip); 1896 struct dioattr da;
··· 627 return error; 628 } 629 630 /* Return 0 on success or positive error */ 631 int 632 xfs_fsbulkstat_one_fmt( ··· 1964 case XFS_IOC_ALLOCSP: 1965 case XFS_IOC_FREESP: 1966 case XFS_IOC_ALLOCSP64: 1967 + case XFS_IOC_FREESP64: 1968 + xfs_warn_once(mp, 1969 + "%s should use fallocate; XFS_IOC_{ALLOC,FREE}SP ioctl unsupported", 1970 + current->comm); 1971 + return -ENOTTY; 1972 case XFS_IOC_DIOINFO: { 1973 struct xfs_buftarg *target = xfs_inode_buftarg(ip); 1974 struct dioattr da;
-6
fs/xfs/xfs_ioctl.h
··· 10 struct xfs_ibulk; 11 struct xfs_inogrp; 12 13 - 14 - extern int 15 - xfs_ioc_space( 16 - struct file *filp, 17 - xfs_flock64_t *bf); 18 - 19 int 20 xfs_ioc_swapext( 21 xfs_swapext_t *sxp);
··· 10 struct xfs_ibulk; 11 struct xfs_inogrp; 12 13 int 14 xfs_ioc_swapext( 15 xfs_swapext_t *sxp);
-27
fs/xfs/xfs_ioctl32.c
··· 28 29 #ifdef BROKEN_X86_ALIGNMENT 30 STATIC int 31 - xfs_compat_flock64_copyin( 32 - xfs_flock64_t *bf, 33 - compat_xfs_flock64_t __user *arg32) 34 - { 35 - if (get_user(bf->l_type, &arg32->l_type) || 36 - get_user(bf->l_whence, &arg32->l_whence) || 37 - get_user(bf->l_start, &arg32->l_start) || 38 - get_user(bf->l_len, &arg32->l_len) || 39 - get_user(bf->l_sysid, &arg32->l_sysid) || 40 - get_user(bf->l_pid, &arg32->l_pid) || 41 - copy_from_user(bf->l_pad, &arg32->l_pad, 4*sizeof(u32))) 42 - return -EFAULT; 43 - return 0; 44 - } 45 - 46 - STATIC int 47 xfs_compat_ioc_fsgeometry_v1( 48 struct xfs_mount *mp, 49 compat_xfs_fsop_geom_v1_t __user *arg32) ··· 429 430 switch (cmd) { 431 #if defined(BROKEN_X86_ALIGNMENT) 432 - case XFS_IOC_ALLOCSP_32: 433 - case XFS_IOC_FREESP_32: 434 - case XFS_IOC_ALLOCSP64_32: 435 - case XFS_IOC_FREESP64_32: { 436 - struct xfs_flock64 bf; 437 - 438 - if (xfs_compat_flock64_copyin(&bf, arg)) 439 - return -EFAULT; 440 - cmd = _NATIVE_IOC(cmd, struct xfs_flock64); 441 - return xfs_ioc_space(filp, &bf); 442 - } 443 case XFS_IOC_FSGEOMETRY_V1_32: 444 return xfs_compat_ioc_fsgeometry_v1(ip->i_mount, arg); 445 case XFS_IOC_FSGROWFSDATA_32: {
··· 28 29 #ifdef BROKEN_X86_ALIGNMENT 30 STATIC int 31 xfs_compat_ioc_fsgeometry_v1( 32 struct xfs_mount *mp, 33 compat_xfs_fsop_geom_v1_t __user *arg32) ··· 445 446 switch (cmd) { 447 #if defined(BROKEN_X86_ALIGNMENT) 448 case XFS_IOC_FSGEOMETRY_V1_32: 449 return xfs_compat_ioc_fsgeometry_v1(ip->i_mount, arg); 450 case XFS_IOC_FSGROWFSDATA_32: {