From b95baca05436d2f31984a5bf0a064b2b8e0cfc42 Mon Sep 17 00:00:00 2001 From: Randolph Chung Date: Wed, 16 Apr 2003 07:45:43 -0700 Subject: [PATCH] [PATCH] getrlimit,setrlimit,getrusage,wait4 unification --- arch/parisc/kernel/sys_parisc32.c | 143 ------------------------ arch/parisc/kernel/syscall.S | 8 +- arch/ppc64/kernel/misc.S | 10 +- arch/ppc64/kernel/sys_ppc32.c | 175 ------------------------------ arch/s390/kernel/compat_linux.c | 101 ----------------- arch/s390/kernel/compat_wrapper.S | 30 ++--- arch/sparc64/kernel/sys_sparc32.c | 127 ---------------------- arch/sparc64/kernel/systbls.S | 8 +- arch/x86_64/ia32/ia32entry.S | 10 +- arch/x86_64/ia32/sys_ia32.c | 148 +------------------------ include/asm-parisc/compat.h | 2 + include/asm-ppc64/compat.h | 3 + include/asm-s390/compat.h | 3 + include/asm-sparc64/compat.h | 2 + include/asm-x86_64/compat.h | 3 + include/linux/compat.h | 24 ++++ kernel/compat.c | 146 +++++++++++++++++++++++++ 17 files changed, 217 insertions(+), 726 deletions(-) diff --git a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c index 011b648aeccb3..63a85350d4ea0 100644 --- a/arch/parisc/kernel/sys_parisc32.c +++ b/arch/parisc/kernel/sys_parisc32.c @@ -475,81 +475,6 @@ sys32_settimeofday(struct compat_timeval *tv, struct timezone *tz) return do_sys_settimeofday(tv ? &ktv : NULL, tz ? &ktz : NULL); } -struct rusage32 { - struct compat_timeval ru_utime; - struct compat_timeval ru_stime; - int ru_maxrss; - int ru_ixrss; - int ru_idrss; - int ru_isrss; - int ru_minflt; - int ru_majflt; - int ru_nswap; - int ru_inblock; - int ru_oublock; - int ru_msgsnd; - int ru_msgrcv; - int ru_nsignals; - int ru_nvcsw; - int ru_nivcsw; -}; - -static int -put_rusage32(struct rusage32 *ru32p, struct rusage *r) -{ - struct rusage32 r32; -#undef CP -#define CP(t) r32.t = r->t; - CP(ru_utime.tv_sec); CP(ru_utime.tv_usec); - CP(ru_stime.tv_sec); CP(ru_stime.tv_usec); - CP(ru_maxrss); - CP(ru_ixrss); - CP(ru_idrss); - CP(ru_isrss); - CP(ru_minflt); - CP(ru_majflt); - CP(ru_nswap); - CP(ru_inblock); - CP(ru_oublock); - CP(ru_msgsnd); - CP(ru_msgrcv); - CP(ru_nsignals); - CP(ru_nvcsw); - CP(ru_nivcsw); - return copy_to_user(ru32p, &r32, sizeof r32); -} - -asmlinkage int -sys32_getrusage(int who, struct rusage32 *ru) -{ - struct rusage r; - int ret; - extern asmlinkage int sys_getrusage(int who, struct rusage *ru); - - KERNEL_SYSCALL(ret, sys_getrusage, who, &r); - if (put_rusage32(ru, &r)) return -EFAULT; - return ret; -} - -asmlinkage int -sys32_wait4(compat_pid_t pid, unsigned int * stat_addr, int options, - struct rusage32 * ru) -{ - if (!ru) - return sys_wait4(pid, stat_addr, options, NULL); - else { - struct rusage r; - int ret; - unsigned int status; - - KERNEL_SYSCALL(ret, sys_wait4, pid, stat_addr ? &status : NULL, options, &r); - if (put_rusage32(ru, &r)) return -EFAULT; - if (stat_addr && put_user(status, stat_addr)) - return -EFAULT; - return ret; - } -} - int cp_compat_stat(struct kstat *stat, struct compat_stat *statbuf) { int err; @@ -721,74 +646,6 @@ out: return error; } -struct rlimit32 { - __u32 rlim_cur; - __u32 rlim_max; -}; - -#define RLIM32_INFINITY 0xffffffff - -asmlinkage long sys32_getrlimit(unsigned int resource, struct rlimit32 *rlim) -{ - struct rlimit32 rlim32; - struct rlimit *rlimip; - - if (resource >= RLIM_NLIMITS) - return -EINVAL; - rlimip = current->rlim + resource; - if (rlimip->rlim_cur >= RLIM32_INFINITY) { - rlim32.rlim_cur = RLIM32_INFINITY; - } else { - rlim32.rlim_cur = rlimip->rlim_cur; - } - if (rlimip->rlim_max >= RLIM32_INFINITY) { - rlim32.rlim_max = RLIM32_INFINITY; - } else { - rlim32.rlim_max = rlimip->rlim_max; - } - return copy_to_user(rlim, &rlim32, sizeof (struct rlimit32)); -} - -asmlinkage long sys32_setrlimit(unsigned int resource, struct rlimit32 *rlim) -{ - struct rlimit32 rlim32; - struct rlimit new_rlim, *old_rlim; - - if (resource >= RLIM_NLIMITS) - return -EINVAL; - if (copy_from_user(&rlim32, rlim, sizeof(rlim))) - return -EFAULT; - if (rlim32.rlim_cur == RLIM32_INFINITY) { - new_rlim.rlim_cur = RLIM_INFINITY; - } else { - new_rlim.rlim_cur = rlim32.rlim_cur; - } - if (rlim32.rlim_max == RLIM32_INFINITY) { - new_rlim.rlim_max = RLIM_INFINITY; - } else { - new_rlim.rlim_max = rlim32.rlim_max; - } - - old_rlim = current->rlim + resource; - if (((new_rlim.rlim_cur > old_rlim->rlim_max) || - (new_rlim.rlim_max > old_rlim->rlim_max)) && - !capable(CAP_SYS_RESOURCE)) - return -EPERM; - if (resource == RLIMIT_NOFILE) { - if (new_rlim.rlim_cur > NR_OPEN || new_rlim.rlim_max > NR_OPEN) - return -EPERM; - } - if (resource == RLIMIT_STACK) { - if (new_rlim.rlim_max > 1024 * 1024 * 1024) { - new_rlim.rlim_max = 1024 * 1024 * 1024; - } - new_rlim.rlim_max = PAGE_ALIGN(new_rlim.rlim_max); - } - - *old_rlim = new_rlim; - return 0; -} - static int copy_mount_stuff_to_kernel(const void *user, unsigned long *kernel) { int i; diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S index 929a4a3cb695f..f1b08ceafe807 100644 --- a/arch/parisc/kernel/syscall.S +++ b/arch/parisc/kernel/syscall.S @@ -431,9 +431,9 @@ sys_call_table: ENTRY_COMP(sigpending) ENTRY_SAME(sethostname) /* Following 3 have linux-common-code structs containing longs -( */ - ENTRY_DIFF(setrlimit) /* 75 */ - ENTRY_DIFF(getrlimit) - ENTRY_DIFF(getrusage) + ENTRY_COMP(setrlimit) /* 75 */ + ENTRY_COMP(getrlimit) + ENTRY_COMP(getrusage) /* struct timeval and timezone are maybe?? consistent wide and narrow */ ENTRY_DIFF(gettimeofday) ENTRY_DIFF(settimeofday) @@ -476,7 +476,7 @@ sys_call_table: ENTRY_SAME(fstat64) ENTRY_SAME(vfork_wrapper) /* struct rusage contains longs... */ - ENTRY_DIFF(wait4) + ENTRY_COMP(wait4) ENTRY_SAME(swapoff) /* 115 */ ENTRY_DIFF(sysinfo) ENTRY_SAME(shutdown) diff --git a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S index 2af247e0e7a16..b13facd777aa6 100644 --- a/arch/ppc64/kernel/misc.S +++ b/arch/ppc64/kernel/misc.S @@ -577,9 +577,9 @@ _GLOBAL(sys_call_table32) .llong .sys_sigsuspend .llong .compat_sys_sigpending .llong .sys32_sethostname - .llong .sys32_setrlimit /* 75 */ - .llong .sys32_old_getrlimit - .llong .sys32_getrusage + .llong .compat_sys_setrlimit /* 75 */ + .llong .compat_sys_old_getrlimit + .llong .compat_sys_getrusage .llong .sys32_gettimeofday .llong .sys32_settimeofday .llong .sys32_getgroups /* 80 */ @@ -616,7 +616,7 @@ _GLOBAL(sys_call_table32) .llong .sys_vhangup .llong .sys_ni_syscall /* old idle syscall */ .llong .sys_ni_syscall /* old vm86 syscall */ - .llong .sys32_wait4 + .llong .compat_sys_wait4 .llong .sys_swapoff /* 115 */ .llong .sys32_sysinfo .llong .sys32_ipc @@ -692,7 +692,7 @@ _GLOBAL(sys_call_table32) .llong .sys_ni_syscall /* reserved for streams1 */ .llong .sys_ni_syscall /* reserved for streams2 */ .llong .sys_vfork - .llong .sys32_getrlimit /* 190 */ + .llong .compat_sys_getrlimit /* 190 */ .llong .sys32_readahead .llong .sys32_mmap2 .llong .sys32_truncate64 diff --git a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c index a7c67d5da6b26..fba8c82544551 100644 --- a/arch/ppc64/kernel/sys_ppc32.c +++ b/arch/ppc64/kernel/sys_ppc32.c @@ -1125,152 +1125,6 @@ static inline long put_tv32(struct compat_timeval *o, struct timeval *i) __put_user(i->tv_usec, &o->tv_usec))); } - - - -#define RLIM_INFINITY32 0xffffffff -#define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x) - -struct rlimit32 { - u32 rlim_cur; - u32 rlim_max; -}; - -extern asmlinkage long sys_getrlimit(unsigned int resource, struct rlimit *rlim); -asmlinkage long sys32_getrlimit(unsigned int resource, struct rlimit32 *rlim) -{ - struct rlimit r; - int ret; - mm_segment_t old_fs = get_fs(); - - set_fs (KERNEL_DS); - ret = sys_getrlimit(resource, &r); - set_fs(old_fs); - if (!ret) { - ret = put_user(RESOURCE32(r.rlim_cur), &rlim->rlim_cur); - ret |= __put_user(RESOURCE32(r.rlim_max), &rlim->rlim_max); - } - - return ret; -} - -/* Back compatibility for getrlimit. Needed for some apps. */ -asmlinkage long sys32_old_getrlimit(unsigned int resource, struct rlimit32* rlim) -{ - struct rlimit x; // 64-bit version of the resource limits. - struct rlimit32 x32; // 32-bit version of the resource limits. - - if (resource >= RLIM_NLIMITS) - return -EINVAL; - - memcpy(&x, current->rlim+resource, sizeof(struct rlimit)); - - if (x.rlim_cur > RLIM_INFINITY32) - x32.rlim_cur = RLIM_INFINITY32; - else - x32.rlim_cur = x.rlim_cur; - - if (x.rlim_max > RLIM_INFINITY32) - x32.rlim_max = RLIM_INFINITY32; - else - x32.rlim_max = x.rlim_max; - - return (copy_to_user(rlim, &x32, sizeof(x32))) ? (-EFAULT) : 0; -} - -extern asmlinkage long sys_setrlimit(unsigned int resource, struct rlimit *rlim); -asmlinkage long sys32_setrlimit(unsigned int resource, struct rlimit32 *rlim) -{ - struct rlimit r; - long ret; - mm_segment_t old_fs = get_fs (); - - if (resource >= RLIM_NLIMITS) return -EINVAL; - if (get_user (r.rlim_cur, &rlim->rlim_cur) || - __get_user (r.rlim_max, &rlim->rlim_max)) - return -EFAULT; - if (r.rlim_cur >= RLIM_INFINITY32) - r.rlim_cur = RLIM_INFINITY; - if (r.rlim_max >= RLIM_INFINITY32) - r.rlim_max = RLIM_INFINITY; - set_fs (KERNEL_DS); - ret = sys_setrlimit(resource, &r); - set_fs (old_fs); - - return ret; -} - - -struct rusage32 { - struct compat_timeval ru_utime; - struct compat_timeval ru_stime; - s32 ru_maxrss; - s32 ru_ixrss; - s32 ru_idrss; - s32 ru_isrss; - s32 ru_minflt; - s32 ru_majflt; - s32 ru_nswap; - s32 ru_inblock; - s32 ru_oublock; - s32 ru_msgsnd; - s32 ru_msgrcv; - s32 ru_nsignals; - s32 ru_nvcsw; - s32 ru_nivcsw; -}; - -static int put_rusage (struct rusage32 *ru, struct rusage *r) -{ - int err; - - err = put_user (r->ru_utime.tv_sec, &ru->ru_utime.tv_sec); - err |= __put_user (r->ru_utime.tv_usec, &ru->ru_utime.tv_usec); - err |= __put_user (r->ru_stime.tv_sec, &ru->ru_stime.tv_sec); - err |= __put_user (r->ru_stime.tv_usec, &ru->ru_stime.tv_usec); - err |= __put_user (r->ru_maxrss, &ru->ru_maxrss); - err |= __put_user (r->ru_ixrss, &ru->ru_ixrss); - err |= __put_user (r->ru_idrss, &ru->ru_idrss); - err |= __put_user (r->ru_isrss, &ru->ru_isrss); - err |= __put_user (r->ru_minflt, &ru->ru_minflt); - err |= __put_user (r->ru_majflt, &ru->ru_majflt); - err |= __put_user (r->ru_nswap, &ru->ru_nswap); - err |= __put_user (r->ru_inblock, &ru->ru_inblock); - err |= __put_user (r->ru_oublock, &ru->ru_oublock); - err |= __put_user (r->ru_msgsnd, &ru->ru_msgsnd); - err |= __put_user (r->ru_msgrcv, &ru->ru_msgrcv); - err |= __put_user (r->ru_nsignals, &ru->ru_nsignals); - err |= __put_user (r->ru_nvcsw, &ru->ru_nvcsw); - err |= __put_user (r->ru_nivcsw, &ru->ru_nivcsw); - return err; -} - - -extern asmlinkage long sys_getrusage(int who, struct rusage *ru); - -/* Note: it is necessary to treat who as an unsigned int, - * with the corresponding cast to a signed int to insure that the - * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) - * and the register representation of a signed int (msr in 64-bit mode) is performed. - */ -asmlinkage long sys32_getrusage(u32 who, struct rusage32 *ru) -{ - struct rusage r; - int ret; - mm_segment_t old_fs = get_fs(); - - set_fs (KERNEL_DS); - ret = sys_getrusage((int)who, &r); - set_fs (old_fs); - if (put_rusage (ru, &r)) - return -EFAULT; - - return ret; -} - - - - struct sysinfo32 { s32 uptime; u32 loads[3]; @@ -2340,35 +2194,6 @@ asmlinkage long sys32_creat(const char * pathname, u32 mode) } -extern asmlinkage long sys_wait4(pid_t pid, unsigned int * stat_addr, int options, struct rusage * ru); - -/* Note: it is necessary to treat pid and options as unsigned ints, - * with the corresponding cast to a signed int to insure that the - * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) - * and the register representation of a signed int (msr in 64-bit mode) is performed. - */ -asmlinkage long sys32_wait4(u32 pid, unsigned int * stat_addr, u32 options, struct rusage * ru) -{ - if (!ru) - return sys_wait4((int)pid, stat_addr, options, NULL); - else { - struct rusage r; - int ret; - unsigned int status; - mm_segment_t old_fs = get_fs(); - - set_fs (KERNEL_DS); - ret = sys_wait4((int)pid, stat_addr ? &status : NULL, options, &r); - set_fs (old_fs); - if (put_rusage ((struct rusage32 *)ru, &r)) return -EFAULT; - if (stat_addr && put_user (status, stat_addr)) - return -EFAULT; - return ret; - } - -} - - extern asmlinkage long sys_waitpid(pid_t pid, unsigned int * stat_addr, int options); /* Note: it is necessary to treat pid and options as unsigned ints, diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c index 7120e9f3d1e47..fc131aa5d8ba1 100644 --- a/arch/s390/kernel/compat_linux.c +++ b/arch/s390/kernel/compat_linux.c @@ -1492,26 +1492,6 @@ static int put_rusage (struct rusage32 *ru, struct rusage *r) return err; } -asmlinkage int sys32_wait4(compat_pid_t pid, unsigned int *stat_addr, int options, struct rusage32 *ru) -{ - if (!ru) - return sys_wait4(pid, stat_addr, options, NULL); - else { - struct rusage r; - int ret; - unsigned int status; - mm_segment_t old_fs = get_fs(); - - set_fs (KERNEL_DS); - ret = sys_wait4(pid, stat_addr ? &status : NULL, options, &r); - set_fs (old_fs); - if (put_rusage (ru, &r)) return -EFAULT; - if (stat_addr && put_user (status, stat_addr)) - return -EFAULT; - return ret; - } -} - struct sysinfo32 { s32 uptime; u32 loads[3]; @@ -1733,87 +1713,6 @@ sys32_rt_sigqueueinfo(int pid, int sig, siginfo_t32 *uinfo) return ret; } -#define RLIM_OLD_INFINITY32 0x7fffffff -#define RLIM_INFINITY32 0xffffffff -#define RESOURCE32_OLD(x) ((x > RLIM_OLD_INFINITY32) ? RLIM_OLD_INFINITY32 : x) -#define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x) - -struct rlimit32 { - u32 rlim_cur; - u32 rlim_max; -}; - -extern asmlinkage long sys_getrlimit(unsigned int resource, struct rlimit *rlim); - -asmlinkage int sys32_old_getrlimit(unsigned int resource, struct rlimit32 *rlim) -{ - struct rlimit r; - int ret; - mm_segment_t old_fs = get_fs (); - - set_fs (KERNEL_DS); - ret = sys_getrlimit(resource, &r); - set_fs (old_fs); - if (!ret) { - ret = put_user (RESOURCE32_OLD(r.rlim_cur), &rlim->rlim_cur); - ret |= __put_user (RESOURCE32_OLD(r.rlim_max), &rlim->rlim_max); - } - return ret; -} - -asmlinkage int sys32_getrlimit(unsigned int resource, struct rlimit32 *rlim) -{ - struct rlimit r; - int ret; - mm_segment_t old_fs = get_fs (); - - set_fs (KERNEL_DS); - ret = sys_getrlimit(resource, &r); - set_fs (old_fs); - if (!ret) { - ret = put_user (RESOURCE32(r.rlim_cur), &rlim->rlim_cur); - ret |= __put_user (RESOURCE32(r.rlim_max), &rlim->rlim_max); - } - return ret; -} - -extern asmlinkage int sys_setrlimit(unsigned int resource, struct rlimit *rlim); - -asmlinkage int sys32_setrlimit(unsigned int resource, struct rlimit32 *rlim) -{ - struct rlimit r; - int ret; - mm_segment_t old_fs = get_fs (); - - if (resource >= RLIM_NLIMITS) return -EINVAL; - if (get_user (r.rlim_cur, &rlim->rlim_cur) || - __get_user (r.rlim_max, &rlim->rlim_max)) - return -EFAULT; - if (r.rlim_cur == RLIM_INFINITY32) - r.rlim_cur = RLIM_INFINITY; - if (r.rlim_max == RLIM_INFINITY32) - r.rlim_max = RLIM_INFINITY; - set_fs (KERNEL_DS); - ret = sys_setrlimit(resource, &r); - set_fs (old_fs); - return ret; -} - -extern asmlinkage int sys_getrusage(int who, struct rusage *ru); - -asmlinkage int sys32_getrusage(int who, struct rusage32 *ru) -{ - struct rusage r; - int ret; - mm_segment_t old_fs = get_fs(); - - set_fs (KERNEL_DS); - ret = sys_getrusage(who, &r); - set_fs (old_fs); - if (put_rusage (ru, &r)) return -EFAULT; - return ret; -} - extern void check_pending(int signum); /* diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S index 6b45e7f1ee37d..e450a8116a030 100644 --- a/arch/s390/kernel/compat_wrapper.S +++ b/arch/s390/kernel/compat_wrapper.S @@ -299,34 +299,34 @@ sys32_sethostname_wrapper: lgfr %r3,%r3 # int jg sys_sethostname # branch to system call - .globl sys32_setrlimit_wrapper -sys32_setrlimit_wrapper: + .globl compat_sys_setrlimit_wrapper +compat_sys_setrlimit_wrapper: llgfr %r2,%r2 # unsigned int llgtr %r3,%r3 # struct rlimit_emu31 * - jg sys32_setrlimit # branch to system call + jg compat_sys_setrlimit # branch to system call - .globl sys32_old_getrlimit_wrapper -sys32_old_getrlimit_wrapper: + .globl compat_sys_old_getrlimit_wrapper +compat_sys_old_getrlimit_wrapper: llgfr %r2,%r2 # unsigned int llgtr %r3,%r3 # struct rlimit_emu31 * - jg sys32_old_getrlimit # branch to system call + jg compat_sys_old_getrlimit # branch to system call - .globl sys32_getrlimit_wrapper -sys32_getrlimit_wrapper: + .globl compat_sys_getrlimit_wrapper +compat_sys_getrlimit_wrapper: llgfr %r2,%r2 # unsigned int llgtr %r3,%r3 # struct rlimit_emu31 * - jg sys32_getrlimit # branch to system call + jg compat_sys_getrlimit # branch to system call .globl sys32_mmap2_wrapper sys32_mmap2_wrapper: llgtr %r2,%r2 # struct mmap_arg_struct_emu31 * jg sys32_mmap2 # branch to system call - .globl sys32_getrusage_wrapper -sys32_getrusage_wrapper: + .globl compat_sys_getrusage_wrapper +compat_sys_getrusage_wrapper: lgfr %r2,%r2 # int llgtr %r3,%r3 # struct rusage_emu31 * - jg sys32_getrusage # branch to system call + jg compat_sys_getrusage # branch to system call .globl sys32_gettimeofday_wrapper sys32_gettimeofday_wrapper: @@ -498,13 +498,13 @@ compat_sys_newfstat_wrapper: #sys32_vhangup_wrapper # void - .globl sys32_wait4_wrapper -sys32_wait4_wrapper: + .globl compat_sys_wait4_wrapper +compat_sys_wait4_wrapper: lgfr %r2,%r2 # pid_t llgtr %r3,%r3 # unsigned int * lgfr %r4,%r4 # int llgtr %r5,%r5 # struct rusage * - jg sys32_wait4 # branch to system call + jg compat_sys_wait4 # branch to system call .globl sys32_swapoff_wrapper sys32_swapoff_wrapper: diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c index 9122aa000ad51..b1194401debae 100644 --- a/arch/sparc64/kernel/sys_sparc32.c +++ b/arch/sparc64/kernel/sys_sparc32.c @@ -1521,70 +1521,6 @@ out: return err; } -struct rusage32 { - struct compat_timeval ru_utime; - struct compat_timeval ru_stime; - s32 ru_maxrss; - s32 ru_ixrss; - s32 ru_idrss; - s32 ru_isrss; - s32 ru_minflt; - s32 ru_majflt; - s32 ru_nswap; - s32 ru_inblock; - s32 ru_oublock; - s32 ru_msgsnd; - s32 ru_msgrcv; - s32 ru_nsignals; - s32 ru_nvcsw; - s32 ru_nivcsw; -}; - -static int put_rusage (struct rusage32 *ru, struct rusage *r) -{ - int err; - - err = put_user (r->ru_utime.tv_sec, &ru->ru_utime.tv_sec); - err |= __put_user (r->ru_utime.tv_usec, &ru->ru_utime.tv_usec); - err |= __put_user (r->ru_stime.tv_sec, &ru->ru_stime.tv_sec); - err |= __put_user (r->ru_stime.tv_usec, &ru->ru_stime.tv_usec); - err |= __put_user (r->ru_maxrss, &ru->ru_maxrss); - err |= __put_user (r->ru_ixrss, &ru->ru_ixrss); - err |= __put_user (r->ru_idrss, &ru->ru_idrss); - err |= __put_user (r->ru_isrss, &ru->ru_isrss); - err |= __put_user (r->ru_minflt, &ru->ru_minflt); - err |= __put_user (r->ru_majflt, &ru->ru_majflt); - err |= __put_user (r->ru_nswap, &ru->ru_nswap); - err |= __put_user (r->ru_inblock, &ru->ru_inblock); - err |= __put_user (r->ru_oublock, &ru->ru_oublock); - err |= __put_user (r->ru_msgsnd, &ru->ru_msgsnd); - err |= __put_user (r->ru_msgrcv, &ru->ru_msgrcv); - err |= __put_user (r->ru_nsignals, &ru->ru_nsignals); - err |= __put_user (r->ru_nvcsw, &ru->ru_nvcsw); - err |= __put_user (r->ru_nivcsw, &ru->ru_nivcsw); - return err; -} - -asmlinkage int sys32_wait4(compat_pid_t pid, unsigned int *stat_addr, int options, struct rusage32 *ru) -{ - if (!ru) - return sys_wait4(pid, stat_addr, options, NULL); - else { - struct rusage r; - int ret; - unsigned int status; - mm_segment_t old_fs = get_fs(); - - set_fs (KERNEL_DS); - ret = sys_wait4(pid, stat_addr ? &status : NULL, options, &r); - set_fs (old_fs); - if (put_rusage (ru, &r)) return -EFAULT; - if (stat_addr && put_user (status, stat_addr)) - return -EFAULT; - return ret; - } -} - struct sysinfo32 { s32 uptime; u32 loads[3]; @@ -1805,69 +1741,6 @@ sys32_rt_sigqueueinfo(int pid, int sig, siginfo_t32 *uinfo) return ret; } -#define RLIM_INFINITY32 0x7fffffff -#define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x) - -struct rlimit32 { - u32 rlim_cur; - u32 rlim_max; -}; - -extern asmlinkage int sys_getrlimit(unsigned int resource, struct rlimit *rlim); - -asmlinkage int sys32_getrlimit(unsigned int resource, struct rlimit32 *rlim) -{ - struct rlimit r; - int ret; - mm_segment_t old_fs = get_fs (); - - set_fs (KERNEL_DS); - ret = sys_getrlimit(resource, &r); - set_fs (old_fs); - if (!ret) { - ret = put_user (RESOURCE32(r.rlim_cur), &rlim->rlim_cur); - ret |= __put_user (RESOURCE32(r.rlim_max), &rlim->rlim_max); - } - return ret; -} - -extern asmlinkage int sys_setrlimit(unsigned int resource, struct rlimit *rlim); - -asmlinkage int sys32_setrlimit(unsigned int resource, struct rlimit32 *rlim) -{ - struct rlimit r; - int ret; - mm_segment_t old_fs = get_fs (); - - if (resource >= RLIM_NLIMITS) return -EINVAL; - if (get_user (r.rlim_cur, &rlim->rlim_cur) || - __get_user (r.rlim_max, &rlim->rlim_max)) - return -EFAULT; - if (r.rlim_cur == RLIM_INFINITY32) - r.rlim_cur = RLIM_INFINITY; - if (r.rlim_max == RLIM_INFINITY32) - r.rlim_max = RLIM_INFINITY; - set_fs (KERNEL_DS); - ret = sys_setrlimit(resource, &r); - set_fs (old_fs); - return ret; -} - -extern asmlinkage int sys_getrusage(int who, struct rusage *ru); - -asmlinkage int sys32_getrusage(int who, struct rusage32 *ru) -{ - struct rusage r; - int ret; - mm_segment_t old_fs = get_fs(); - - set_fs (KERNEL_DS); - ret = sys_getrusage(who, &r); - set_fs (old_fs); - if (put_rusage (ru, &r)) return -EFAULT; - return ret; -} - extern void check_pending(int signum); asmlinkage int sys32_sigaction (int sig, struct old_sigaction32 *act, struct old_sigaction32 *oact) diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S index 31efe79e77c94..e2d02cced8536 100644 --- a/arch/sparc64/kernel/systbls.S +++ b/arch/sparc64/kernel/systbls.S @@ -20,7 +20,7 @@ .globl sys_call_table32 sys_call_table32: /*0*/ .word sys_restart_syscall, sparc_exit, sys_fork, sys_read, sys_write -/*5*/ .word sparc32_open, sys_close, sys32_wait4, sys_creat, sys_link +/*5*/ .word sparc32_open, sys_close, compat_sys_wait4, sys_creat, sys_link /*10*/ .word sys_unlink, sunos_execv, sys_chdir, sys32_chown16, sys32_mknod /*15*/ .word sys32_chmod, sys32_lchown16, sparc_brk, sys_perfctr, sys32_lseek /*20*/ .word sys_getpid, sys_capget, sys_capset, sys32_setuid16, sys32_getuid16 @@ -42,13 +42,13 @@ sys_call_table32: /*100*/ .word sys_getpriority, sys32_rt_sigreturn, sys32_rt_sigaction, sys32_rt_sigprocmask, sys32_rt_sigpending .word sys32_rt_sigtimedwait, sys32_rt_sigqueueinfo, sys32_rt_sigsuspend, sys_setresuid, sys_getresuid /*110*/ .word sys_setresgid, sys_getresgid, sys_setregid, sys_nis_syscall, sys_nis_syscall - .word sys_getgroups, sys32_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_getcwd + .word sys_getgroups, sys32_gettimeofday, compat_sys_getrusage, sys_nis_syscall, sys_getcwd /*120*/ .word sys32_readv, sys32_writev, sys32_settimeofday, sys32_fchown16, sys_fchmod .word sys_nis_syscall, sys32_setreuid16, sys32_setregid16, sys_rename, sys_truncate /*130*/ .word sys_ftruncate, sys_flock, sys_lstat64, sys_nis_syscall, sys_nis_syscall .word sys_nis_syscall, sys_mkdir, sys_rmdir, sys32_utimes, sys_stat64 -/*140*/ .word sys32_sendfile64, sys_nis_syscall, compat_sys_futex, sys_gettid, sys32_getrlimit - .word sys32_setrlimit, sys_pivot_root, sys32_prctl, sys32_pciconfig_read, sys32_pciconfig_write +/*140*/ .word sys32_sendfile64, sys_nis_syscall, compat_sys_futex, sys_gettid, compat_sys_getrlimit + .word compat_sys_setrlimit, sys_pivot_root, sys32_prctl, sys32_pciconfig_read, sys32_pciconfig_write /*150*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64 .word compat_sys_fcntl64, sys_ni_syscall, compat_sys_statfs, compat_sys_fstatfs, sys_oldumount /*160*/ .word compat_sys_sched_setaffinity, compat_sys_sched_getaffinity, sys_getdomainname, sys_setdomainname, sys_nis_syscall diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S index d70801da8afe2..ae1196f233013 100644 --- a/arch/x86_64/ia32/ia32entry.S +++ b/arch/x86_64/ia32/ia32entry.S @@ -279,9 +279,9 @@ ia32_sys_call_table: .quad stub32_sigsuspend .quad compat_sys_sigpending .quad sys_sethostname - .quad sys32_setrlimit /* 75 */ - .quad sys32_old_getrlimit /* old_getrlimit */ - .quad sys32_getrusage + .quad compat_sys_setrlimit /* 75 */ + .quad compat_sys_old_getrlimit /* old_getrlimit */ + .quad compat_sys_getrusage .quad sys32_gettimeofday .quad sys32_settimeofday .quad sys_getgroups16 /* 80 */ @@ -318,7 +318,7 @@ ia32_sys_call_table: .quad sys_vhangup .quad ni_syscall /* old "idle" system call */ .quad sys32_vm86_warning /* vm86old */ - .quad sys32_wait4 + .quad compat_sys_wait4 .quad sys_swapoff /* 115 */ .quad sys32_sysinfo .quad sys32_ipc @@ -395,7 +395,7 @@ ia32_sys_call_table: .quad ni_syscall /* streams1 */ .quad ni_syscall /* streams2 */ .quad stub32_vfork /* 190 */ - .quad sys32_getrlimit + .quad compat_sys_getrlimit .quad sys32_mmap2 .quad sys_truncate .quad sys_ftruncate diff --git a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c index 40a88a198c317..292936f958f05 100644 --- a/arch/x86_64/ia32/sys_ia32.c +++ b/arch/x86_64/ia32/sys_ia32.c @@ -836,82 +836,6 @@ sys32_writev(int fd, struct compat_iovec *vector, u32 count) return ret; } -#define RLIM_INFINITY32 0xffffffff -#define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x) - -struct rlimit32 { - int rlim_cur; - int rlim_max; -}; - -extern asmlinkage long sys_getrlimit(unsigned int resource, struct rlimit *rlim); - -asmlinkage long -sys32_getrlimit(unsigned int resource, struct rlimit32 *rlim) -{ - struct rlimit r; - int ret; - mm_segment_t old_fs; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_getrlimit(resource, &r); - set_fs(old_fs); - if (!ret) { - if (verify_area(VERIFY_WRITE, rlim, sizeof(struct rlimit32)) || - __put_user(RESOURCE32(r.rlim_cur), &rlim->rlim_cur) || - __put_user(RESOURCE32(r.rlim_max), &rlim->rlim_max)) - ret = -EFAULT; - } - return ret; -} - -extern asmlinkage long sys_old_getrlimit(unsigned int resource, struct rlimit *rlim); - -asmlinkage long -sys32_old_getrlimit(unsigned int resource, struct rlimit32 *rlim) -{ - struct rlimit r; - int ret; - mm_segment_t old_fs; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_old_getrlimit(resource, &r); - set_fs(old_fs); - if (!ret) { - if (verify_area(VERIFY_WRITE, rlim, sizeof(struct rlimit32)) || - __put_user(r.rlim_cur, &rlim->rlim_cur) || - __put_user(r.rlim_max, &rlim->rlim_max)) - ret = -EFAULT; - } - return ret; -} - -extern asmlinkage long sys_setrlimit(unsigned int resource, struct rlimit *rlim); - -asmlinkage long -sys32_setrlimit(unsigned int resource, struct rlimit32 *rlim) -{ - struct rlimit r; - int ret; - mm_segment_t old_fs = get_fs (); - - if (resource >= RLIM_NLIMITS) return -EINVAL; - if (verify_area(VERIFY_READ, rlim, sizeof(struct rlimit32)) || - __get_user (r.rlim_cur, &rlim->rlim_cur) || - __get_user (r.rlim_max, &rlim->rlim_max)) - return -EFAULT; - if (r.rlim_cur == RLIM_INFINITY32) - r.rlim_cur = RLIM_INFINITY; - if (r.rlim_max == RLIM_INFINITY32) - r.rlim_max = RLIM_INFINITY; - set_fs (KERNEL_DS); - ret = sys_setrlimit(resource, &r); - set_fs (old_fs); - return ret; -} - /* * sys_time() can be implemented in user-level using * sys_gettimeofday(). x86-64 did this but i386 Linux did not @@ -931,80 +855,10 @@ asmlinkage long sys32_time(int * tloc) return i; } -struct rusage32 { - struct compat_timeval ru_utime; - struct compat_timeval ru_stime; - int ru_maxrss; - int ru_ixrss; - int ru_idrss; - int ru_isrss; - int ru_minflt; - int ru_majflt; - int ru_nswap; - int ru_inblock; - int ru_oublock; - int ru_msgsnd; - int ru_msgrcv; - int ru_nsignals; - int ru_nvcsw; - int ru_nivcsw; -}; - -static int -put_rusage (struct rusage32 *ru, struct rusage *r) -{ - if (verify_area(VERIFY_WRITE, ru, sizeof(struct rusage32)) || - __put_user (r->ru_utime.tv_sec, &ru->ru_utime.tv_sec) || - __put_user (r->ru_utime.tv_usec, &ru->ru_utime.tv_usec) || - __put_user (r->ru_stime.tv_sec, &ru->ru_stime.tv_sec) || - __put_user (r->ru_stime.tv_usec, &ru->ru_stime.tv_usec) || - __put_user (r->ru_maxrss, &ru->ru_maxrss) || - __put_user (r->ru_ixrss, &ru->ru_ixrss) || - __put_user (r->ru_idrss, &ru->ru_idrss) || - __put_user (r->ru_isrss, &ru->ru_isrss) || - __put_user (r->ru_minflt, &ru->ru_minflt) || - __put_user (r->ru_majflt, &ru->ru_majflt) || - __put_user (r->ru_nswap, &ru->ru_nswap) || - __put_user (r->ru_inblock, &ru->ru_inblock) || - __put_user (r->ru_oublock, &ru->ru_oublock) || - __put_user (r->ru_msgsnd, &ru->ru_msgsnd) || - __put_user (r->ru_msgrcv, &ru->ru_msgrcv) || - __put_user (r->ru_nsignals, &ru->ru_nsignals) || - __put_user (r->ru_nvcsw, &ru->ru_nvcsw) || - __put_user (r->ru_nivcsw, &ru->ru_nivcsw)) - return -EFAULT; - return 0; -} - -extern asmlinkage long sys_wait4(pid_t pid,unsigned int * stat_addr, - int options, struct rusage * ru); - -asmlinkage long -sys32_wait4(compat_pid_t pid, unsigned int *stat_addr, int options, - struct rusage32 *ru) -{ - if (!ru) - return sys_wait4(pid, stat_addr, options, NULL); - else { - struct rusage r; - int ret; - unsigned int status; - mm_segment_t old_fs = get_fs(); - - set_fs (KERNEL_DS); - ret = sys_wait4(pid, stat_addr ? &status : NULL, options, &r); - set_fs (old_fs); - if (put_rusage (ru, &r)) return -EFAULT; - if (stat_addr && put_user (status, stat_addr)) - return -EFAULT; - return ret; - } -} - asmlinkage long sys32_waitpid(compat_pid_t pid, unsigned int *stat_addr, int options) { - return sys32_wait4(pid, stat_addr, options, NULL); + return compat_sys_wait4(pid, stat_addr, options, NULL); } diff --git a/include/asm-parisc/compat.h b/include/asm-parisc/compat.h index 2940a9757a647..3a3ac178498df 100644 --- a/include/asm-parisc/compat.h +++ b/include/asm-parisc/compat.h @@ -99,6 +99,8 @@ struct compat_statfs { s32 f_spare[6]; }; +#define COMPAT_RLIM_INFINITY 0xffffffff + typedef u32 compat_old_sigset_t; /* at least 32 bits */ #define _COMPAT_NSIG 64 diff --git a/include/asm-ppc64/compat.h b/include/asm-ppc64/compat.h index 4934e9315e761..913cbd936dd94 100644 --- a/include/asm-ppc64/compat.h +++ b/include/asm-ppc64/compat.h @@ -93,6 +93,9 @@ struct compat_statfs { int f_spare[6]; }; +#define COMPAT_RLIM_OLD_INFINITY 0x7fffffff +#define COMPAT_RLIM_INFINITY 0xffffffff + typedef u32 compat_old_sigset_t; #define _COMPAT_NSIG 64 diff --git a/include/asm-s390/compat.h b/include/asm-s390/compat.h index 55966b41d2908..b010629a46e98 100644 --- a/include/asm-s390/compat.h +++ b/include/asm-s390/compat.h @@ -96,6 +96,9 @@ struct compat_statfs { s32 f_spare[6]; }; +#define COMPAT_RLIM_OLD_INFINITY 0x7fffffff +#define COMPAT_RLIM_INFINITY 0xffffffff + typedef u32 compat_old_sigset_t; /* at least 32 bits */ #define _COMPAT_NSIG 64 diff --git a/include/asm-sparc64/compat.h b/include/asm-sparc64/compat.h index dc174a7ef925a..6503e10e5a754 100644 --- a/include/asm-sparc64/compat.h +++ b/include/asm-sparc64/compat.h @@ -95,6 +95,8 @@ struct compat_statfs { int f_spare[6]; }; +#define COMPAT_RLIM_INFINITY 0x7fffffff + typedef u32 compat_old_sigset_t; #define _COMPAT_NSIG 64 diff --git a/include/asm-x86_64/compat.h b/include/asm-x86_64/compat.h index 06c27d32eae52..90265acf71b27 100644 --- a/include/asm-x86_64/compat.h +++ b/include/asm-x86_64/compat.h @@ -102,6 +102,9 @@ struct compat_statfs { int f_spare[6]; }; +#define COMPAT_RLIM_OLD_INFINITY 0x7fffffff +#define COMPAT_RLIM_INFINITY 0xffffffff + typedef u32 compat_old_sigset_t; /* at least 32 bits */ #define _COMPAT_NSIG 64 diff --git a/include/linux/compat.h b/include/linux/compat.h index 305b8f0411a56..bc69ea28d7e98 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -47,5 +47,29 @@ struct compat_iovec { compat_size_t iov_len; }; +struct compat_rlimit { + compat_ulong_t rlim_cur; + compat_ulong_t rlim_max; +}; + +struct compat_rusage { + struct compat_timeval ru_utime; + struct compat_timeval ru_stime; + compat_long_t ru_maxrss; + compat_long_t ru_ixrss; + compat_long_t ru_idrss; + compat_long_t ru_isrss; + compat_long_t ru_minflt; + compat_long_t ru_majflt; + compat_long_t ru_nswap; + compat_long_t ru_inblock; + compat_long_t ru_oublock; + compat_long_t ru_msgsnd; + compat_long_t ru_msgrcv; + compat_long_t ru_nsignals; + compat_long_t ru_nvcsw; + compat_long_t ru_nivcsw; +}; + #endif /* CONFIG_COMPAT */ #endif /* _LINUX_COMPAT_H */ diff --git a/kernel/compat.c b/kernel/compat.c index 13ab289c0fc5d..0dcab5fc6acd8 100644 --- a/kernel/compat.c +++ b/kernel/compat.c @@ -227,6 +227,152 @@ asmlinkage long compat_sys_futex(u32 *uaddr, int op, int val, return do_futex((unsigned long)uaddr, op, val, timeout); } +asmlinkage long sys_setrlimit(unsigned int resource, struct rlimit *rlim); + +asmlinkage long compat_sys_setrlimit(unsigned int resource, struct compat_rlimit *rlim) +{ + struct rlimit r; + int ret; + mm_segment_t old_fs = get_fs (); + + if (resource >= RLIM_NLIMITS) + return -EINVAL; + + if (!access_ok(VERIFY_READ, rlim, sizeof(*rlim)) || + __get_user(r.rlim_cur, &rlim->rlim_cur) || + __get_user(r.rlim_max, &rlim->rlim_max)) + return -EFAULT; + + if (r.rlim_cur == COMPAT_RLIM_INFINITY) + r.rlim_cur = RLIM_INFINITY; + if (r.rlim_max == COMPAT_RLIM_INFINITY) + r.rlim_max = RLIM_INFINITY; + set_fs(KERNEL_DS); + ret = sys_setrlimit(resource, &r); + set_fs(old_fs); + return ret; +} + +#ifdef COMPAT_RLIM_OLD_INFINITY +asmlinkage long sys_old_getrlimit(unsigned int resource, struct rlimit *rlim); + +asmlinkage long compat_sys_old_getrlimit(unsigned int resource, struct compat_rlimit *rlim) +{ + struct rlimit r; + int ret; + mm_segment_t old_fs = get_fs(); + + set_fs(KERNEL_DS); + ret = sys_old_getrlimit(resource, &r); + set_fs(old_fs); + + if (!ret) { + if (r.rlim_cur > COMPAT_RLIM_OLD_INFINITY) + r.rlim_cur = COMPAT_RLIM_INFINITY; + if (r.rlim_max > COMPAT_RLIM_OLD_INFINITY) + r.rlim_max = COMPAT_RLIM_INFINITY; + + if (!access_ok(VERIFY_WRITE, rlim, sizeof(*rlim)) || + __put_user(r.rlim_cur, &rlim->rlim_cur) || + __put_user(r.rlim_max, &rlim->rlim_max)) + return -EFAULT; + } + return ret; +} +#endif + +asmlinkage long sys_getrlimit (unsigned int resource, struct rlimit *rlim); + +asmlinkage long compat_sys_getrlimit (unsigned int resource, struct compat_rlimit *rlim) +{ + struct rlimit r; + int ret; + mm_segment_t old_fs = get_fs(); + + set_fs(KERNEL_DS); + ret = sys_getrlimit(resource, &r); + set_fs(old_fs); + if (!ret) { + if (r.rlim_cur > COMPAT_RLIM_INFINITY) + r.rlim_cur = COMPAT_RLIM_INFINITY; + if (r.rlim_max > COMPAT_RLIM_INFINITY) + r.rlim_max = COMPAT_RLIM_INFINITY; + + if (!access_ok(VERIFY_WRITE, rlim, sizeof(*rlim)) || + __put_user(r.rlim_cur, &rlim->rlim_cur) || + __put_user(r.rlim_max, &rlim->rlim_max)) + return -EFAULT; + } + return ret; +} + +static long put_compat_rusage (struct compat_rusage *ru, struct rusage *r) +{ + if (!access_ok(VERIFY_WRITE, ru, sizeof(*ru)) || + __put_user(r->ru_utime.tv_sec, &ru->ru_utime.tv_sec) || + __put_user(r->ru_utime.tv_usec, &ru->ru_utime.tv_usec) || + __put_user(r->ru_stime.tv_sec, &ru->ru_stime.tv_sec) || + __put_user(r->ru_stime.tv_usec, &ru->ru_stime.tv_usec) || + __put_user(r->ru_maxrss, &ru->ru_maxrss) || + __put_user(r->ru_ixrss, &ru->ru_ixrss) || + __put_user(r->ru_idrss, &ru->ru_idrss) || + __put_user(r->ru_isrss, &ru->ru_isrss) || + __put_user(r->ru_minflt, &ru->ru_minflt) || + __put_user(r->ru_majflt, &ru->ru_majflt) || + __put_user(r->ru_nswap, &ru->ru_nswap) || + __put_user(r->ru_inblock, &ru->ru_inblock) || + __put_user(r->ru_oublock, &ru->ru_oublock) || + __put_user(r->ru_msgsnd, &ru->ru_msgsnd) || + __put_user(r->ru_msgrcv, &ru->ru_msgrcv) || + __put_user(r->ru_nsignals, &ru->ru_nsignals) || + __put_user(r->ru_nvcsw, &ru->ru_nvcsw) || + __put_user(r->ru_nivcsw, &ru->ru_nivcsw)) + return -EFAULT; + return 0; +} + +asmlinkage long sys_getrusage(int who, struct rusage *ru); + +asmlinkage long compat_sys_getrusage(int who, struct compat_rusage *ru) +{ + struct rusage r; + int ret; + mm_segment_t old_fs = get_fs(); + + set_fs(KERNEL_DS); + ret = sys_getrusage(who, &r); + set_fs(old_fs); + + return ret || put_compat_rusage(ru, &r); +} + +asmlinkage long +compat_sys_wait4(compat_pid_t pid, compat_uint_t * stat_addr, int options, + struct compat_rusage *ru) +{ + if (!ru) { + return sys_wait4(pid, stat_addr, options, NULL); + } else { + struct rusage r; + int ret; + unsigned int status; + mm_segment_t old_fs = get_fs(); + + set_fs (KERNEL_DS); + ret = sys_wait4(pid, stat_addr ? &status : NULL, options, &r); + set_fs (old_fs); + + if (!ret) + { + if (put_compat_rusage(ru, &r)) + return -EFAULT; + if (stat_addr && put_user(status, stat_addr)) + return -EFAULT; + } + return ret; + } +} + extern asmlinkage long sys_sched_setaffinity(pid_t pid, unsigned int len, unsigned long *user_mask_ptr); -- 2.53.0