diff options
Diffstat (limited to 'kernel/sys.c')
| -rw-r--r-- | kernel/sys.c | 116 | 
1 files changed, 105 insertions, 11 deletions
diff --git a/kernel/sys.c b/kernel/sys.c index 8a94b4eabcaa..47d901586b4e 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -886,7 +886,7 @@ SYSCALL_DEFINE0(getegid)  	return from_kgid_munged(current_user_ns(), current_egid());  } -void do_sys_times(struct tms *tms) +static void do_sys_times(struct tms *tms)  {  	u64 tgutime, tgstime, cutime, cstime; @@ -912,6 +912,32 @@ SYSCALL_DEFINE1(times, struct tms __user *, tbuf)  	return (long) jiffies_64_to_clock_t(get_jiffies_64());  } +#ifdef CONFIG_COMPAT +static compat_clock_t clock_t_to_compat_clock_t(clock_t x) +{ +	return compat_jiffies_to_clock_t(clock_t_to_jiffies(x)); +} + +COMPAT_SYSCALL_DEFINE1(times, struct compat_tms __user *, tbuf) +{ +	if (tbuf) { +		struct tms tms; +		struct compat_tms tmp; + +		do_sys_times(&tms); +		/* Convert our struct tms to the compat version. */ +		tmp.tms_utime = clock_t_to_compat_clock_t(tms.tms_utime); +		tmp.tms_stime = clock_t_to_compat_clock_t(tms.tms_stime); +		tmp.tms_cutime = clock_t_to_compat_clock_t(tms.tms_cutime); +		tmp.tms_cstime = clock_t_to_compat_clock_t(tms.tms_cstime); +		if (copy_to_user(tbuf, &tmp, sizeof(tmp))) +			return -EFAULT; +	} +	force_successful_syscall_return(); +	return compat_jiffies_to_clock_t(jiffies); +} +#endif +  /*   * This needs some heavy checking ...   * I just haven't the stomach for it. I also don't fully @@ -1306,6 +1332,54 @@ SYSCALL_DEFINE2(getrlimit, unsigned int, resource, struct rlimit __user *, rlim)  	return ret;  } +#ifdef CONFIG_COMPAT + +COMPAT_SYSCALL_DEFINE2(setrlimit, unsigned int, resource, +		       struct compat_rlimit __user *, rlim) +{ +	struct rlimit r; +	struct compat_rlimit r32; + +	if (copy_from_user(&r32, rlim, sizeof(struct compat_rlimit))) +		return -EFAULT; + +	if (r32.rlim_cur == COMPAT_RLIM_INFINITY) +		r.rlim_cur = RLIM_INFINITY; +	else +		r.rlim_cur = r32.rlim_cur; +	if (r32.rlim_max == COMPAT_RLIM_INFINITY) +		r.rlim_max = RLIM_INFINITY; +	else +		r.rlim_max = r32.rlim_max; +	return do_prlimit(current, resource, &r, NULL); +} + +COMPAT_SYSCALL_DEFINE2(getrlimit, unsigned int, resource, +		       struct compat_rlimit __user *, rlim) +{ +	struct rlimit r; +	int ret; + +	ret = do_prlimit(current, resource, NULL, &r); +	if (!ret) { +		struct rlimit r32; +		if (r.rlim_cur > COMPAT_RLIM_INFINITY) +			r32.rlim_cur = COMPAT_RLIM_INFINITY; +		else +			r32.rlim_cur = r.rlim_cur; +		if (r.rlim_max > COMPAT_RLIM_INFINITY) +			r32.rlim_max = COMPAT_RLIM_INFINITY; +		else +			r32.rlim_max = r.rlim_max; + +		if (copy_to_user(rlim, &r32, sizeof(struct compat_rlimit))) +			return -EFAULT; +	} +	return ret; +} + +#endif +  #ifdef __ARCH_WANT_SYS_OLD_GETRLIMIT  /* @@ -1328,6 +1402,30 @@ SYSCALL_DEFINE2(old_getrlimit, unsigned int, resource,  	return copy_to_user(rlim, &x, sizeof(x)) ? -EFAULT : 0;  } +#ifdef CONFIG_COMPAT +COMPAT_SYSCALL_DEFINE2(old_getrlimit, unsigned int, resource, +		       struct compat_rlimit __user *, rlim) +{ +	struct rlimit r; + +	if (resource >= RLIM_NLIMITS) +		return -EINVAL; + +	task_lock(current->group_leader); +	r = current->signal->rlim[resource]; +	task_unlock(current->group_leader); +	if (r.rlim_cur > 0x7FFFFFFF) +		r.rlim_cur = 0x7FFFFFFF; +	if (r.rlim_max > 0x7FFFFFFF) +		r.rlim_max = 0x7FFFFFFF; + +	if (put_user(r.rlim_cur, &rlim->rlim_cur) || +	    put_user(r.rlim_max, &rlim->rlim_max)) +		return -EFAULT; +	return 0; +} +#endif +  #endif  static inline bool rlim64_is_infinity(__u64 rlim64) @@ -1552,7 +1650,7 @@ static void accumulate_thread_rusage(struct task_struct *t, struct rusage *r)  	r->ru_oublock += task_io_get_oublock(t);  } -static void k_getrusage(struct task_struct *p, int who, struct rusage *r) +void getrusage(struct task_struct *p, int who, struct rusage *r)  {  	struct task_struct *t;  	unsigned long flags; @@ -1626,20 +1724,16 @@ out:  	r->ru_maxrss = maxrss * (PAGE_SIZE / 1024); /* convert pages to KBs */  } -int getrusage(struct task_struct *p, int who, struct rusage __user *ru) +SYSCALL_DEFINE2(getrusage, int, who, struct rusage __user *, ru)  {  	struct rusage r; -	k_getrusage(p, who, &r); -	return copy_to_user(ru, &r, sizeof(r)) ? -EFAULT : 0; -} - -SYSCALL_DEFINE2(getrusage, int, who, struct rusage __user *, ru) -{  	if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN &&  	    who != RUSAGE_THREAD)  		return -EINVAL; -	return getrusage(current, who, ru); + +	getrusage(current, who, &r); +	return copy_to_user(ru, &r, sizeof(r)) ? -EFAULT : 0;  }  #ifdef CONFIG_COMPAT @@ -1651,7 +1745,7 @@ COMPAT_SYSCALL_DEFINE2(getrusage, int, who, struct compat_rusage __user *, ru)  	    who != RUSAGE_THREAD)  		return -EINVAL; -	k_getrusage(current, who, &r); +	getrusage(current, who, &r);  	return put_compat_rusage(&r, ru);  }  #endif  |