compa

parent 7e4b1fa1
......@@ -210,7 +210,7 @@
199 common fremovexattr __x64_sys_fremovexattr
200 common tkill __x64_sys_tkill
201 common time __x64_sys_time
202 common futex __x64_sys_futex
202 64 futex __x64_sys_futex
203 common sched_setaffinity __x64_sys_sched_setaffinity
204 common sched_getaffinity __x64_sys_sched_getaffinity
205 64 set_thread_area
......@@ -400,3 +400,4 @@
545 x32 execveat __x32_compat_sys_execveat/ptregs
546 x32 preadv2 __x32_compat_sys_preadv64v2
547 x32 pwritev2 __x32_compat_sys_pwritev64v2
548 x32 futex __x32_compat_sys_futex
\ No newline at end of file
......@@ -381,6 +381,12 @@ struct compat_robust_list_head {
compat_uptr_t list_op_pending;
};
struct compat_futex_wait_block {
compat_uptr_t uaddr;
__u32 val;
__u32 bitset;
};
#ifdef CONFIG_COMPAT_OLD_SIGACTION
struct compat_old_sigaction {
compat_uptr_t sa_handler;
......@@ -665,6 +671,10 @@ compat_sys_set_robust_list(struct compat_robust_list_head __user *head,
asmlinkage long
compat_sys_get_robust_list(int pid, compat_uptr_t __user *head_ptr,
compat_size_t __user *len_ptr);
asmlinkage long
compat_sys_futex(u32 __user * uaddr, int op, u32 val,
struct __kernel_timespec __user * utime,
u32 __user *uaddr2, u32 val3);
/* kernel/itimer.c */
asmlinkage long compat_sys_getitimer(int which,
......
......@@ -819,7 +819,7 @@ __SYSCALL(__NR_semtimedop_time64, sys_semtimedop)
#define __NR_rt_sigtimedwait_time64 421
__SC_COMP(__NR_rt_sigtimedwait_time64, sys_rt_sigtimedwait, compat_sys_rt_sigtimedwait_time64)
#define __NR_futex_time64 422
__SYSCALL(__NR_futex_time64, sys_futex)
__SC_COMP(__NR_futex_time64, sys_futex, compat_sys_futex)
#define __NR_sched_rr_get_interval_time64 423
__SYSCALL(__NR_sched_rr_get_interval_time64, sys_sched_rr_get_interval)
#endif
......
......@@ -2892,19 +2892,21 @@ static int futex_wait_multiple(u32 __user *uaddr, unsigned int flags,
__set_current_state(TASK_RUNNING);
if (ret < 0) {
if (to && !to->task) {
ret = -ETIMEDOUT;
break;
} else if (signal_pending(current)) {
ret = -ERESTARTSYS;
break;
}
/*
* The final case is a spurious wakeup, for
* which we can just retry.
*/
if (ret >= 0)
break;
if (to && !to->task) {
ret = -ETIMEDOUT;
break;
} else if (signal_pending(current)) {
ret = -ERESTARTSYS;
break;
}
/*
* There is one more error case here, which indicates a
* spurious wakeup, but for that case, we can just let
* the loop retry.
*/
} while (ret < 0);
if (to) {
......@@ -3882,10 +3884,9 @@ long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout,
return -ENOSYS;
}
SYSCALL_DEFINE6(futex, u32 __user *, uaddr, int, op, u32, val,
struct __kernel_timespec __user *, utime, u32 __user *, uaddr2,
u32, val3)
long ksys_futex(u32 __user *uaddr, int op, u32 val,
struct __kernel_timespec __user *utime,
u32 __user *uaddr2, u32 val3)
{
struct timespec64 ts;
ktime_t t, *tp = NULL;
......@@ -3919,13 +3920,51 @@ SYSCALL_DEFINE6(futex, u32 __user *, uaddr, int, op, u32, val,
return do_futex(uaddr, op, val, tp, uaddr2, val2, val3);
}
struct futex_q *futex_read_wait_block(u32 __user *uaddr, u32 count)
{
struct futex_q *qs = NULL;
struct futex_wait_block entry, *fwb;
int i;
if (!count || count > FUTEX_MULTIPLE_MAX_COUNT)
return ERR_PTR(-EINVAL);
qs = kcalloc(count, sizeof(*qs), GFP_KERNEL);
if (!qs)
return ERR_PTR(-ENOMEM);
fwb = (struct futex_wait_block *) __user uaddr;
for (i = 0; i < count; i++) {
if (copy_from_user(&entry, &fwb[i], sizeof(entry))) {
kfree(qs);
return ERR_PTR(-EFAULT);
}
qs[i].uval = entry.val;
qs[i].uaddr = entry.uaddr;
qs[i].bitset = entry.bitset;
}
return qs;
}
SYSCALL_DEFINE6(futex, u32 __user *, uaddr, int, op, u32, val,
struct __kernel_timespec __user *, utime, u32 __user *, uaddr2,
u32, val3)
{
/* if (op == FUTEX_WAIT_MULTIPLE) { */
/* uaddr = (u32 *) futex_read_wait_block(uaddr, val); */
/* if (IS_ERR(uaddr)) */
/* return PTR_ERR(uaddr); */
/* } */
return ksys_futex(uaddr, op, val, utime, uaddr2, val3);
}
#ifdef CONFIG_COMPAT
/*
* Fetch a robust-list pointer. Bit 0 signals PI futexes:
*/
static inline int
compat_fetch_robust_entry(compat_uptr_t *uentry, struct robust_list __user **entry,
compat_uptr_t __user *head, unsigned int *pi)
compat_uptr_t __user *head, unsigned int *pi)
{
if (get_user(*uentry, head))
return -EFAULT;
......@@ -4074,6 +4113,55 @@ COMPAT_SYSCALL_DEFINE3(get_robust_list, int, pid,
return ret;
}
struct futex_wait_block *compat_futex_read_wait_block(u32 __user *uaddr,
u32 count)
{
int i;
struct futex_wait_block *fwb;
struct compat_futex_wait_block entry;
struct compat_futex_wait_block *compat =
(struct compat_futex_wait_block*) uaddr;
if (!count || count > FUTEX_MULTIPLE_MAX_COUNT)
return ERR_PTR(-EINVAL);
fwb = kcalloc(count, sizeof(*fwb), GFP_KERNEL);
if (!fwb)
return ERR_PTR(-ENOMEM);
for (i = 0; i < count; i++) {
if (copy_from_user(&entry, &compat[i], sizeof(entry))) {
kfree(fwb);
return ERR_PTR(-EFAULT);
}
fwb[i].uaddr = compat_ptr(entry.uaddr);
fwb[i].val = entry.val;
fwb[i].bitset = entry.bitset;
}
return fwb;
}
COMPAT_SYSCALL_DEFINE6(futex, u32 __user *, uaddr, int, op, u32, val,
struct __kernel_timespec __user *, utime, u32 __user *, uaddr2,
u32, val3)
{
int ret;
if (op == FUTEX_WAIT_MULTIPLE) {
struct futex_wait_block *fwb;
fwb = compat_futex_read_wait_block(uaddr, val);
if (IS_ERR(fwb))
return PTR_ERR(fwb);
ret = ksys_futex((u32*) fwb, op, val, utime, uaddr2, val3);
kfree (fwb);
return ret;
}
return ksys_futex(uaddr, op, val, utime, uaddr2, val3);
}
#endif /* CONFIG_COMPAT */
#ifdef CONFIG_COMPAT_32BIT_TIME
......@@ -4083,7 +4171,7 @@ SYSCALL_DEFINE6(futex_time32, u32 __user *, uaddr, int, op, u32, val,
{
struct timespec64 ts;
ktime_t t, *tp = NULL;
int val2 = 0;
int val2 = 0, ret;
int cmd = op & FUTEX_CMD_MASK;
if (utime && (cmd == FUTEX_WAIT || cmd == FUTEX_LOCK_PI ||
......@@ -4104,6 +4192,16 @@ SYSCALL_DEFINE6(futex_time32, u32 __user *, uaddr, int, op, u32, val,
cmd == FUTEX_CMP_REQUEUE_PI || cmd == FUTEX_WAKE_OP)
val2 = (int) (unsigned long) utime;
if (op == FUTEX_WAIT_MULTIPLE) {
struct futex_wait_block *fwb;
fwb = compat_futex_read_wait_block(uaddr, val);
if (IS_ERR(fwb))
return PTR_ERR(fwb);
ret = do_futex((u32*) fwb, op, val, tp, uaddr2, val2, val3);
kfree (fwb);
return ret;
}
return do_futex(uaddr, op, val, tp, uaddr2, val2, val3);
}
#endif /* CONFIG_COMPAT_32BIT_TIME */
......
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