Skip to content

Commit 4d1b97f

Browse files
author
Darrick J. Wong
committed
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: 983d8e6 ("xfs: map unwritten blocks in XFS_IOC_{ALLOC,FREE}SP just like fallocate") Signed-off-by: Darrick J. Wong <[email protected]> Reviewed-by: Eric Sandeen <[email protected]> Reviewed-by: Dave Chinner <[email protected]>
1 parent 9dec036 commit 4d1b97f

File tree

6 files changed

+10
-127
lines changed

6 files changed

+10
-127
lines changed

fs/xfs/xfs_bmap_util.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -771,8 +771,7 @@ int
771771
xfs_alloc_file_space(
772772
struct xfs_inode *ip,
773773
xfs_off_t offset,
774-
xfs_off_t len,
775-
int alloc_type)
774+
xfs_off_t len)
776775
{
777776
xfs_mount_t *mp = ip->i_mount;
778777
xfs_off_t count;
@@ -865,8 +864,8 @@ xfs_alloc_file_space(
865864
goto error;
866865

867866
error = xfs_bmapi_write(tp, ip, startoffset_fsb,
868-
allocatesize_fsb, alloc_type, 0, imapp,
869-
&nimaps);
867+
allocatesize_fsb, XFS_BMAPI_PREALLOC, 0, imapp,
868+
&nimaps);
870869
if (error)
871870
goto error;
872871

fs/xfs/xfs_bmap_util.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ int xfs_bmap_last_extent(struct xfs_trans *tp, struct xfs_inode *ip,
5454

5555
/* preallocation and hole punch interface */
5656
int xfs_alloc_file_space(struct xfs_inode *ip, xfs_off_t offset,
57-
xfs_off_t len, int alloc_type);
57+
xfs_off_t len);
5858
int xfs_free_file_space(struct xfs_inode *ip, xfs_off_t offset,
5959
xfs_off_t len);
6060
int xfs_collapse_file_space(struct xfs_inode *, xfs_off_t offset,

fs/xfs/xfs_file.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1052,8 +1052,7 @@ xfs_file_fallocate(
10521052
}
10531053

10541054
if (!xfs_is_always_cow_inode(ip)) {
1055-
error = xfs_alloc_file_space(ip, offset, len,
1056-
XFS_BMAPI_PREALLOC);
1055+
error = xfs_alloc_file_space(ip, offset, len);
10571056
if (error)
10581057
goto out_unlock;
10591058
}

fs/xfs/xfs_ioctl.c

Lines changed: 5 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -627,86 +627,6 @@ xfs_attrmulti_by_handle(
627627
return error;
628628
}
629629

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-
710630
/* Return 0 on success or positive error */
711631
int
712632
xfs_fsbulkstat_one_fmt(
@@ -1964,13 +1884,11 @@ xfs_file_ioctl(
19641884
case XFS_IOC_ALLOCSP:
19651885
case XFS_IOC_FREESP:
19661886
case XFS_IOC_ALLOCSP64:
1967-
case XFS_IOC_FREESP64: {
1968-
xfs_flock64_t bf;
1969-
1970-
if (copy_from_user(&bf, arg, sizeof(bf)))
1971-
return -EFAULT;
1972-
return xfs_ioc_space(filp, &bf);
1973-
}
1887+
case XFS_IOC_FREESP64:
1888+
xfs_warn_once(mp,
1889+
"%s should use fallocate; XFS_IOC_{ALLOC,FREE}SP ioctl unsupported",
1890+
current->comm);
1891+
return -ENOTTY;
19741892
case XFS_IOC_DIOINFO: {
19751893
struct xfs_buftarg *target = xfs_inode_buftarg(ip);
19761894
struct dioattr da;

fs/xfs/xfs_ioctl.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,6 @@ struct xfs_bstat;
1010
struct xfs_ibulk;
1111
struct xfs_inogrp;
1212

13-
14-
extern int
15-
xfs_ioc_space(
16-
struct file *filp,
17-
xfs_flock64_t *bf);
18-
1913
int
2014
xfs_ioc_swapext(
2115
xfs_swapext_t *sxp);

fs/xfs/xfs_ioctl32.c

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -27,22 +27,6 @@
2727
_IOC(_IOC_DIR(cmd), _IOC_TYPE(cmd), _IOC_NR(cmd), sizeof(type))
2828

2929
#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-
4630
STATIC int
4731
xfs_compat_ioc_fsgeometry_v1(
4832
struct xfs_mount *mp,
@@ -445,17 +429,6 @@ xfs_file_compat_ioctl(
445429

446430
switch (cmd) {
447431
#if defined(BROKEN_X86_ALIGNMENT)
448-
case XFS_IOC_ALLOCSP_32:
449-
case XFS_IOC_FREESP_32:
450-
case XFS_IOC_ALLOCSP64_32:
451-
case XFS_IOC_FREESP64_32: {
452-
struct xfs_flock64 bf;
453-
454-
if (xfs_compat_flock64_copyin(&bf, arg))
455-
return -EFAULT;
456-
cmd = _NATIVE_IOC(cmd, struct xfs_flock64);
457-
return xfs_ioc_space(filp, &bf);
458-
}
459432
case XFS_IOC_FSGEOMETRY_V1_32:
460433
return xfs_compat_ioc_fsgeometry_v1(ip->i_mount, arg);
461434
case XFS_IOC_FSGROWFSDATA_32: {

0 commit comments

Comments
 (0)