Commit b95baca0 authored by Randolph Chung's avatar Randolph Chung Committed by Linus Torvalds

[PATCH] getrlimit,setrlimit,getrusage,wait4 unification

parent 98af522f
......@@ -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 @@ sys32_readdir (unsigned int fd, void * dirent, unsigned int count)
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;
......
......@@ -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)
......
......@@ -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
......
......@@ -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,
......
......@@ -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);
/*
......
......@@ -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:
......
......@@ -1521,70 +1521,6 @@ asmlinkage int sys32_mount(char *dev_name, char *dir_name, char *type, unsigned
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)
......
......@@ -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
......
......@@ -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
......
......@@ -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);
}
......
......@@ -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
......
......@@ -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
......
......@@ -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
......
......@@ -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
......
......@@ -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
......
......@@ -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 */
......@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment