mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-04 20:19:47 +08:00
- Fill out the build string
- Prevent inode fork extent count overflows
- Refactor the allocator to reduce long tail latency
- Rework incore log locking a little to reduce spinning
- Break up the xfs_iomap_begin functions into smaller more cohesive
parts
- Fix allocation alignment being dropped too early when the allocation
request is for more blocks than an AG is large
- Other small cleanups
- Clean up file buftarg retrieval helpers
- Hoist the resvsp and unresvsp ioctls to the vfs
- Remove the undocumented biosize mount option, since it has never been
mentioned as existing or supported on linux
- Clean up some of the mount option printing and parsing
- Enhance attr leaf verifier to check block structure
- Check dirent and attr names for invalid characters before passing them
to the vfs
- Refactor open-coded bmbt walking
- Fix a few places where we return EIO instead of EFSCORRUPTED after
failing metadata sanity checks
- Fix a synchronization problem between fallocate and aio dio corrupting
the file length
- Clean up various loose ends in the iomap and bmap code
- Convert to the new mount api
- Make sure we always log something when returning EFSCORRUPTED
- Fix some problems where long running scrub loops could trigger soft
lockup warnings and/or fail to exit due to fatal signals pending
- Fix various Coverity complaints
- Remove most of the function pointers from the directory code to reduce
indirection penalties
- Ensure that dquots are attached to the inode when performing unwritten
extent conversion after io
- Deuglify incore projid and crtime types
- Fix another AGI/AGF locking order deadlock when renaming
- Clean up some quota typedefs
- Remove the FSSETDM ioctls which haven't done anything in 20 years
- Fix some memory leaks when mounting the log fails
- Fix an underflow when updating an xattr leaf freemap
- Remove some trivial wrappers
- Report metadata corruption as an error, not a (potentially) fatal
assertion
- Clean up the dir/attr buffer mapping code
- Allow fatal signals to kill scrub during parent pointer checks
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEUzaAxoMeQq6m2jMV+H93GTRKtOsFAl3fNjcACgkQ+H93GTRK
tOv/8w//Y0Oa9Paiy8+iPTChs3/PqeKp307Fj5KONG52haMCakEJFT5+/wpkIAJw
uUmKiPolwN1ivviIUmIS14ThTJ7NV1jq0G0h/0tC25i/3hoJrGWdzqYJMlvhlqgE
taHrjCwPTDkhRJ0D5QCrkkHPU7lSdquO5TWxltaqYLhyLIt8SkklD6dN1dHWEPnk
k0j3TL+VqVJDYyEj1bLwJ0QUb2C3J8ygWnlviF/WxsSeJtJpGoeLEaYXhhsUK0Dt
aHg70OM6zzFzrJJAtJeBXpgaFsG/Pqbcw4wUWSxEMWjVSJwCSKLuZ5F+p6NcqoEj
HeLQkaGePoO61YCInk2JKLHIyx7ohqMOt7+Dm0mdbe1pvcKwV9ZcdkqKa8L/Fm6v
bUP6a2hEpsGy7vLnkYxwYACTLPbGX3uLw8MUr6ZpJ+SpfVLktU4ycpr8dCkJkp6a
0qOpEeHsBDy74NkMOUa7Qrju7lJ2GiL70qqBwaPe+ubcUa3U/3WAsSekSzXgUwn8
Fap4r8wn7cUbxymAvO06RlU8YymuulAlyjwdo9gOL/Su/5POldss6dy1YuUtyq19
CD6NtkHqEUMsTc2cI+H65H44aEeckB1j0D2Grm2uMchAh0GcTSFVNF6jony++B8k
s2sL2dEw9/9vr0uc1TSVF5ezxaONuyaCXdYXUkkdyq3iNvfpRCg=
=aACq
-----END PGP SIGNATURE-----
Merge tag 'xfs-5.5-merge-16' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux
Pull XFS updates from Darrick Wong:
"For this release, we changed quite a few things.
Highlights:
- Fixed some long tail latency problems in the block allocator
- Removed some long deprecated (and for the past several years no-op)
mount options and ioctls
- Strengthened the extended attribute and directory verifiers
- Audited and fixed all the places where we could return EFSCORRUPTED
without logging anything
- Refactored the old SGI space allocation ioctls to make the
equivalent fallocate calls
- Fixed a race between fallocate and directio
- Fixed an integer overflow when files have more than a few
billion(!) extents
- Fixed a longstanding bug where quota accounting could be incorrect
when performing unwritten extent conversion on a freshly mounted fs
- Fixed various complaints in scrub about soft lockups and
unresponsiveness to signals
- De-vtable'd the directory handling code, which should make it
faster
- Converted to the new mount api, for better or for worse
- Cleaned up some memory leaks
and quite a lot of other smaller fixes and cleanups.
A more detailed summary:
- Fill out the build string
- Prevent inode fork extent count overflows
- Refactor the allocator to reduce long tail latency
- Rework incore log locking a little to reduce spinning
- Break up the xfs_iomap_begin functions into smaller more cohesive
parts
- Fix allocation alignment being dropped too early when the
allocation request is for more blocks than an AG is large
- Other small cleanups
- Clean up file buftarg retrieval helpers
- Hoist the resvsp and unresvsp ioctls to the vfs
- Remove the undocumented biosize mount option, since it has never
been mentioned as existing or supported on linux
- Clean up some of the mount option printing and parsing
- Enhance attr leaf verifier to check block structure
- Check dirent and attr names for invalid characters before passing
them to the vfs
- Refactor open-coded bmbt walking
- Fix a few places where we return EIO instead of EFSCORRUPTED after
failing metadata sanity checks
- Fix a synchronization problem between fallocate and aio dio
corrupting the file length
- Clean up various loose ends in the iomap and bmap code
- Convert to the new mount api
- Make sure we always log something when returning EFSCORRUPTED
- Fix some problems where long running scrub loops could trigger soft
lockup warnings and/or fail to exit due to fatal signals pending
- Fix various Coverity complaints
- Remove most of the function pointers from the directory code to
reduce indirection penalties
- Ensure that dquots are attached to the inode when performing
unwritten extent conversion after io
- Deuglify incore projid and crtime types
- Fix another AGI/AGF locking order deadlock when renaming
- Clean up some quota typedefs
- Remove the FSSETDM ioctls which haven't done anything in 20 years
- Fix some memory leaks when mounting the log fails
- Fix an underflow when updating an xattr leaf freemap
- Remove some trivial wrappers
- Report metadata corruption as an error, not a (potentially) fatal
assertion
- Clean up the dir/attr buffer mapping code
- Allow fatal signals to kill scrub during parent pointer checks"
* tag 'xfs-5.5-merge-16' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux: (198 commits)
xfs: allow parent directory scans to be interrupted with fatal signals
xfs: remove the mappedbno argument to xfs_da_get_buf
xfs: remove the mappedbno argument to xfs_da_read_buf
xfs: split xfs_da3_node_read
xfs: remove the mappedbno argument to xfs_dir3_leafn_read
xfs: remove the mappedbno argument to xfs_dir3_leaf_read
xfs: remove the mappedbno argument to xfs_attr3_leaf_read
xfs: remove the mappedbno argument to xfs_da_reada_buf
xfs: improve the xfs_dabuf_map calling conventions
xfs: refactor xfs_dabuf_map
xfs: simplify mappedbno handling in xfs_da_{get,read}_buf
xfs: report corruption only as a regular error
xfs: Remove kmem_zone_free() wrapper
xfs: Remove kmem_zone_destroy() wrapper
xfs: Remove slab init wrappers
xfs: fix attr leaf header freemap.size underflow
xfs: fix some memory leaks in log recovery
xfs: fix another missing include
xfs: remove XFS_IOC_FSSETDM and XFS_IOC_FSSETDM_BY_HANDLE
xfs: remove duplicated include from xfs_dir2_data.c
...
262 lines
6.4 KiB
C
262 lines
6.4 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
||
/*
|
||
* ioctl32.c: Conversion between 32bit and 64bit native ioctls.
|
||
*
|
||
* Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com)
|
||
* Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
|
||
* Copyright (C) 2001,2002 Andi Kleen, SuSE Labs
|
||
* Copyright (C) 2003 Pavel Machek (pavel@ucw.cz)
|
||
*
|
||
* These routines maintain argument size conversion between 32bit and 64bit
|
||
* ioctls.
|
||
*/
|
||
|
||
#include <linux/types.h>
|
||
#include <linux/compat.h>
|
||
#include <linux/kernel.h>
|
||
#include <linux/capability.h>
|
||
#include <linux/compiler.h>
|
||
#include <linux/sched.h>
|
||
#include <linux/smp.h>
|
||
#include <linux/ioctl.h>
|
||
#include <linux/if.h>
|
||
#include <linux/raid/md_u.h>
|
||
#include <linux/falloc.h>
|
||
#include <linux/file.h>
|
||
#include <linux/ppp-ioctl.h>
|
||
#include <linux/if_pppox.h>
|
||
#include <linux/tty.h>
|
||
#include <linux/vt_kern.h>
|
||
#include <linux/blkdev.h>
|
||
#include <linux/serial.h>
|
||
#include <linux/ctype.h>
|
||
#include <linux/syscalls.h>
|
||
#include <linux/gfp.h>
|
||
#include <linux/cec.h>
|
||
|
||
#include "internal.h"
|
||
|
||
#ifdef CONFIG_BLOCK
|
||
#include <linux/cdrom.h>
|
||
#include <linux/fd.h>
|
||
#include <scsi/scsi.h>
|
||
#include <scsi/scsi_ioctl.h>
|
||
#include <scsi/sg.h>
|
||
#endif
|
||
|
||
#include <linux/uaccess.h>
|
||
#include <linux/watchdog.h>
|
||
|
||
#include <linux/hiddev.h>
|
||
|
||
|
||
#include <linux/sort.h>
|
||
|
||
/*
|
||
* simple reversible transform to make our table more evenly
|
||
* distributed after sorting.
|
||
*/
|
||
#define XFORM(i) (((i) ^ ((i) << 27) ^ ((i) << 17)) & 0xffffffff)
|
||
|
||
#define COMPATIBLE_IOCTL(cmd) XFORM((u32)cmd),
|
||
static unsigned int ioctl_pointer[] = {
|
||
#ifdef CONFIG_BLOCK
|
||
/* Big S */
|
||
COMPATIBLE_IOCTL(SCSI_IOCTL_GET_IDLUN)
|
||
COMPATIBLE_IOCTL(SCSI_IOCTL_DOORLOCK)
|
||
COMPATIBLE_IOCTL(SCSI_IOCTL_DOORUNLOCK)
|
||
COMPATIBLE_IOCTL(SCSI_IOCTL_TEST_UNIT_READY)
|
||
COMPATIBLE_IOCTL(SCSI_IOCTL_GET_BUS_NUMBER)
|
||
COMPATIBLE_IOCTL(SCSI_IOCTL_SEND_COMMAND)
|
||
COMPATIBLE_IOCTL(SCSI_IOCTL_PROBE_HOST)
|
||
COMPATIBLE_IOCTL(SCSI_IOCTL_GET_PCI)
|
||
#endif
|
||
#ifdef CONFIG_BLOCK
|
||
/* SG stuff */
|
||
COMPATIBLE_IOCTL(SG_IO)
|
||
COMPATIBLE_IOCTL(SG_GET_REQUEST_TABLE)
|
||
COMPATIBLE_IOCTL(SG_SET_TIMEOUT)
|
||
COMPATIBLE_IOCTL(SG_GET_TIMEOUT)
|
||
COMPATIBLE_IOCTL(SG_EMULATED_HOST)
|
||
COMPATIBLE_IOCTL(SG_GET_TRANSFORM)
|
||
COMPATIBLE_IOCTL(SG_SET_RESERVED_SIZE)
|
||
COMPATIBLE_IOCTL(SG_GET_RESERVED_SIZE)
|
||
COMPATIBLE_IOCTL(SG_GET_SCSI_ID)
|
||
COMPATIBLE_IOCTL(SG_SET_FORCE_LOW_DMA)
|
||
COMPATIBLE_IOCTL(SG_GET_LOW_DMA)
|
||
COMPATIBLE_IOCTL(SG_SET_FORCE_PACK_ID)
|
||
COMPATIBLE_IOCTL(SG_GET_PACK_ID)
|
||
COMPATIBLE_IOCTL(SG_GET_NUM_WAITING)
|
||
COMPATIBLE_IOCTL(SG_SET_DEBUG)
|
||
COMPATIBLE_IOCTL(SG_GET_SG_TABLESIZE)
|
||
COMPATIBLE_IOCTL(SG_GET_COMMAND_Q)
|
||
COMPATIBLE_IOCTL(SG_SET_COMMAND_Q)
|
||
COMPATIBLE_IOCTL(SG_GET_VERSION_NUM)
|
||
COMPATIBLE_IOCTL(SG_NEXT_CMD_LEN)
|
||
COMPATIBLE_IOCTL(SG_SCSI_RESET)
|
||
COMPATIBLE_IOCTL(SG_GET_REQUEST_TABLE)
|
||
COMPATIBLE_IOCTL(SG_SET_KEEP_ORPHAN)
|
||
COMPATIBLE_IOCTL(SG_GET_KEEP_ORPHAN)
|
||
#endif
|
||
};
|
||
|
||
/*
|
||
* Convert common ioctl arguments based on their command number
|
||
*
|
||
* Please do not add any code in here. Instead, implement
|
||
* a compat_ioctl operation in the place that handleѕ the
|
||
* ioctl for the native case.
|
||
*/
|
||
static long do_ioctl_trans(unsigned int cmd,
|
||
unsigned long arg, struct file *file)
|
||
{
|
||
return -ENOIOCTLCMD;
|
||
}
|
||
|
||
static int compat_ioctl_check_table(unsigned int xcmd)
|
||
{
|
||
#ifdef CONFIG_BLOCK
|
||
int i;
|
||
const int max = ARRAY_SIZE(ioctl_pointer) - 1;
|
||
|
||
BUILD_BUG_ON(max >= (1 << 16));
|
||
|
||
/* guess initial offset into table, assuming a
|
||
normalized distribution */
|
||
i = ((xcmd >> 16) * max) >> 16;
|
||
|
||
/* do linear search up first, until greater or equal */
|
||
while (ioctl_pointer[i] < xcmd && i < max)
|
||
i++;
|
||
|
||
/* then do linear search down */
|
||
while (ioctl_pointer[i] > xcmd && i > 0)
|
||
i--;
|
||
|
||
return ioctl_pointer[i] == xcmd;
|
||
#else
|
||
return 0;
|
||
#endif
|
||
}
|
||
|
||
COMPAT_SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd,
|
||
compat_ulong_t, arg32)
|
||
{
|
||
unsigned long arg = arg32;
|
||
struct fd f = fdget(fd);
|
||
int error = -EBADF;
|
||
if (!f.file)
|
||
goto out;
|
||
|
||
/* RED-PEN how should LSM module know it's handling 32bit? */
|
||
error = security_file_ioctl(f.file, cmd, arg);
|
||
if (error)
|
||
goto out_fput;
|
||
|
||
switch (cmd) {
|
||
/* these are never seen by ->ioctl(), no argument or int argument */
|
||
case FIOCLEX:
|
||
case FIONCLEX:
|
||
case FIFREEZE:
|
||
case FITHAW:
|
||
case FICLONE:
|
||
goto do_ioctl;
|
||
/* these are never seen by ->ioctl(), pointer argument */
|
||
case FIONBIO:
|
||
case FIOASYNC:
|
||
case FIOQSIZE:
|
||
case FS_IOC_FIEMAP:
|
||
case FIGETBSZ:
|
||
case FICLONERANGE:
|
||
case FIDEDUPERANGE:
|
||
goto found_handler;
|
||
/*
|
||
* The next group is the stuff handled inside file_ioctl().
|
||
* For regular files these never reach ->ioctl(); for
|
||
* devices, sockets, etc. they do and one (FIONREAD) is
|
||
* even accepted in some cases. In all those cases
|
||
* argument has the same type, so we can handle these
|
||
* here, shunting them towards do_vfs_ioctl().
|
||
* ->compat_ioctl() will never see any of those.
|
||
*/
|
||
/* pointer argument, never actually handled by ->ioctl() */
|
||
case FIBMAP:
|
||
goto found_handler;
|
||
/* handled by some ->ioctl(); always a pointer to int */
|
||
case FIONREAD:
|
||
goto found_handler;
|
||
/* these get messy on amd64 due to alignment differences */
|
||
#if defined(CONFIG_X86_64)
|
||
case FS_IOC_RESVSP_32:
|
||
case FS_IOC_RESVSP64_32:
|
||
error = compat_ioctl_preallocate(f.file, 0, compat_ptr(arg));
|
||
goto out_fput;
|
||
case FS_IOC_UNRESVSP_32:
|
||
case FS_IOC_UNRESVSP64_32:
|
||
error = compat_ioctl_preallocate(f.file, FALLOC_FL_PUNCH_HOLE,
|
||
compat_ptr(arg));
|
||
goto out_fput;
|
||
case FS_IOC_ZERO_RANGE_32:
|
||
error = compat_ioctl_preallocate(f.file, FALLOC_FL_ZERO_RANGE,
|
||
compat_ptr(arg));
|
||
goto out_fput;
|
||
#else
|
||
case FS_IOC_RESVSP:
|
||
case FS_IOC_RESVSP64:
|
||
case FS_IOC_UNRESVSP:
|
||
case FS_IOC_UNRESVSP64:
|
||
case FS_IOC_ZERO_RANGE:
|
||
goto found_handler;
|
||
#endif
|
||
|
||
default:
|
||
if (f.file->f_op->compat_ioctl) {
|
||
error = f.file->f_op->compat_ioctl(f.file, cmd, arg);
|
||
if (error != -ENOIOCTLCMD)
|
||
goto out_fput;
|
||
}
|
||
|
||
if (!f.file->f_op->unlocked_ioctl)
|
||
goto do_ioctl;
|
||
break;
|
||
}
|
||
|
||
if (compat_ioctl_check_table(XFORM(cmd)))
|
||
goto found_handler;
|
||
|
||
error = do_ioctl_trans(cmd, arg, f.file);
|
||
if (error == -ENOIOCTLCMD)
|
||
error = -ENOTTY;
|
||
|
||
goto out_fput;
|
||
|
||
found_handler:
|
||
arg = (unsigned long)compat_ptr(arg);
|
||
do_ioctl:
|
||
error = do_vfs_ioctl(f.file, fd, cmd, arg);
|
||
out_fput:
|
||
fdput(f);
|
||
out:
|
||
return error;
|
||
}
|
||
|
||
static int __init init_sys32_ioctl_cmp(const void *p, const void *q)
|
||
{
|
||
unsigned int a, b;
|
||
a = *(unsigned int *)p;
|
||
b = *(unsigned int *)q;
|
||
if (a > b)
|
||
return 1;
|
||
if (a < b)
|
||
return -1;
|
||
return 0;
|
||
}
|
||
|
||
static int __init init_sys32_ioctl(void)
|
||
{
|
||
sort(ioctl_pointer, ARRAY_SIZE(ioctl_pointer), sizeof(*ioctl_pointer),
|
||
init_sys32_ioctl_cmp, NULL);
|
||
return 0;
|
||
}
|
||
__initcall(init_sys32_ioctl);
|