[PATCH v2 00/16] compat: Introduce and use in_compat_syscall

Andy Lutomirski
2016-01-25T22:24:14Z

Linux distinguishes compat syscalls from normal syscalls in two ways.
First, compat syscalls use separate entry points. This is entirely
sensible. Second, code paths that are common to compat and non-compat
syscalls can query is_compat_task() to check whether they are being
called from a compat syscall or not.

The latter is problematic. Two architectures explicitly allow tasks
to issue syscalls for which the task bitness and the syscall bitness
don't match. On x86, is_compat_task returns true if the current
syscall is a compat syscall, which is a different condition from being
a compat task. This oddity is confusing. On SPARC, is_compat_task
does what it sounds like, which means that user programs can cause
is_compat_task to fail to match the syscall entry used. That could
expose bugs.

This series introduces in_compat_syscall() as a new way to query the
syscall type. On SPARC, it really does check the syscall bitness.
Later patches change all of the non arch-specific is_compat_task
callers to use in_compat_syscall. The last patch removes
is_compat_task on x86, which will prevent this confusion from
recurring.

I've cc'd the maintainers of all archs that support compat. If your
arch makes it possible for a malicious user process to invoke a compat
syscall in a nominally 64-bit task or vice versa and your arch is not
x86 or SPARC, please tell me.

Davem, can you check whether I handled SPARC correctly?

Andy Lutomirski (16):
compat: Add in_compat_syscall to ask whether we're in a compat syscall
sparc/compat: Provide an accurate in_compat_syscall implementation
sparc/syscall: Fix syscall_get_arch
seccomp: Check in_compat_syscall, not is_compat_task, in strict mode
ptrace: in PEEK_SIGINFO, check syscall bitness, not task bitness
auditsc: For seccomp events, log syscall compat state using
in_compat_syscall
staging/lustre: Switch from is_compat_task to in_compat_syscall
ext4: In ext4_dir_llseek, check syscall bitness directly
net/sctp: Use in_compat_syscall for sctp_getsockopt_connectx3
net/xfrm_user: Use in_compat_syscall to deny compat syscalls
firewire: Use in_compat_syscall to check ioctl compatness
efivars: Use in_compat_syscall to check for compat callers
amdkfd: Use in_compat_syscall to check open() caller type
input: Redefine INPUT_COMPAT_TEST as in_compat_syscall()
uhid: Check write() bitness using in_compat_syscall
x86/compat: Remove is_compat_task

arch/sparc/include/asm/compat.h | 6 ++++++
arch/sparc/include/asm/syscall.h | 9 ++++++++-
arch/x86/include/asm/compat.h | 3 ++-
arch/x86/include/asm/ftrace.h | 2 +-
arch/x86/kernel/process_64.c | 2 +-
drivers/firewire/core-cdev.c | 4 ++--
drivers/firmware/efi/efivars.c | 2 +-
drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 2 +-
drivers/gpu/drm/amd/amdkfd/kfd_process.c | 2 +-
drivers/hid/uhid.c | 2 +-
drivers/input/input-compat.h | 12 +-----------
drivers/staging/lustre/lustre/llite/llite_internal.h | 2 +-
fs/ext4/dir.c | 2 +-
include/linux/compat.h | 15 +++++++++++++++
kernel/auditsc.c | 4 ++--
kernel/ptrace.c | 2 +-
kernel/seccomp.c | 4 ++--
net/sctp/socket.c | 2 +-
net/xfrm/xfrm_user.c | 2 +-
19 files changed, 49 insertions(+), 30 deletions(-)

--
2.5.0