Merge branch 'misc.compat' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull misc compat stuff updates from Al Viro:
"This part is basically untangling various compat stuff. Compat
syscalls moved to their native counterparts, getting rid of quite a
bit of double-copying and/or set_fs() uses. A lot of field-by-field
copyin/copyout killed off.
- kernel/compat.c is much closer to containing just the
copyin/copyout of compat structs. Not all compat syscalls are gone
from it yet, but it's getting there.
- ipc/compat_mq.c killed off completely.
- block/compat_ioctl.c cleaned up; floppy compat ioctls moved to
drivers/block/floppy.c where they belong. Yes, there are several
drivers that implement some of the same ioctls. Some are m68k and
one is 32bit-only pmac. drivers/block/floppy.c is the only one in
that bunch that can be built on biarch"
* 'misc.compat' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
mqueue: move compat syscalls to native ones
usbdevfs: get rid of field-by-field copyin
compat_hdio_ioctl: get rid of set_fs()
take floppy compat ioctls to sodding floppy.c
ipmi: get rid of field-by-field __get_user()
ipmi: get COMPAT_IPMICTL_RECEIVE_MSG in sync with the native one
rt_sigtimedwait(): move compat to native
select: switch compat_{get,put}_fd_set() to compat_{get,put}_bitmap()
put_compat_rusage(): switch to copy_to_user()
sigpending(): move compat to native
getrlimit()/setrlimit(): move compat to native
times(2): move compat to native
compat_{get,put}_bitmap(): use unsafe_{get,put}_user()
fb_get_fscreeninfo(): don't bother with do_fb_ioctl()
do_sigaltstack(): lift copying to/from userland into callers
take compat_sys_old_getrlimit() to native syscall
trim __ARCH_WANT_SYS_OLD_GETRLIMIT
This commit is contained in:
+49
-218
@@ -247,53 +247,6 @@ int put_compat_itimerval(struct compat_itimerval __user *o, const struct itimerv
|
||||
return copy_to_user(o, &v32, sizeof(struct compat_itimerval)) ? -EFAULT : 0;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
#ifdef __ARCH_WANT_SYS_SIGPENDING
|
||||
|
||||
/*
|
||||
* Assumption: old_sigset_t and compat_old_sigset_t are both
|
||||
* types that can be passed to put_user()/get_user().
|
||||
*/
|
||||
|
||||
COMPAT_SYSCALL_DEFINE1(sigpending, compat_old_sigset_t __user *, set)
|
||||
{
|
||||
old_sigset_t s;
|
||||
long ret;
|
||||
mm_segment_t old_fs = get_fs();
|
||||
|
||||
set_fs(KERNEL_DS);
|
||||
ret = sys_sigpending((old_sigset_t __user *) &s);
|
||||
set_fs(old_fs);
|
||||
if (ret == 0)
|
||||
ret = put_user(s, set);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __ARCH_WANT_SYS_SIGPROCMASK
|
||||
|
||||
/*
|
||||
@@ -348,94 +301,29 @@ COMPAT_SYSCALL_DEFINE3(sigprocmask, int, how,
|
||||
|
||||
#endif
|
||||
|
||||
COMPAT_SYSCALL_DEFINE2(setrlimit, unsigned int, resource,
|
||||
struct compat_rlimit __user *, rlim)
|
||||
{
|
||||
struct rlimit r;
|
||||
|
||||
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;
|
||||
return do_prlimit(current, resource, &r, NULL);
|
||||
}
|
||||
|
||||
#ifdef COMPAT_RLIM_OLD_INFINITY
|
||||
|
||||
COMPAT_SYSCALL_DEFINE2(old_getrlimit, unsigned int, resource,
|
||||
struct compat_rlimit __user *, rlim)
|
||||
{
|
||||
struct rlimit r;
|
||||
int ret;
|
||||
mm_segment_t old_fs = get_fs();
|
||||
|
||||
set_fs(KERNEL_DS);
|
||||
ret = sys_old_getrlimit(resource, (struct rlimit __user *)&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
|
||||
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
|
||||
int put_compat_rusage(const struct rusage *r, struct compat_rusage __user *ru)
|
||||
{
|
||||
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))
|
||||
struct compat_rusage r32;
|
||||
memset(&r32, 0, sizeof(r32));
|
||||
r32.ru_utime.tv_sec = r->ru_utime.tv_sec;
|
||||
r32.ru_utime.tv_usec = r->ru_utime.tv_usec;
|
||||
r32.ru_stime.tv_sec = r->ru_stime.tv_sec;
|
||||
r32.ru_stime.tv_usec = r->ru_stime.tv_usec;
|
||||
r32.ru_maxrss = r->ru_maxrss;
|
||||
r32.ru_ixrss = r->ru_ixrss;
|
||||
r32.ru_idrss = r->ru_idrss;
|
||||
r32.ru_isrss = r->ru_isrss;
|
||||
r32.ru_minflt = r->ru_minflt;
|
||||
r32.ru_majflt = r->ru_majflt;
|
||||
r32.ru_nswap = r->ru_nswap;
|
||||
r32.ru_inblock = r->ru_inblock;
|
||||
r32.ru_oublock = r->ru_oublock;
|
||||
r32.ru_msgsnd = r->ru_msgsnd;
|
||||
r32.ru_msgrcv = r->ru_msgrcv;
|
||||
r32.ru_nsignals = r->ru_nsignals;
|
||||
r32.ru_nvcsw = r->ru_nvcsw;
|
||||
r32.ru_nivcsw = r->ru_nivcsw;
|
||||
if (copy_to_user(ru, &r32, sizeof(r32)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
@@ -565,84 +453,59 @@ int get_compat_sigevent(struct sigevent *event,
|
||||
long compat_get_bitmap(unsigned long *mask, const compat_ulong_t __user *umask,
|
||||
unsigned long bitmap_size)
|
||||
{
|
||||
int i, j;
|
||||
unsigned long m;
|
||||
compat_ulong_t um;
|
||||
unsigned long nr_compat_longs;
|
||||
|
||||
/* align bitmap up to nearest compat_long_t boundary */
|
||||
bitmap_size = ALIGN(bitmap_size, BITS_PER_COMPAT_LONG);
|
||||
nr_compat_longs = BITS_TO_COMPAT_LONGS(bitmap_size);
|
||||
|
||||
if (!access_ok(VERIFY_READ, umask, bitmap_size / 8))
|
||||
return -EFAULT;
|
||||
|
||||
nr_compat_longs = BITS_TO_COMPAT_LONGS(bitmap_size);
|
||||
|
||||
for (i = 0; i < BITS_TO_LONGS(bitmap_size); i++) {
|
||||
m = 0;
|
||||
|
||||
for (j = 0; j < sizeof(m)/sizeof(um); j++) {
|
||||
/*
|
||||
* We dont want to read past the end of the userspace
|
||||
* bitmap. We must however ensure the end of the
|
||||
* kernel bitmap is zeroed.
|
||||
*/
|
||||
if (nr_compat_longs) {
|
||||
nr_compat_longs--;
|
||||
if (__get_user(um, umask))
|
||||
return -EFAULT;
|
||||
} else {
|
||||
um = 0;
|
||||
}
|
||||
|
||||
umask++;
|
||||
m |= (long)um << (j * BITS_PER_COMPAT_LONG);
|
||||
}
|
||||
*mask++ = m;
|
||||
user_access_begin();
|
||||
while (nr_compat_longs > 1) {
|
||||
compat_ulong_t l1, l2;
|
||||
unsafe_get_user(l1, umask++, Efault);
|
||||
unsafe_get_user(l2, umask++, Efault);
|
||||
*mask++ = ((unsigned long)l2 << BITS_PER_COMPAT_LONG) | l1;
|
||||
nr_compat_longs -= 2;
|
||||
}
|
||||
|
||||
if (nr_compat_longs)
|
||||
unsafe_get_user(*mask, umask++, Efault);
|
||||
user_access_end();
|
||||
return 0;
|
||||
|
||||
Efault:
|
||||
user_access_end();
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
long compat_put_bitmap(compat_ulong_t __user *umask, unsigned long *mask,
|
||||
unsigned long bitmap_size)
|
||||
{
|
||||
int i, j;
|
||||
unsigned long m;
|
||||
compat_ulong_t um;
|
||||
unsigned long nr_compat_longs;
|
||||
|
||||
/* align bitmap up to nearest compat_long_t boundary */
|
||||
bitmap_size = ALIGN(bitmap_size, BITS_PER_COMPAT_LONG);
|
||||
nr_compat_longs = BITS_TO_COMPAT_LONGS(bitmap_size);
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, umask, bitmap_size / 8))
|
||||
return -EFAULT;
|
||||
|
||||
nr_compat_longs = BITS_TO_COMPAT_LONGS(bitmap_size);
|
||||
|
||||
for (i = 0; i < BITS_TO_LONGS(bitmap_size); i++) {
|
||||
m = *mask++;
|
||||
|
||||
for (j = 0; j < sizeof(m)/sizeof(um); j++) {
|
||||
um = m;
|
||||
|
||||
/*
|
||||
* We dont want to write past the end of the userspace
|
||||
* bitmap.
|
||||
*/
|
||||
if (nr_compat_longs) {
|
||||
nr_compat_longs--;
|
||||
if (__put_user(um, umask))
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
umask++;
|
||||
m >>= 4*sizeof(um);
|
||||
m >>= 4*sizeof(um);
|
||||
}
|
||||
user_access_begin();
|
||||
while (nr_compat_longs > 1) {
|
||||
unsigned long m = *mask++;
|
||||
unsafe_put_user((compat_ulong_t)m, umask++, Efault);
|
||||
unsafe_put_user(m >> BITS_PER_COMPAT_LONG, umask++, Efault);
|
||||
nr_compat_longs -= 2;
|
||||
}
|
||||
|
||||
if (nr_compat_longs)
|
||||
unsafe_put_user((compat_ulong_t)*mask, umask++, Efault);
|
||||
user_access_end();
|
||||
return 0;
|
||||
Efault:
|
||||
user_access_end();
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -668,38 +531,6 @@ sigset_to_compat(compat_sigset_t *compat, const sigset_t *set)
|
||||
}
|
||||
}
|
||||
|
||||
COMPAT_SYSCALL_DEFINE4(rt_sigtimedwait, compat_sigset_t __user *, uthese,
|
||||
struct compat_siginfo __user *, uinfo,
|
||||
struct compat_timespec __user *, uts, compat_size_t, sigsetsize)
|
||||
{
|
||||
compat_sigset_t s32;
|
||||
sigset_t s;
|
||||
struct timespec t;
|
||||
siginfo_t info;
|
||||
long ret;
|
||||
|
||||
if (sigsetsize != sizeof(sigset_t))
|
||||
return -EINVAL;
|
||||
|
||||
if (copy_from_user(&s32, uthese, sizeof(compat_sigset_t)))
|
||||
return -EFAULT;
|
||||
sigset_from_compat(&s, &s32);
|
||||
|
||||
if (uts) {
|
||||
if (compat_get_timespec(&t, uts))
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
ret = do_sigtimedwait(&s, &info, uts ? &t : NULL);
|
||||
|
||||
if (ret > 0 && uinfo) {
|
||||
if (copy_siginfo_to_user32(uinfo, &info))
|
||||
ret = -EFAULT;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NUMA
|
||||
COMPAT_SYSCALL_DEFINE6(move_pages, pid_t, pid, compat_ulong_t, nr_pages,
|
||||
compat_uptr_t __user *, pages32,
|
||||
|
||||
+93
-62
@@ -2776,7 +2776,7 @@ int copy_siginfo_to_user(siginfo_t __user *to, const siginfo_t *from)
|
||||
* @info: if non-null, the signal's siginfo is returned here
|
||||
* @ts: upper bound on process time suspension
|
||||
*/
|
||||
int do_sigtimedwait(const sigset_t *which, siginfo_t *info,
|
||||
static int do_sigtimedwait(const sigset_t *which, siginfo_t *info,
|
||||
const struct timespec *ts)
|
||||
{
|
||||
ktime_t *to = NULL, timeout = KTIME_MAX;
|
||||
@@ -2865,6 +2865,40 @@ SYSCALL_DEFINE4(rt_sigtimedwait, const sigset_t __user *, uthese,
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
COMPAT_SYSCALL_DEFINE4(rt_sigtimedwait, compat_sigset_t __user *, uthese,
|
||||
struct compat_siginfo __user *, uinfo,
|
||||
struct compat_timespec __user *, uts, compat_size_t, sigsetsize)
|
||||
{
|
||||
compat_sigset_t s32;
|
||||
sigset_t s;
|
||||
struct timespec t;
|
||||
siginfo_t info;
|
||||
long ret;
|
||||
|
||||
if (sigsetsize != sizeof(sigset_t))
|
||||
return -EINVAL;
|
||||
|
||||
if (copy_from_user(&s32, uthese, sizeof(compat_sigset_t)))
|
||||
return -EFAULT;
|
||||
sigset_from_compat(&s, &s32);
|
||||
|
||||
if (uts) {
|
||||
if (compat_get_timespec(&t, uts))
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
ret = do_sigtimedwait(&s, &info, uts ? &t : NULL);
|
||||
|
||||
if (ret > 0 && uinfo) {
|
||||
if (copy_siginfo_to_user32(uinfo, &info))
|
||||
ret = -EFAULT;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* sys_kill - send a signal to a process
|
||||
* @pid: the PID of the process
|
||||
@@ -3121,78 +3155,68 @@ int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact)
|
||||
}
|
||||
|
||||
static int
|
||||
do_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, unsigned long sp)
|
||||
do_sigaltstack (const stack_t *ss, stack_t *oss, unsigned long sp)
|
||||
{
|
||||
stack_t oss;
|
||||
int error;
|
||||
struct task_struct *t = current;
|
||||
|
||||
oss.ss_sp = (void __user *) current->sas_ss_sp;
|
||||
oss.ss_size = current->sas_ss_size;
|
||||
oss.ss_flags = sas_ss_flags(sp) |
|
||||
(current->sas_ss_flags & SS_FLAG_BITS);
|
||||
if (oss) {
|
||||
memset(oss, 0, sizeof(stack_t));
|
||||
oss->ss_sp = (void __user *) t->sas_ss_sp;
|
||||
oss->ss_size = t->sas_ss_size;
|
||||
oss->ss_flags = sas_ss_flags(sp) |
|
||||
(current->sas_ss_flags & SS_FLAG_BITS);
|
||||
}
|
||||
|
||||
if (uss) {
|
||||
void __user *ss_sp;
|
||||
size_t ss_size;
|
||||
unsigned ss_flags;
|
||||
if (ss) {
|
||||
void __user *ss_sp = ss->ss_sp;
|
||||
size_t ss_size = ss->ss_size;
|
||||
unsigned ss_flags = ss->ss_flags;
|
||||
int ss_mode;
|
||||
|
||||
error = -EFAULT;
|
||||
if (!access_ok(VERIFY_READ, uss, sizeof(*uss)))
|
||||
goto out;
|
||||
error = __get_user(ss_sp, &uss->ss_sp) |
|
||||
__get_user(ss_flags, &uss->ss_flags) |
|
||||
__get_user(ss_size, &uss->ss_size);
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
error = -EPERM;
|
||||
if (on_sig_stack(sp))
|
||||
goto out;
|
||||
if (unlikely(on_sig_stack(sp)))
|
||||
return -EPERM;
|
||||
|
||||
ss_mode = ss_flags & ~SS_FLAG_BITS;
|
||||
error = -EINVAL;
|
||||
if (ss_mode != SS_DISABLE && ss_mode != SS_ONSTACK &&
|
||||
ss_mode != 0)
|
||||
goto out;
|
||||
if (unlikely(ss_mode != SS_DISABLE && ss_mode != SS_ONSTACK &&
|
||||
ss_mode != 0))
|
||||
return -EINVAL;
|
||||
|
||||
if (ss_mode == SS_DISABLE) {
|
||||
ss_size = 0;
|
||||
ss_sp = NULL;
|
||||
} else {
|
||||
error = -ENOMEM;
|
||||
if (ss_size < MINSIGSTKSZ)
|
||||
goto out;
|
||||
if (unlikely(ss_size < MINSIGSTKSZ))
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
current->sas_ss_sp = (unsigned long) ss_sp;
|
||||
current->sas_ss_size = ss_size;
|
||||
current->sas_ss_flags = ss_flags;
|
||||
t->sas_ss_sp = (unsigned long) ss_sp;
|
||||
t->sas_ss_size = ss_size;
|
||||
t->sas_ss_flags = ss_flags;
|
||||
}
|
||||
|
||||
error = 0;
|
||||
if (uoss) {
|
||||
error = -EFAULT;
|
||||
if (!access_ok(VERIFY_WRITE, uoss, sizeof(*uoss)))
|
||||
goto out;
|
||||
error = __put_user(oss.ss_sp, &uoss->ss_sp) |
|
||||
__put_user(oss.ss_size, &uoss->ss_size) |
|
||||
__put_user(oss.ss_flags, &uoss->ss_flags);
|
||||
}
|
||||
|
||||
out:
|
||||
return error;
|
||||
return 0;
|
||||
}
|
||||
|
||||
SYSCALL_DEFINE2(sigaltstack,const stack_t __user *,uss, stack_t __user *,uoss)
|
||||
{
|
||||
return do_sigaltstack(uss, uoss, current_user_stack_pointer());
|
||||
stack_t new, old;
|
||||
int err;
|
||||
if (uss && copy_from_user(&new, uss, sizeof(stack_t)))
|
||||
return -EFAULT;
|
||||
err = do_sigaltstack(uss ? &new : NULL, uoss ? &old : NULL,
|
||||
current_user_stack_pointer());
|
||||
if (!err && uoss && copy_to_user(uoss, &old, sizeof(stack_t)))
|
||||
err = -EFAULT;
|
||||
return err;
|
||||
}
|
||||
|
||||
int restore_altstack(const stack_t __user *uss)
|
||||
{
|
||||
int err = do_sigaltstack(uss, NULL, current_user_stack_pointer());
|
||||
stack_t new;
|
||||
if (copy_from_user(&new, uss, sizeof(stack_t)))
|
||||
return -EFAULT;
|
||||
(void)do_sigaltstack(&new, NULL, current_user_stack_pointer());
|
||||
/* squash all but EFAULT for now */
|
||||
return err == -EFAULT ? err : 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __save_altstack(stack_t __user *uss, unsigned long sp)
|
||||
@@ -3215,29 +3239,24 @@ COMPAT_SYSCALL_DEFINE2(sigaltstack,
|
||||
{
|
||||
stack_t uss, uoss;
|
||||
int ret;
|
||||
mm_segment_t seg;
|
||||
|
||||
if (uss_ptr) {
|
||||
compat_stack_t uss32;
|
||||
|
||||
memset(&uss, 0, sizeof(stack_t));
|
||||
if (copy_from_user(&uss32, uss_ptr, sizeof(compat_stack_t)))
|
||||
return -EFAULT;
|
||||
uss.ss_sp = compat_ptr(uss32.ss_sp);
|
||||
uss.ss_flags = uss32.ss_flags;
|
||||
uss.ss_size = uss32.ss_size;
|
||||
}
|
||||
seg = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
ret = do_sigaltstack((stack_t __force __user *) (uss_ptr ? &uss : NULL),
|
||||
(stack_t __force __user *) &uoss,
|
||||
ret = do_sigaltstack(uss_ptr ? &uss : NULL, &uoss,
|
||||
compat_user_stack_pointer());
|
||||
set_fs(seg);
|
||||
if (ret >= 0 && uoss_ptr) {
|
||||
if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(compat_stack_t)) ||
|
||||
__put_user(ptr_to_compat(uoss.ss_sp), &uoss_ptr->ss_sp) ||
|
||||
__put_user(uoss.ss_flags, &uoss_ptr->ss_flags) ||
|
||||
__put_user(uoss.ss_size, &uoss_ptr->ss_size))
|
||||
compat_stack_t old;
|
||||
memset(&old, 0, sizeof(old));
|
||||
old.ss_sp = ptr_to_compat(uoss.ss_sp);
|
||||
old.ss_flags = uoss.ss_flags;
|
||||
old.ss_size = uoss.ss_size;
|
||||
if (copy_to_user(uoss_ptr, &old, sizeof(compat_stack_t)))
|
||||
ret = -EFAULT;
|
||||
}
|
||||
return ret;
|
||||
@@ -3277,6 +3296,18 @@ SYSCALL_DEFINE1(sigpending, old_sigset_t __user *, set)
|
||||
return sys_rt_sigpending((sigset_t __user *)set, sizeof(old_sigset_t));
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
COMPAT_SYSCALL_DEFINE1(sigpending, compat_old_sigset_t __user *, set32)
|
||||
{
|
||||
sigset_t set;
|
||||
int err = do_sigpending(&set, sizeof(old_sigset_t));
|
||||
if (err == 0)
|
||||
if (copy_to_user(set32, &set, sizeof(old_sigset_t)))
|
||||
err = -EFAULT;
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __ARCH_WANT_SYS_SIGPROCMASK
|
||||
|
||||
+99
-1
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user