lkml.org 
[lkml]   [2012]   [Mar]   [26]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 2/6] trace: add support for 32 bit compat syscalls on x86_64
    Date
    From: Michael Davidson <md@google.com>

    Add support for a set of events to trace 32 bit compat system calls
    in addition to the native 64 bit system calls.

    Events for compat system calls have event names of the form:
    syscalls:sys_enter_compat_<name>
    syscalls:sys_exit_compat_<name>

    The ascii formatted version of trace events that can be read from
    the tracing/trace file reports compat system calls as:
    compat_<name>(...)

    - add CONFIG_FTRACE_COMPAT_SYSCALLS

    - add a "compat" flag to the syscall_metadata struct so that we can
    distinguish between "native" and "compat" metadata at init time
    when building the system call # to metadata mapping tables

    - add a COMPAT_SYSCALL_METADATAx() macro to define system call
    metadata for compat system calls

    - define a set of COMPAT_SYSCALL_METADATA[0-6] macros

    - modify syscall_nr_to_meta() to know about compat system calls
    and return a pointer to the correct metadata

    - modify print_syscall_{enter|exit}() to find the system call metadata
    by looking in the containing ftrace_event_call struct

    - add system call metadata definitions for the x86_64 32 bit compat
    system calls

    Signed-off-by: Vaibhav Nagarnaik <vnagarnaik@google.com>
    ---
    arch/x86/ia32/Makefile | 2 +
    arch/x86/ia32/ia32_syscall_metadata.c | 443 +++++++++++++++++++++++++++++++++
    fs/dcookies.c | 2 +-
    fs/open.c | 2 +-
    fs/read_write.c | 8 +-
    fs/sync.c | 8 +-
    include/linux/syscalls.h | 24 ++-
    include/trace/syscall.h | 18 ++-
    kernel/trace/Kconfig | 6 +
    kernel/trace/trace_syscalls.c | 24 ++-
    mm/fadvise.c | 5 +-
    mm/filemap.c | 2 +-
    12 files changed, 521 insertions(+), 23 deletions(-)
    create mode 100644 arch/x86/ia32/ia32_syscall_metadata.c

    diff --git a/arch/x86/ia32/Makefile b/arch/x86/ia32/Makefile
    index 455646e..ba6d3c8 100644
    --- a/arch/x86/ia32/Makefile
    +++ b/arch/x86/ia32/Makefile
    @@ -12,3 +12,5 @@ obj-$(CONFIG_IA32_AOUT) += ia32_aout.o

    audit-class-$(CONFIG_AUDIT) := audit.o
    obj-$(CONFIG_IA32_EMULATION) += $(audit-class-y)
    +
    +obj-$(CONFIG_FTRACE_COMPAT_SYSCALLS) += ia32_syscall_metadata.o
    diff --git a/arch/x86/ia32/ia32_syscall_metadata.c b/arch/x86/ia32/ia32_syscall_metadata.c
    new file mode 100644
    index 0000000..8001794
    --- /dev/null
    +++ b/arch/x86/ia32/ia32_syscall_metadata.c
    @@ -0,0 +1,443 @@
    +#include <linux/slab.h>
    +#include <linux/syscalls.h>
    +#include <linux/module.h>
    +#include <asm/asm-offsets.h>
    +
    +/*
    + * syscall metadata for 32 bit compatible system calls
    + *
    + * The metadata entries are in the same order as the system call table
    + * but this is just to make it easier to check them for completeness
    + * and correctness.
    + */
    +
    +COMPAT_SYSCALL_METADATA0(restart_syscall)
    +COMPAT_SYSCALL_METADATA1(exit, int, error_code)
    +/* fork */
    +COMPAT_SYSCALL_METADATA3(read, unsigned int, fd, char __user *, buf, size_t, count)
    +COMPAT_SYSCALL_METADATA3(write, unsigned int, fd, const char __user *, buf, size_t, count)
    +COMPAT_SYSCALL_METADATA3(open, const char __user *, filename, int, flags, int, mode)
    +COMPAT_SYSCALL_METADATA1(close, unsigned int, fd)
    +COMPAT_SYSCALL_METADATA3(waitpid, compat_pid_t, pid, int __user *, stat_addr, int, options)
    +COMPAT_SYSCALL_METADATA2(creat, const char __user *, pathname, int, mode)
    +COMPAT_SYSCALL_METADATA2(link, const char __user *, oldname, const char __user *, newname)
    +COMPAT_SYSCALL_METADATA1(unlink, const char __user *, pathname)
    +/* execve */
    +COMPAT_SYSCALL_METADATA1(chdir, const char __user *, filename)
    +COMPAT_SYSCALL_METADATA1(time, compat_time_t __user *, tloc)
    +COMPAT_SYSCALL_METADATA3(mknod, const char __user *, filename, int, mode, unsigned, dev)
    +COMPAT_SYSCALL_METADATA2(chmod, const char __user *, filename, mode_t, mode)
    +COMPAT_SYSCALL_METADATA3(lchown16, const char __user *, filename, old_uid_t, user, old_gid_t, group)
    +/* ni */
    +COMPAT_SYSCALL_METADATA2(stat, char __user *, filename, struct __old_kernel_stat __user *, statbuf)
    +COMPAT_SYSCALL_METADATA3(lseek, unsigned int, fd, int, offset, unsigned int, whence)
    +COMPAT_SYSCALL_METADATA0(getpid)
    +COMPAT_SYSCALL_METADATA5(mount, char __user *, dev_name, char __user *, dir_name, char __user *, type, unsigned long, flags, void __user *, data)
    +COMPAT_SYSCALL_METADATA1(oldumount, char __user *, name)
    +COMPAT_SYSCALL_METADATA1(setuid16, old_uid_t, uid)
    +COMPAT_SYSCALL_METADATA0(getuid16)
    +COMPAT_SYSCALL_METADATA1(stime, compat_time_t __user *, tptr)
    +COMPAT_SYSCALL_METADATA4(ptrace, compat_long_t, request, compat_long_t, pid, compat_long_t, addr, compat_long_t, data)
    +COMPAT_SYSCALL_METADATA1(alarm, unsigned int, seconds)
    +COMPAT_SYSCALL_METADATA2(fstat, unsigned int, fd, struct __old_kernel_stat __user *, statbuf)
    +COMPAT_SYSCALL_METADATA0(pause)
    +COMPAT_SYSCALL_METADATA2(utime, char __user *, filename, struct compat_utimbuf __user *, times)
    +/* ni */
    +/* ni */
    +COMPAT_SYSCALL_METADATA2(access, const char __user *, filename, int, mode)
    +COMPAT_SYSCALL_METADATA1(nice, int, increment)
    +/* ni */
    +COMPAT_SYSCALL_METADATA0(sync)
    +COMPAT_SYSCALL_METADATA2(kill, int, pid, int, sig)
    +COMPAT_SYSCALL_METADATA2(rename, const char __user *, oldname, const char __user *, newname)
    +COMPAT_SYSCALL_METADATA2(mkdir, const char __user *, pathname, int, mode)
    +COMPAT_SYSCALL_METADATA1(rmdir, const char __user *, pathname)
    +COMPAT_SYSCALL_METADATA1(dup, unsigned int, fildes)
    +COMPAT_SYSCALL_METADATA1(pipe, int __user *, fildes)
    +COMPAT_SYSCALL_METADATA1(times, struct compat_tms __user *, tbuf)
    +/* ni */
    +COMPAT_SYSCALL_METADATA1(brk, unsigned long, brk)
    +COMPAT_SYSCALL_METADATA1(setgid16, old_gid_t, gid)
    +COMPAT_SYSCALL_METADATA0(getgid16)
    +COMPAT_SYSCALL_METADATA2(signal, int, sig, __sighandler_t, handler)
    +COMPAT_SYSCALL_METADATA0(geteuid16)
    +COMPAT_SYSCALL_METADATA0(getegid16)
    +COMPAT_SYSCALL_METADATA1(acct, const char __user *, name)
    +COMPAT_SYSCALL_METADATA2(umount, char __user *, name, int, flags)
    +/* ni */
    +COMPAT_SYSCALL_METADATA3(ioctl, unsigned int, fd, unsigned int, cmd, unsigned long, arg)
    +/* ni */
    +COMPAT_SYSCALL_METADATA2(setpgid, pid_t, pid, pid_t, pgid)
    +/* ni */
    +COMPAT_SYSCALL_METADATA1(olduname, struct oldold_utsname __user *, name)
    +COMPAT_SYSCALL_METADATA1(umask, int, mask)
    +COMPAT_SYSCALL_METADATA1(chroot, const char __user *, filename)
    +COMPAT_SYSCALL_METADATA2(ustat, unsigned, dev, struct compat_ustat __user *, ubuf)
    +COMPAT_SYSCALL_METADATA2(dup2, unsigned int, oldfd, unsigned int, newfd)
    +COMPAT_SYSCALL_METADATA0(getppid)
    +COMPAT_SYSCALL_METADATA0(getpgrp)
    +COMPAT_SYSCALL_METADATA0(setsid)
    +COMPAT_SYSCALL_METADATA3(sigaction, int, sig, struct old_sigaction32 __user *, act, struct old_sigaction32 __user *, oact)
    +COMPAT_SYSCALL_METADATA0(sgetmask)
    +COMPAT_SYSCALL_METADATA1(ssetmask, int, newmask)
    +COMPAT_SYSCALL_METADATA2(setreuid16, old_uid_t, ruid, old_uid_t, euid)
    +COMPAT_SYSCALL_METADATA2(setregid16, old_gid_t, rgid, old_gid_t, egid)
    +COMPAT_SYSCALL_METADATA3(sigsuspend, int, history0, int, history1, old_sigset_t, mask)
    +COMPAT_SYSCALL_METADATA1(sigpending, compat_old_sigset_t __user *, set)
    +COMPAT_SYSCALL_METADATA2(sethostname, char __user *, name, int, len)
    +COMPAT_SYSCALL_METADATA2(setrlimit, unsigned int, resource, struct compat_rlimit __user *, rlim)
    +COMPAT_SYSCALL_METADATA2(old_getrlimit, unsigned int, resource, struct compat_rlimit __user *, rlim)
    +COMPAT_SYSCALL_METADATA2(getrusage, int, who, struct compat_rusage __user *, ru)
    +COMPAT_SYSCALL_METADATA2(gettimeofday, struct compat_timeval __user *, tv, struct timezone __user *, tz)
    +COMPAT_SYSCALL_METADATA2(settimeofday, struct compat_timeval __user *, tv, struct timezone __user *, tz)
    +COMPAT_SYSCALL_METADATA2(getgroups16, int, gidsetsize, old_gid_t __user *, grouplist)
    +COMPAT_SYSCALL_METADATA2(setgroups16, int, gidsetsize, old_gid_t __user *, grouplist)
    +COMPAT_SYSCALL_METADATA1(old_select, struct compat_sel_arg_struct __user *, arg)
    +COMPAT_SYSCALL_METADATA2(symlink, const char __user *, oldname, const char __user *, newname)
    +COMPAT_SYSCALL_METADATA2(lstat, char __user *, filename, struct __old_kernel_stat __user *, statbuf)
    +COMPAT_SYSCALL_METADATA3(readlink, const char __user *, path, char __user *, buf, int, bufsiz)
    +COMPAT_SYSCALL_METADATA1(uselib, const char __user *, library)
    +COMPAT_SYSCALL_METADATA2(swapon, const char __user *, specialfile, int, swap_flags)
    +COMPAT_SYSCALL_METADATA4(reboot, int, magic1, int, magic2, unsigned int, cmd, void __user *, arg)
    +COMPAT_SYSCALL_METADATA3(old_readdir, unsigned int, fd, struct compat_old_linux_dirent __user *, dirent, unsigned int, count)
    +COMPAT_SYSCALL_METADATA1(mmap, struct mmap_arg_struct32 __user *, arg)
    +COMPAT_SYSCALL_METADATA2(munmap, unsigned long, addr, size_t, len)
    +COMPAT_SYSCALL_METADATA2(truncate, const char __user *, path, long, length)
    +COMPAT_SYSCALL_METADATA2(ftruncate, unsigned int, fd, unsigned long, length)
    +COMPAT_SYSCALL_METADATA2(fchmod, unsigned int, fd, mode_t, mode)
    +COMPAT_SYSCALL_METADATA3(fchown16, unsigned int, fd, old_uid_t, user, old_gid_t, group)
    +COMPAT_SYSCALL_METADATA2(getpriority, int, which, int, who)
    +COMPAT_SYSCALL_METADATA3(setpriority, int, which, int, who, int, niceval)
    +/* ni */
    +COMPAT_SYSCALL_METADATA2(statfs, const char __user *, pathname, struct compat_statfs __user *, buf)
    +COMPAT_SYSCALL_METADATA2(fstatfs, unsigned int, fd, struct compat_statfs __user *, buf)
    +COMPAT_SYSCALL_METADATA3(ioperm, unsigned long, from, unsigned long, num, int, turn_on)
    +COMPAT_SYSCALL_METADATA2(socketcall, int, call, u32 __user *, args)
    +COMPAT_SYSCALL_METADATA3(syslog, int, type, char __user *, buf, int, len)
    +COMPAT_SYSCALL_METADATA3(setitimer, int, which, struct compat_itimerval __user *, in, struct compat_itimerval __user *, out)
    +COMPAT_SYSCALL_METADATA2(getitimer, int, which, struct compat_itimerval __user *, it)
    +COMPAT_SYSCALL_METADATA2(newstat, char __user *, filename, struct compat_stat __user *, statbuf)
    +COMPAT_SYSCALL_METADATA2(newlstat, char __user *, filename, struct compat_stat __user *, statbuf)
    +COMPAT_SYSCALL_METADATA2(newfstat, unsigned int, fd, struct compat_stat __user *, statbuf)
    +COMPAT_SYSCALL_METADATA1(uname, struct old_utsname __user *, name)
    +COMPAT_SYSCALL_METADATA1(iopl, unsigned int, level)
    +COMPAT_SYSCALL_METADATA0(vhangup)
    +/* ni */
    +/* sys32_vm86_warning */
    +COMPAT_SYSCALL_METADATA4(wait4, compat_pid_t, pid, compat_uint_t __user *, stat_addr, int, options, struct compat_rusage __user *, ru)
    +COMPAT_SYSCALL_METADATA1(swapoff, const char __user *, specialfile)
    +COMPAT_SYSCALL_METADATA1(sysinfo, struct compat_sysinfo __user *, info)
    +COMPAT_SYSCALL_METADATA6(ipc, u32, call, int, first, int, second, int, third, compat_uptr_t, ptr, u32, fifth)
    +COMPAT_SYSCALL_METADATA1(fsync, unsigned int, fd)
    +/* stub32_sigreturn */
    +/* stub32_clone */
    +COMPAT_SYSCALL_METADATA2(setdomainname, char __user *, name, int, len)
    +COMPAT_SYSCALL_METADATA1(newuname, struct new_utsname __user *, name)
    +/* sys_modify_ldt */
    +COMPAT_SYSCALL_METADATA1(adjtimex, struct compat_timex __user *, utp)
    +COMPAT_SYSCALL_METADATA3(mprotect, unsigned long, start, size_t, len, unsigned long, prot)
    +COMPAT_SYSCALL_METADATA3(sigprocmask, int, how, compat_old_sigset_t __user *, set, compat_old_sigset_t __user *, oset)
    +/* ni */
    +COMPAT_SYSCALL_METADATA3(init_module, void __user *, umod, unsigned long, len, const char __user *, uargs)
    +COMPAT_SYSCALL_METADATA2(delete_module, const char __user *, name_user, unsigned int, flags)
    +/* ni */
    +COMPAT_SYSCALL_METADATA4(quotactl, unsigned int, cmd, const char __user *, special, qid_t, id, void __user *, addr)
    +COMPAT_SYSCALL_METADATA1(getpgid, pid_t, pid)
    +COMPAT_SYSCALL_METADATA1(fchdir, unsigned int, fd)
    +/* ni */
    +COMPAT_SYSCALL_METADATA3(sysfs, int, option, unsigned long, arg1, unsigned long, arg2)
    +COMPAT_SYSCALL_METADATA1(personality, u_long, personality)
    +/* ni */
    +COMPAT_SYSCALL_METADATA1(setfsuid16, old_uid_t, uid)
    +COMPAT_SYSCALL_METADATA1(setfsgid16, old_gid_t, gid)
    +COMPAT_SYSCALL_METADATA5(llseek, unsigned int, fd, unsigned long, offset_high, unsigned long, offset_low, loff_t __user *, result, unsigned int, origin)
    +COMPAT_SYSCALL_METADATA3(getdents, unsigned int, fd, struct compat_linux_dirent __user *, dirent, unsigned int, count)
    +COMPAT_SYSCALL_METADATA5(select, int, n, compat_ulong_t __user *, inp, compat_ulong_t __user *, outp, compat_ulong_tt __user *, exp, struct compat_timeval __user *, tvp)
    +COMPAT_SYSCALL_METADATA2(flock, unsigned int, fd, unsigned int, cmd)
    +COMPAT_SYSCALL_METADATA3(msync, unsigned long, start, size_t, len, int, flags)
    +COMPAT_SYSCALL_METADATA3(readv, unsigned long, fd, const struct compat_iovec __user *, vec, unsigned long, vlen)
    +COMPAT_SYSCALL_METADATA3(writev, unsigned long, fd, const struct compat_iovec __user *, vec, unsigned long, vlen)
    +COMPAT_SYSCALL_METADATA1(getsid, pid_t, pid)
    +COMPAT_SYSCALL_METADATA1(fdatasync, unsigned int, fd)
    +COMPAT_SYSCALL_METADATA1(sysctl, struct compat_sysctl_args __user *, args)
    +COMPAT_SYSCALL_METADATA2(mlock, unsigned long, start, size_t, len)
    +COMPAT_SYSCALL_METADATA1(mlockall, int, flags)
    +COMPAT_SYSCALL_METADATA2(munlock, unsigned long, start, size_t, len)
    +COMPAT_SYSCALL_METADATA0(munlockall)
    +COMPAT_SYSCALL_METADATA2(sched_setparam, pid_t, pid, struct sched_param __user *, param)
    +COMPAT_SYSCALL_METADATA2(sched_getparam, pid_t, pid, struct sched_param __user *, param)
    +COMPAT_SYSCALL_METADATA3(sched_setscheduler, pid_t, pid, int, policy, struct sched_param __user *, param)
    +COMPAT_SYSCALL_METADATA1(sched_getscheduler, pid_t, pid)
    +COMPAT_SYSCALL_METADATA0(sched_yield)
    +COMPAT_SYSCALL_METADATA1(sched_get_priority_max, int, policy)
    +COMPAT_SYSCALL_METADATA1(sched_get_priority_min, int, policy)
    +COMPAT_SYSCALL_METADATA2(sched_rr_get_interval, compat_pid_t, pid, struct compat_timespec __user *, interval)
    +COMPAT_SYSCALL_METADATA2(nanosleep, struct compat_timespec __user *, rqtp, struct compat_timespec __user *, rmtp)
    +COMPAT_SYSCALL_METADATA5(mremap, unsigned long, addr, unsigned long, old_len, unsigned long, new_len, unsigned long, flags, unsigned long, new_addr)
    +COMPAT_SYSCALL_METADATA3(setresuid16, old_uid_t, ruid, old_uid_t, euid, old_uid_t, suid)
    +COMPAT_SYSCALL_METADATA3(getresuid16, old_uid_t __user *, ruid, old_uid_t __user *, euid, old_uid_t __user *, suid)
    +/* sys32_vm86_warning */
    +/* ni */
    +COMPAT_SYSCALL_METADATA3(poll, struct pollfd __user *, ufds, unsigned int, nfds, long, timeout_msecs)
    +COMPAT_SYSCALL_METADATA3(nfsservctl, int, cmd, struct compat_nfsctl_arg __user *, arg, struct compat_nfsctl_res __user *, res)
    +COMPAT_SYSCALL_METADATA3(setresgid16, old_gid_t, rgid, old_gid_t, egid, old_gid_t, sgid)
    +COMPAT_SYSCALL_METADATA3(getresgid16, old_gid_t __user *, rgid, old_gid_t __user *, egid, old_gid_t __user *, sgid)
    +COMPAT_SYSCALL_METADATA5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, unsigned long, arg4, unsigned long, arg5)
    +/* stub32_rt_sigreturn */
    +COMPAT_SYSCALL_METADATA4(rt_sigaction, int, sig, const struct sigaction32 __user *, act, struct sigaction32 __user *, oact, unsigned int , sigsetsize)
    +COMPAT_SYSCALL_METADATA4(rt_sigprocmask, int, how, compat_sigset_t __user *, set, compat_sigset_t __user *, oset, unsigned int, sigsetsize)
    +COMPAT_SYSCALL_METADATA2(rt_sigpending, compat_sigset_t __user *, set, unsigned int, sigsetsize)
    +COMPAT_SYSCALL_METADATA4(rt_sigtimedwait, const compat_sigset_t __user *, uthese, compat_siginfo_t __user *, uinfo, const struct compat_timespec __user *, uts, compat_size_t, sigsetsize)
    +COMPAT_SYSCALL_METADATA3(rt_sigqueueinfo, int, pid, int, sig, compat_siginfo_t __user *, uinfo)
    +COMPAT_SYSCALL_METADATA2(rt_sigsuspend, sigset_t __user *, unewset, size_t, sigsetsize)
    +COMPAT_SYSCALL_METADATA5(pread, unsigned int, fd, char __user *, ubuf, u32, count, u32, poslo, u32, poshi)
    +COMPAT_SYSCALL_METADATA5(pwrite, unsigned int, fd, char __user *, ubuf, u32, count, u32, poslo, u32, poshi)
    +COMPAT_SYSCALL_METADATA3(chown16, const char __user *, filename, old_uid_t, user, old_gid_t, group)
    +COMPAT_SYSCALL_METADATA2(getcwd, char __user *, buf, unsigned long, size)
    +COMPAT_SYSCALL_METADATA2(capget, cap_user_header_t, header, cap_user_data_t, dataptr)
    +COMPAT_SYSCALL_METADATA2(capset, cap_user_header_t, header, const cap_user_data_t, data)
    +COMPAT_SYSCALL_METADATA2(sigaltstack, const stack_ia32_t __user *, uss_ptr, stack_ia32_t __user *, uoss_ptr)
    +COMPAT_SYSCALL_METADATA4(sendfile, int, out_fd, int, in_fd, compat_off_t __user *, offset, s32, count)
    +/* ni */
    +/* ni */
    +/* stub32_vfork */
    +COMPAT_SYSCALL_METADATA2(getrlimit, unsigned int, resource, struct rlimit __user *, rlim)
    +COMPAT_SYSCALL_METADATA6(mmap_pgoff, unsigned long, addr, unsigned long, len, unsigned long, prot, unsigned long, flags, unsigned long, fd, unsigned long, pgoff)
    +COMPAT_SYSCALL_METADATA3(truncate64, const char __user *, path, unsigned long, offset_lo, unsigned long, offset_high)
    +COMPAT_SYSCALL_METADATA3(ftruncate64, unsigned int, fd, unsigned long, offset_lo, unsigned long, offset_high)
    +COMPAT_SYSCALL_METADATA2(stat64, char __user *, filename, struct stat64 __user *, statbuf)
    +COMPAT_SYSCALL_METADATA2(lstat64, char __user *, filename, struct stat64 __user *, statbuf)
    +COMPAT_SYSCALL_METADATA2(fstat64, unsigned long, fd, struct stat64 __user *, statbuf)
    +COMPAT_SYSCALL_METADATA3(lchown, const char __user *, filename, uid_t, user, gid_t, group)
    +COMPAT_SYSCALL_METADATA0(getuid)
    +COMPAT_SYSCALL_METADATA0(getgid)
    +COMPAT_SYSCALL_METADATA0(geteuid)
    +COMPAT_SYSCALL_METADATA0(getegid)
    +COMPAT_SYSCALL_METADATA2(setreuid, uid_t, ruid, uid_t, euid)
    +COMPAT_SYSCALL_METADATA2(setregid, gid_t, rgid, gid_t, egid)
    +COMPAT_SYSCALL_METADATA2(getgroups, int, gidsetsize, gid_t __user *, grouplist)
    +COMPAT_SYSCALL_METADATA2(setgroups, int, gidsetsize, gid_t __user *, grouplist)
    +COMPAT_SYSCALL_METADATA3(fchown, unsigned int, fd, uid_t, user, gid_t, group)
    +COMPAT_SYSCALL_METADATA3(setresuid, uid_t, ruid, uid_t, euid, uid_t, suid)
    +COMPAT_SYSCALL_METADATA3(getresuid, uid_t __user *, ruid, uid_t __user *, euid, uid_t __user *, suid)
    +COMPAT_SYSCALL_METADATA3(setresgid, gid_t, rgid, gid_t, egid, gid_t, sgid)
    +COMPAT_SYSCALL_METADATA3(getresgid, gid_t __user *, rgid, gid_t __user *, egid, gid_t __user *, sgid)
    +COMPAT_SYSCALL_METADATA3(chown, const char __user *, filename, uid_t, user, gid_t, group)
    +COMPAT_SYSCALL_METADATA1(setuid, uid_t, uid)
    +COMPAT_SYSCALL_METADATA1(setgid, gid_t, gid)
    +COMPAT_SYSCALL_METADATA1(setfsuid, uid_t, uid)
    +COMPAT_SYSCALL_METADATA1(setfsgid, gid_t, gid)
    +COMPAT_SYSCALL_METADATA2(pivot_root, const char __user *, new_root, const char __user *, put_old)
    +COMPAT_SYSCALL_METADATA3(mincore, unsigned long, start, size_t, len, unsigned char __user *, vec)
    +COMPAT_SYSCALL_METADATA3(madvise, unsigned long, start, size_t, len_in, int, behavior)
    +COMPAT_SYSCALL_METADATA3(getdents64, unsigned int, fd, struct linux_dirent64 __user *, dirent, unsigned int, count)
    +COMPAT_SYSCALL_METADATA3(fcntl64, unsigned int, fd, unsigned int, cmd, unsigned long, arg)
    +/* ni */
    +/* ni */
    +COMPAT_SYSCALL_METADATA0(gettid)
    +COMPAT_SYSCALL_METADATA4(readahead, int, fd, unsigned, off_lo, unsigned, off_hi, size_t, count)
    +COMPAT_SYSCALL_METADATA5(setxattr, const char __user *, pathname, const char __user *, name, const void __user *, value, size_t, size, int, flags)
    +COMPAT_SYSCALL_METADATA5(lsetxattr, const char __user *, pathname, const char __user *, name, const void __user *, value, size_t, size, int, flags)
    +COMPAT_SYSCALL_METADATA5(fsetxattr, int, fd, const char __user *, name, const void __user *,value, size_t, size, int, flags)
    +COMPAT_SYSCALL_METADATA4(getxattr, const char __user *, pathname, const char __user *, name, void __user *, value, size_t, size)
    +COMPAT_SYSCALL_METADATA4(fgetxattr, int, fd, const char __user *, name, void __user *, value, size_t, size)
    +COMPAT_SYSCALL_METADATA4(lgetxattr, const char __user *, pathname, const char __user *, name, void __user *, value, size_t, size)
    +COMPAT_SYSCALL_METADATA3(listxattr, const char __user *, pathname, char __user *, list, size_t, size)
    +COMPAT_SYSCALL_METADATA3(llistxattr, const char __user *, pathname, char __user *, list, size_t, size)
    +COMPAT_SYSCALL_METADATA3(flistxattr, int, fd, char __user *, list, size_t, size)
    +COMPAT_SYSCALL_METADATA2(removexattr, const char __user *, pathname, const char __user *, name)
    +COMPAT_SYSCALL_METADATA2(lremovexattr, const char __user *, pathname, const char __user *, name)
    +COMPAT_SYSCALL_METADATA2(fremovexattr, int, fd, const char __user *, name)
    +COMPAT_SYSCALL_METADATA2(tkill, pid_t, pid, int, sig)
    +COMPAT_SYSCALL_METADATA4(sendfile64, int, out_fd, int, in_fd, loff_t __user *, offset, size_t, count)
    +COMPAT_SYSCALL_METADATA6(futex, u32 __user *, uaddr, int, op, u32, val, struct compat_timespec __user *, utime, u32 __user *, uaddr2, u32, val3)
    +COMPAT_SYSCALL_METADATA3(sched_setaffinity, compat_pid_t, pid, unsigned int, len, compat_ulong_t __user *, user_mask_ptr)
    +COMPAT_SYSCALL_METADATA3(sched_getaffinity, compat_pid_t, pid, unsigned int, len, compat_ulong_t __user *, user_mask_ptr)
    +COMPAT_SYSCALL_METADATA1(set_thread_area, struct user_desc __user *, u_info)
    +COMPAT_SYSCALL_METADATA1(get_thread_area, struct user_desc __user *, u_info)
    +COMPAT_SYSCALL_METADATA2(io_setup, unsigned, nr_reqs, u32 __user *, ctxp)
    +COMPAT_SYSCALL_METADATA1(io_destroy, aio_context_t, ctx)
    +COMPAT_SYSCALL_METADATA5(io_getevents, aio_context_t, ctx_id, long, min_nr, long, nr, struct io_event __user *, events, struct timespec __user *, timeout)
    +COMPAT_SYSCALL_METADATA3(io_submit, aio_context_t, ctx_id, long, nr, struct iocb __user * __user *, iocbpp)
    +COMPAT_SYSCALL_METADATA3(io_cancel, aio_context_t, ctx_id, struct iocb __user *, iocb, struct io_event __user *, result)
    +COMPAT_SYSCALL_METADATA6(fadvise64, int, fd, __u32, offset_low, __u32, offset_high, __u32, len_low, __u32, len_high, int, advice)
    +/* ni */
    +COMPAT_SYSCALL_METADATA1(exit_group, int, error_code)
    +COMPAT_SYSCALL_METADATA3(lookup_dcookie, u64, cookie64, char __user *, buf, size_t, len)
    +COMPAT_SYSCALL_METADATA1(epoll_create, int, size)
    +COMPAT_SYSCALL_METADATA4(epoll_ctl, int, epfd, int, op, int, fd, struct epoll_event __user *, event)
    +COMPAT_SYSCALL_METADATA4(epoll_wait, int, epfd, struct epoll_event __user *, events, int, maxevents, int, timeout)
    +COMPAT_SYSCALL_METADATA5(remap_file_pages, unsigned long, start, unsigned long, size, unsigned long, prot, unsigned long, pgoff, unsigned long, flags)
    +COMPAT_SYSCALL_METADATA1(set_tid_address, int __user *, tidptr)
    +COMPAT_SYSCALL_METADATA3(timer_create, const clockid_t, which_clock, struct sigevent __user *, timer_event_spec, timer_t __user *, created_timer_id)
    +COMPAT_SYSCALL_METADATA4(timer_settime, timer_t, timer_id, int, flags, const struct itimerspec __user *, new_setting, struct itimerspec __user *, old_setting)
    +COMPAT_SYSCALL_METADATA2(timer_gettime, timer_t, timer_id, struct itimerspec __user *, setting)
    +COMPAT_SYSCALL_METADATA1(timer_getoverrun, timer_t, timer_id)
    +COMPAT_SYSCALL_METADATA1(timer_delete, timer_t, timer_id)
    +COMPAT_SYSCALL_METADATA2(clock_settime, const clockid_t, which_clock, const struct timespec __user *, tp)
    +COMPAT_SYSCALL_METADATA2(clock_gettime, const clockid_t, which_clock, struct timespec __user *,tp)
    +COMPAT_SYSCALL_METADATA2(clock_getres, const clockid_t, which_clock, struct timespec __user *, tp)
    +COMPAT_SYSCALL_METADATA4(clock_nanosleep, const clockid_t, which_clock, int, flags, const struct timespec __user *, rqtp, struct timespec __user *, rmtp)
    +COMPAT_SYSCALL_METADATA3(statfs64, const char __user *, pathname, size_t, sz, struct statfs64 __user *, buf)
    +COMPAT_SYSCALL_METADATA3(fstatfs64, unsigned int, fd, size_t, sz, struct statfs64 __user *, buf)
    +COMPAT_SYSCALL_METADATA3(tgkill, pid_t, tgid, pid_t, pid, int, sig)
    +COMPAT_SYSCALL_METADATA2(utimes, char __user *, filename, struct timeval __user *, utimes)
    +COMPAT_SYSCALL_METADATA4(fadvise64_64, int, fd, loff_t, offset, loff_t, len, int, advice)
    +/* ni */
    +COMPAT_SYSCALL_METADATA6(mbind, unsigned long, start, unsigned long, len, unsigned long, mode, unsigned long __user *, nmask, unsigned long, maxnode, unsigned, flags)
    +COMPAT_SYSCALL_METADATA5(get_mempolicy, int __user *, policy, unsigned long __user *, nmask, unsigned long, maxnode, unsigned long, addr, unsigned long, flags)
    +COMPAT_SYSCALL_METADATA3(set_mempolicy, int, mode, unsigned long __user *, nmask, unsigned long, maxnode)
    +COMPAT_SYSCALL_METADATA4(mq_open, const char __user *, u_name, int, oflag, mode_t, mode, struct mq_attr __user *, u_attr)
    +COMPAT_SYSCALL_METADATA1(mq_unlink, const char __user *, u_name)
    +COMPAT_SYSCALL_METADATA5(mq_timedsend, mqd_t, mqdes, const char __user *, u_msg_ptr, size_t, msg_len, unsigned int, msg_prio, const struct timespec __user *, u_abs_timeout)
    +COMPAT_SYSCALL_METADATA5(mq_timedreceive, mqd_t, mqdes, char __user *, u_msg_ptr, size_t, msg_len, unsigned int __user *, u_msg_prio, const struct timespec __user *, u_abs_timeout)
    +COMPAT_SYSCALL_METADATA2(mq_notify, mqd_t, mqdes, const struct sigevent __user *, u_notification)
    +COMPAT_SYSCALL_METADATA3(mq_getsetattr, mqd_t, mqdes, const struct mq_attr __user *, u_mqstat, struct mq_attr __user *, u_omqstat)
    +COMPAT_SYSCALL_METADATA4(kexec_load, unsigned long, entry, unsigned long, nr_segments, struct kexec_segment __user *, segments, unsigned long, flags)
    +COMPAT_SYSCALL_METADATA5(waitid, int, which, pid_t, upid, struct siginfo __user *, infop, int, options, struct rusage __user *, ru)
    +/* ni */
    +COMPAT_SYSCALL_METADATA5(add_key, const char __user *, _type, const char __user *, _description, const void __user *, _payload, size_t, plen, key_serial_t, ringid)
    +COMPAT_SYSCALL_METADATA4(request_key, const char __user *, _type, const char __user *, _description, const char __user *, _callout_info, key_serial_t, destringid)
    +COMPAT_SYSCALL_METADATA5(keyctl, int, option, unsigned long, arg2, unsigned long, arg3, unsigned long, arg4, unsigned long, arg5)
    +COMPAT_SYSCALL_METADATA3(ioprio_set, int, which, int, who, int, ioprio)
    +COMPAT_SYSCALL_METADATA2(ioprio_get, int, which, int, who)
    +COMPAT_SYSCALL_METADATA0(inotify_init)
    +COMPAT_SYSCALL_METADATA3(inotify_add_watch, int, fd, const char __user *, pathname, u32, mask)
    +COMPAT_SYSCALL_METADATA2(inotify_rm_watch, int, fd, __s32, wd)
    +COMPAT_SYSCALL_METADATA4(migrate_pages, pid_t, pid, unsigned long, maxnode, const unsigned long __user *, old_nodes, const unsigned long __user *, new_nodes)
    +COMPAT_SYSCALL_METADATA4(openat, int, dfd, const char __user *, filename, int, flags, int, mode)
    +COMPAT_SYSCALL_METADATA3(mkdirat, int, dfd, const char __user *, pathname, int, mode)
    +COMPAT_SYSCALL_METADATA4(mknodat, int, dfd, const char __user *, filename, int, mode, unsigned, dev)
    +COMPAT_SYSCALL_METADATA5(fchownat, int, dfd, const char __user *, filename, uid_t, user, gid_t, group, int, flag)
    +COMPAT_SYSCALL_METADATA3(futimesat, int, dfd, char __user *, filename, struct timeval __user *, utimes)
    +COMPAT_SYSCALL_METADATA4(fstatat, int, dfd, char __user *, filename, struct stat64 __user *, statbuf, int, flag)
    +COMPAT_SYSCALL_METADATA3(unlinkat, int, dfd, const char __user *, pathname, int, flag)
    +COMPAT_SYSCALL_METADATA4(renameat, int, olddfd, const char __user *, oldname, int, newdfd, const char __user *, newname)
    +COMPAT_SYSCALL_METADATA5(linkat, int, olddfd, const char __user *, oldname, int, newdfd, const char __user *, newname, int, flags)
    +COMPAT_SYSCALL_METADATA3(symlinkat, const char __user *, oldname, int, newdfd, const char __user *, newname)
    +COMPAT_SYSCALL_METADATA4(readlinkat, int, dfd, const char __user *, pathname, char __user *, buf, int, bufsiz)
    +COMPAT_SYSCALL_METADATA3(fchmodat, int, dfd, const char __user *, filename, mode_t, mode)
    +COMPAT_SYSCALL_METADATA3(faccessat, int, dfd, const char __user *, filename, int, mode)
    +COMPAT_SYSCALL_METADATA6(pselect6, int, n, fd_set __user *, inp, fd_set __user *, outp, fd_set __user *, exp, struct timespec __user *, tsp, void __user *, sig)
    +COMPAT_SYSCALL_METADATA5(ppoll, struct pollfd __user *, ufds, unsigned int, nfds, struct timespec __user *, tsp, const sigset_t __user *, sigmask, size_t, sigsetsize)
    +COMPAT_SYSCALL_METADATA1(unshare, unsigned long, unshare_flags)
    +COMPAT_SYSCALL_METADATA2(set_robust_list, struct robust_list_head __user *, head, compat_size_t, len)
    +COMPAT_SYSCALL_METADATA3(get_robust_list, int, pid, struct robust_list_head __user * __user *, head_ptr, compat_size_t __user *, len_ptr)
    +COMPAT_SYSCALL_METADATA6(splice, int, fd_in, loff_t __user *, off_in, int, fd_out, loff_t __user *, off_out, size_t, len, unsigned int, flags)
    +COMPAT_SYSCALL_METADATA4(sync_file_range, int, fd, loff_t, offset, loff_t, nbytes, unsigned int, flags)
    +COMPAT_SYSCALL_METADATA4(tee, int, fdin, int, fdout, size_t, len, unsigned int, flags)
    +COMPAT_SYSCALL_METADATA4(vmsplice, int, fd, const struct compat_iovec __user *, iov, unsigned long, nr_segs, unsigned int, flags)
    +COMPAT_SYSCALL_METADATA6(move_pages, pid_t, pid, unsigned long, nr_pages, const void __user * __user *, pages, const int __user *, nodes, int __user *, status, int, flags)
    +COMPAT_SYSCALL_METADATA3(getcpu, unsigned __user *, cpup, unsigned __user *, nodep, struct getcpu_cache __user *, unused)
    +COMPAT_SYSCALL_METADATA6(epoll_pwait, int, epfd, struct epoll_event __user *, events, int, maxevents, int, timeout, const sigset_t __user *, sigmask, size_t, sigsetsize)
    +COMPAT_SYSCALL_METADATA4(utimensat, int, dfd, char __user *, filename, struct timespec __user *, utimes, int, flags)
    +COMPAT_SYSCALL_METADATA3(signalfd, int, ufd, sigset_t __user *, user_mask, size_t, sizemask)
    +COMPAT_SYSCALL_METADATA2(timerfd_create, int, clockid, int, flags)
    +COMPAT_SYSCALL_METADATA1(eventfd, unsigned int, count)
    +COMPAT_SYSCALL_METADATA4(fallocate, int, fd, int, mode, loff_t, offset, loff_t, len)
    +COMPAT_SYSCALL_METADATA4(timerfd_settime, int, ufd, int, flags, const struct itimerspec __user *, utmr, struct itimerspec __user *, otmr)
    +COMPAT_SYSCALL_METADATA2(timerfd_gettime, int, ufd, struct itimerspec __user *, otmr)
    +COMPAT_SYSCALL_METADATA4(signalfd4, int, ufd, sigset_t __user *, user_mask, size_t, sizemask, int, flags)
    +COMPAT_SYSCALL_METADATA2(eventfd2, unsigned int, count, int, flags)
    +COMPAT_SYSCALL_METADATA1(epoll_create1, int, flags)
    +COMPAT_SYSCALL_METADATA3(dup3, unsigned int, oldfd, unsigned int, newfd, int, flags)
    +COMPAT_SYSCALL_METADATA2(pipe2, int __user *, fildes, int, flags)
    +COMPAT_SYSCALL_METADATA1(inotify_init1, int, flags)
    +COMPAT_SYSCALL_METADATA5(preadv, unsigned long, fd, const struct compat_iovec __user *, vec, unsigned long, vlen, u32, pos_low, 32, pos_high)
    +COMPAT_SYSCALL_METADATA5(pwritev, unsigned long, fd, const struct compat_iovec __user *, vec, unsigned long, vlen, u32, pos_low, u32, pos_high)
    +COMPAT_SYSCALL_METADATA4(rt_tgsigqueueinfo, pid_t, tgid, pid_t, pid, int, sig, siginfo_t __user *, uinfo)
    +COMPAT_SYSCALL_METADATA5(perf_event_open, struct perf_event_attr __user *, attr_uptr, pid_t, pid, int, cpu, int, group_fd, unsigned long, flags)
    +COMPAT_SYSCALL_METADATA5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg, unsigned int, vlen, unsigned int, flags, struct timespec __user *, timeout)
    +
    +
    +extern long ia32_sys_call_table[];
    +
    +int nr_compat_syscalls;
    +struct syscall_metadata **compat_syscalls_metadata;
    +
    +static const char *prefixes[] = { "sys32", "stub32", "compat_sys", "sys", NULL };
    +
    +/*
    + * This is truly horrible.
    + *
    + * There is no header file that defines a *complete* set of 32 bit system
    + * call numbers (unistd_32.h only defines ones that are currently exported
    + * to user space and omits lots of old system calls that are still implemented
    + * by the kernel.
    + *
    + * There is also no table that can be used to map a system call number into
    + * the canonical name of that system call.
    + *
    + * So we are forced to use an even more unpleasant version of the technique
    + * used by ftrace to handle the normal system call metadata ...
    + *
    + * For each entry in the 32 bit system call table:
    + * Look up the address in the kernel symbol table
    + * Strip off any "sys32|stub32|sys|compat" prefix
    + * Search through all of the compat metadata entries for a matching name
    + *
    + */
    +static struct syscall_metadata __init *find_compat_syscall_meta(unsigned long addr)
    +{
    + struct syscall_metadata **start;
    + struct syscall_metadata **stop;
    + char str[KSYM_SYMBOL_LEN];
    + const char *name;
    + const char **p;
    + extern struct syscall_metadata *__start_syscalls_metadata[];
    + extern struct syscall_metadata *__stop_syscalls_metadata[];
    +
    + start = __start_syscalls_metadata;
    + stop = __stop_syscalls_metadata;
    + kallsyms_lookup(addr, NULL, NULL, NULL, str);
    +
    + /*
    + * If there is a {sys|compat|sys32|stub32} prefix strip it off
    + */
    + for (p = prefixes, name = str; *p; p++) {
    + int len = strlen(*p);
    + if (strncmp(name, *p, len) == 0) {
    + name += len;
    + break;
    + }
    + }
    +
    + for ( ; start < stop; start++) {
    + if (!(*start)->compat)
    + continue;
    +
    + /*
    + * ignore the "compat_" prefix on the metadata name
    + * when doing the comparison
    + */
    + if ((*start)->name && !strcmp((*start)->name + 6, name))
    + return *start;
    + }
    + return NULL;
    +}
    +
    +static int __init init_compat_syscall_metadata(void)
    +{
    + struct syscall_metadata *meta;
    + int i;
    +
    + nr_compat_syscalls = __NR_ia32_syscall_max;
    + compat_syscalls_metadata = kzalloc(sizeof(*compat_syscalls_metadata) *
    + nr_compat_syscalls, GFP_KERNEL);
    + if (!compat_syscalls_metadata) {
    + nr_compat_syscalls = -1;
    + WARN_ON(1);
    + return -ENOMEM;
    + }
    +
    + for (i = 0; i < nr_compat_syscalls; i++) {
    + if ((meta = find_compat_syscall_meta(ia32_sys_call_table[i]))) {
    + meta->syscall_nr = i;
    + compat_syscalls_metadata[i] = meta;
    + }
    + }
    +
    + return 0;
    +}
    +
    +core_initcall(init_compat_syscall_metadata);
    diff --git a/fs/dcookies.c b/fs/dcookies.c
    index dda0dc7..9a448c8 100644
    --- a/fs/dcookies.c
    +++ b/fs/dcookies.c
    @@ -145,7 +145,7 @@ out:
    /* And here is where the userspace process can look up the cookie value
    * to retrieve the path.
    */
    -SYSCALL_DEFINE(lookup_dcookie)(u64 cookie64, char __user * buf, size_t len)
    +SYSCALL_DEFINE3(lookup_dcookie, u64, cookie64, char __user *, buf, size_t, len)
    {
    unsigned long cookie = (unsigned long)cookie64;
    int err = -EINVAL;
    diff --git a/fs/open.c b/fs/open.c
    index 77becc0..cc5edeb 100644
    --- a/fs/open.c
    +++ b/fs/open.c
    @@ -269,7 +269,7 @@ int do_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
    return file->f_op->fallocate(file, mode, offset, len);
    }

    -SYSCALL_DEFINE(fallocate)(int fd, int mode, loff_t offset, loff_t len)
    +SYSCALL_DEFINE4(fallocate, int, fd, int, mode, loff_t, offset, loff_t, len)
    {
    struct file *file;
    int error = -EBADF;
    diff --git a/fs/read_write.c b/fs/read_write.c
    index 5ad4248..72b675b 100644
    --- a/fs/read_write.c
    +++ b/fs/read_write.c
    @@ -492,8 +492,8 @@ SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf,
    return ret;
    }

    -SYSCALL_DEFINE(pread64)(unsigned int fd, char __user *buf,
    - size_t count, loff_t pos)
    +SYSCALL_DEFINE4(pread64, unsigned int, fd, char __user *, buf,
    + size_t, count, loff_t, pos)
    {
    struct file *file;
    ssize_t ret = -EBADF;
    @@ -521,8 +521,8 @@ asmlinkage long SyS_pread64(long fd, long buf, long count, loff_t pos)
    SYSCALL_ALIAS(sys_pread64, SyS_pread64);
    #endif

    -SYSCALL_DEFINE(pwrite64)(unsigned int fd, const char __user *buf,
    - size_t count, loff_t pos)
    +SYSCALL_DEFINE4(pwrite64, unsigned int, fd, const char __user *, buf,
    + size_t, count, loff_t, pos)
    {
    struct file *file;
    ssize_t ret = -EBADF;
    diff --git a/fs/sync.c b/fs/sync.c
    index f3501ef..584cbd0 100644
    --- a/fs/sync.c
    +++ b/fs/sync.c
    @@ -271,8 +271,8 @@ EXPORT_SYMBOL(generic_write_sync);
    * already-instantiated disk blocks, there are no guarantees here that the data
    * will be available after a crash.
    */
    -SYSCALL_DEFINE(sync_file_range)(int fd, loff_t offset, loff_t nbytes,
    - unsigned int flags)
    +SYSCALL_DEFINE4(sync_file_range, int, fd, loff_t, offset, loff_t, nbytes,
    + unsigned int, flags)
    {
    int ret;
    struct file *file;
    @@ -366,8 +366,8 @@ SYSCALL_ALIAS(sys_sync_file_range, SyS_sync_file_range);

    /* It would be nice if people remember that not all the world's an i386
    when they introduce new system calls */
    -SYSCALL_DEFINE(sync_file_range2)(int fd, unsigned int flags,
    - loff_t offset, loff_t nbytes)
    +SYSCALL_DEFINE4(sync_file_range2, int, fd, unsigned int, flags,
    + loff_t, offset, loff_t, nbytes)
    {
    return sys_sync_file_range(fd, offset, nbytes, flags);
    }
    diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
    index ed0003c..a5b0cae 100644
    --- a/include/linux/syscalls.h
    +++ b/include/linux/syscalls.h
    @@ -159,7 +159,7 @@ extern struct trace_event_functions exit_syscall_print_funcs;
    __attribute__((section("_ftrace_events"))) \
    *__event_exit_##sname = &event_exit_##sname;

    -#define SYSCALL_METADATAx(x, sname, ...) \
    +#define _SYSCALL_METADATAx(x, mname, sname, _compat, ...) \
    static const char *types_##sname[] = { \
    __SC_STR_TDECL##x(__VA_ARGS__) \
    }; \
    @@ -170,11 +170,12 @@ extern struct trace_event_functions exit_syscall_print_funcs;
    SYSCALL_TRACE_EXIT_EVENT(sname); \
    static struct syscall_metadata __used \
    __syscall_meta_##sname = { \
    - .name = "sys"#sname, \
    + .name = mname, \
    .syscall_nr = -1, /* Filled in at boot */ \
    .nb_args = x, \
    .types = types_##sname, \
    .args = args_##sname, \
    + .compat = _compat, \
    .enter_event = &event_enter_##sname, \
    .exit_event = &event_exit_##sname, \
    .enter_fields = LIST_HEAD_INIT(__syscall_meta_##sname.enter_fields), \
    @@ -182,6 +183,25 @@ extern struct trace_event_functions exit_syscall_print_funcs;
    static struct syscall_metadata __used \
    __attribute__((section("__syscalls_metadata"))) \
    *__p_syscall_meta_##sname = &__syscall_meta_##sname;
    +
    +#define SYSCALL_METADATAx(x, sname, ...) \
    + _SYSCALL_METADATAx(x, "sys"#sname, sname, 0, __VA_ARGS__)
    +
    +#ifdef CONFIG_FTRACE_COMPAT_SYSCALLS
    +
    +#define COMPAT_SYSCALL_METADATAx(x, sname, ...) \
    + _SYSCALL_METADATAx(x, "compat"#sname, _compat##sname, 1, __VA_ARGS__)
    +
    +#define COMPAT_SYSCALL_METADATA0(name, ...) COMPAT_SYSCALL_METADATAx(0, _##name, __VA_ARGS__)
    +#define COMPAT_SYSCALL_METADATA1(name, ...) COMPAT_SYSCALL_METADATAx(1, _##name, __VA_ARGS__)
    +#define COMPAT_SYSCALL_METADATA2(name, ...) COMPAT_SYSCALL_METADATAx(2, _##name, __VA_ARGS__)
    +#define COMPAT_SYSCALL_METADATA3(name, ...) COMPAT_SYSCALL_METADATAx(3, _##name, __VA_ARGS__)
    +#define COMPAT_SYSCALL_METADATA4(name, ...) COMPAT_SYSCALL_METADATAx(4, _##name, __VA_ARGS__)
    +#define COMPAT_SYSCALL_METADATA5(name, ...) COMPAT_SYSCALL_METADATAx(5, _##name, __VA_ARGS__)
    +#define COMPAT_SYSCALL_METADATA6(name, ...) COMPAT_SYSCALL_METADATAx(6, _##name, __VA_ARGS__)
    +
    +#endif /* CONFIG_FTRACE_COMPAT_SYSCALLS */
    +
    #else
    #define SYSCALL_METADATAx(x, name, ...)
    #endif /* CONFIG_FTRACE_SYSCALLS */
    diff --git a/include/trace/syscall.h b/include/trace/syscall.h
    index 31966a4..f495e55 100644
    --- a/include/trace/syscall.h
    +++ b/include/trace/syscall.h
    @@ -21,8 +21,9 @@
    */
    struct syscall_metadata {
    const char *name;
    - int syscall_nr;
    - int nb_args;
    + u16 syscall_nr;
    + u8 nb_args;
    + u8 compat;
    const char **types;
    const char **args;
    struct list_head enter_fields;
    @@ -32,6 +33,19 @@ struct syscall_metadata {
    };

    #ifdef CONFIG_FTRACE_SYSCALLS
    +
    +#ifdef CONFIG_FTRACE_COMPAT_SYSCALLS
    +
    +extern int nr_compat_syscalls;
    +extern struct syscall_metadata **compat_syscalls_metadata;
    +
    +static inline struct syscall_metadata *compat_syscall_nr_to_meta(int nr)
    +{
    + return (nr < nr_compat_syscalls) ? compat_syscalls_metadata[nr]
    + : NULL;
    +}
    +#endif /* CONFIG_FTRACE_COMPAT_SYSCALLS */
    +
    extern unsigned long arch_syscall_addr(int nr);
    extern int init_syscall_trace(struct ftrace_event_call *call);

    diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig
    index cd31345..cd0954b 100644
    --- a/kernel/trace/Kconfig
    +++ b/kernel/trace/Kconfig
    @@ -240,6 +240,12 @@ config FTRACE_SYSCALLS
    help
    Basic tracer to catch the syscall entry and exit events.

    +config FTRACE_COMPAT_SYSCALLS
    + bool "Trace 32 bit compat syscalls"
    + depends on FTRACE_SYSCALLS
    + help
    + Trace syscall entry and exit events for 32 bit compat syscalls.
    +
    config TRACE_BRANCH_PROFILING
    bool
    select GENERIC_TRACER
    diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c
    index cb65454..43a8685 100644
    --- a/kernel/trace/trace_syscalls.c
    +++ b/kernel/trace/trace_syscalls.c
    @@ -5,6 +5,7 @@
    #include <linux/module.h> /* for MODULE_NAME_LEN via KSYM_SYMBOL_LEN */
    #include <linux/ftrace.h>
    #include <linux/perf_event.h>
    +#include <linux/compat.h>
    #include <asm/syscall.h>

    #include "trace_output.h"
    @@ -90,6 +91,10 @@ find_syscall_meta(unsigned long syscall)
    return NULL;

    for ( ; start < stop; start++) {
    +#ifdef CONFIG_FTRACE_COMPAT_SYSCALLS
    + if ((*start)->compat) /* skip compat syscalls */
    + continue;
    +#endif
    if ((*start)->name && arch_syscall_match_sym_name(str, (*start)->name))
    return *start;
    }
    @@ -98,6 +103,10 @@ find_syscall_meta(unsigned long syscall)

    static struct syscall_metadata *syscall_nr_to_meta(int nr)
    {
    +#ifdef CONFIG_FTRACE_COMPAT_SYSCALLS
    + if (is_compat_task())
    + return compat_syscall_nr_to_meta(nr);
    +#endif
    if (!syscalls_metadata || nr >= NR_syscalls || nr < 0)
    return NULL;

    @@ -112,11 +121,13 @@ print_syscall_enter(struct trace_iterator *iter, int flags,
    struct trace_entry *ent = iter->ent;
    struct syscall_trace_enter *trace;
    struct syscall_metadata *entry;
    - int i, ret, syscall;
    + int i, ret;
    + struct ftrace_event_call *call;

    trace = (typeof(trace))ent;
    - syscall = trace->nr;
    - entry = syscall_nr_to_meta(syscall);
    + event = ftrace_find_event(ent->type);
    + call = container_of(event, struct ftrace_event_call, event);
    + entry = call->data;

    if (!entry)
    goto end;
    @@ -164,13 +175,14 @@ print_syscall_exit(struct trace_iterator *iter, int flags,
    struct trace_seq *s = &iter->seq;
    struct trace_entry *ent = iter->ent;
    struct syscall_trace_exit *trace;
    - int syscall;
    struct syscall_metadata *entry;
    int ret;
    + struct ftrace_event_call *call;

    trace = (typeof(trace))ent;
    - syscall = trace->nr;
    - entry = syscall_nr_to_meta(syscall);
    + event = ftrace_find_event(ent->type);
    + call = container_of(event, struct ftrace_event_call, event);
    + entry = call->data;

    if (!entry) {
    trace_seq_printf(s, "\n");
    diff --git a/mm/fadvise.c b/mm/fadvise.c
    index 469491e..60d83eb 100644
    --- a/mm/fadvise.c
    +++ b/mm/fadvise.c
    @@ -24,7 +24,8 @@
    * POSIX_FADV_WILLNEED could set PG_Referenced, and POSIX_FADV_NOREUSE could
    * deactivate the pages and clear PG_Referenced.
    */
    -SYSCALL_DEFINE(fadvise64_64)(int fd, loff_t offset, loff_t len, int advice)
    +SYSCALL_DEFINE4(fadvise64_64, int, fd, loff_t, offset,
    + loff_t, len, int, advice)
    {
    struct file *file = fget(fd);
    struct address_space *mapping;
    @@ -145,7 +146,7 @@ SYSCALL_ALIAS(sys_fadvise64_64, SyS_fadvise64_64);

    #ifdef __ARCH_WANT_SYS_FADVISE64

    -SYSCALL_DEFINE(fadvise64)(int fd, loff_t offset, size_t len, int advice)
    +SYSCALL_DEFINE4(fadvise64, int, fd, loff_t, offset, size_t, len, int, advice)
    {
    return sys_fadvise64_64(fd, offset, len, advice);
    }
    diff --git a/mm/filemap.c b/mm/filemap.c
    index cb8ee3e..6e06d27 100644
    --- a/mm/filemap.c
    +++ b/mm/filemap.c
    @@ -1499,7 +1499,7 @@ do_readahead(struct address_space *mapping, struct file *filp,
    return 0;
    }

    -SYSCALL_DEFINE(readahead)(int fd, loff_t offset, size_t count)
    +SYSCALL_DEFINE3(readahead, int, fd, loff_t, offset, size_t, count)
    {
    ssize_t ret;
    struct file *file;
    --
    1.7.7.3


    \
     
     \ /
      Last update: 2012-03-26 20:43    [W:0.092 / U:0.036 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site