You have COMPAT_SYSCALL_DEFINE3(x86_waitpid, compat_pid_t, pid, unsigned int __user *, stat_addr, int, options) { return compat_sys_wait4(pid, stat_addr, options, NULL); } with COMPAT_SYSCALL_DEFINE4(wait4, compat_pid_t, pid, compat_uint_t __user *, stat_addr, int, options, struct compat_rusage __user *, ru) { struct rusage r; long err = kernel_wait4(pid, stat_addr, options, ru ? &r : NULL); if (err > 0) { if (ru && put_compat_rusage(&r, ru)) return -EFAULT; } return err; }
so that turns into return kernel_wait4(pid, stat_addr, options, NULL); Now, look at SYSCALL_DEFINE3(waitpid, pid_t, pid, int __user *, stat_addr, int, options) { return sys_wait4(pid, stat_addr, options, NULL); } and SYSCALL_DEFINE4(wait4, pid_t, upid, int __user *, stat_addr, int, options, struct rusage __user *, ru) { struct rusage r; long err = kernel_wait4(upid, stat_addr, options, ru ? &r : NULL); if (err > 0) { if (ru && copy_to_user(ru, &r, sizeof(struct rusage))) return -EFAULT; } return err; } and tell me what is the difference between those. In other words, the problem with sys32_waitpid() was not that it didn't use proper wrappers - it's that it was (and always had been) 100% pointless. For fsck sake, look at the arguments. waitpid(2) takes pid_t, pointer to int and an int. How the hell could it possibly have required a compat wrapper? Let's get rid of the junk rather than covering it with more layers of crap...