89 lines
2.5 KiB
Diff
89 lines
2.5 KiB
Diff
diff --git a/include/uapi/linux/futex.h b/include/uapi/linux/futex.h
|
|
--- a/include/uapi/linux/futex.h
|
|
+++ b/include/uapi/linux/futex.h
|
|
@@ -134,7 +134,7 @@
|
|
* @bitset: Bitset for the optional bitmasked wakeup
|
|
*/
|
|
struct futex_wait_block {
|
|
- __u32 __user *uaddr;
|
|
+ __aligned_u64 uaddr;
|
|
__u32 val;
|
|
__u32 bitset;
|
|
};
|
|
diff --git a/kernel/futex/syscalls.c b/kernel/futex/syscalls.c
|
|
--- a/kernel/futex/syscalls.c
|
|
+++ b/kernel/futex/syscalls.c
|
|
@@ -198,7 +198,8 @@
|
|
* initialize the fields) and then, for each futex_wait_block element from
|
|
* userspace, fill a futex_q element with proper values.
|
|
*/
|
|
-static inline struct futex_vector *futex_read_wait_block(u32 __user *uaddr, u32 count)
|
|
+static inline struct futex_vector *futex_read_wait_block(u32 __user *uaddr, u32 count,
|
|
+ unsigned int flags)
|
|
{
|
|
unsigned int i;
|
|
struct futex_vector *futexv;
|
|
@@ -219,10 +220,17 @@
|
|
return ERR_PTR(-EFAULT);
|
|
}
|
|
|
|
- futexv[i].w.flags = FUTEX_32;
|
|
+ if (!fwb.bitset) {
|
|
+ kfree(futexv);
|
|
+ return ERR_PTR(-EINVAL);
|
|
+ }
|
|
+
|
|
+ futexv[i].w.flags = flags;
|
|
futexv[i].w.val = fwb.val;
|
|
- futexv[i].w.uaddr = (uintptr_t) (fwb.uaddr);
|
|
+ futexv[i].w.uaddr = fwb.uaddr;
|
|
futexv[i].q = futex_q_init;
|
|
+ futexv[i].q.bitset = fwb.bitset;
|
|
+ futexv[i].q.wake = futex_wake_mark;
|
|
}
|
|
|
|
return futexv;
|
|
@@ -231,17 +239,21 @@
|
|
int futex_wait_multiple(struct futex_vector *vs, unsigned int count,
|
|
struct hrtimer_sleeper *to);
|
|
|
|
-static int futex_opcode_31(ktime_t *abs_time, u32 __user *uaddr, int count)
|
|
+static int futex_opcode_31(ktime_t *abs_time, u32 __user *uaddr, int count, int op)
|
|
{
|
|
int ret;
|
|
struct futex_vector *vs;
|
|
struct hrtimer_sleeper *to = NULL, timeout;
|
|
+ unsigned int flags = futex_to_flags(op);
|
|
+
|
|
+ if (flags & FLAGS_CLOCKRT)
|
|
+ return -ENOSYS;
|
|
|
|
- vs = futex_read_wait_block(uaddr, count);
|
|
+ vs = futex_read_wait_block(uaddr, count, flags);
|
|
if (IS_ERR(vs))
|
|
return PTR_ERR(vs);
|
|
|
|
- to = futex_setup_timer(abs_time, &timeout, 0, 0);
|
|
+ to = futex_setup_timer(abs_time, &timeout, flags, current->timer_slack_ns);
|
|
|
|
ret = futex_wait_multiple(vs, count, abs_time ? to : NULL);
|
|
kfree(vs);
|
|
@@ -274,7 +286,7 @@
|
|
}
|
|
|
|
if (cmd == FUTEX_WAIT_MULTIPLE)
|
|
- return futex_opcode_31(tp, uaddr, val);
|
|
+ return futex_opcode_31(tp, uaddr, val, op);
|
|
|
|
return do_futex(uaddr, op, val, tp, uaddr2, (unsigned long)utime, val3);
|
|
}
|
|
@@ -591,7 +603,7 @@
|
|
}
|
|
|
|
if (cmd == FUTEX_WAIT_MULTIPLE)
|
|
- return futex_opcode_31(tp, uaddr, val);
|
|
+ return futex_opcode_31(tp, uaddr, val, op);
|
|
|
|
return do_futex(uaddr, op, val, tp, uaddr2, (unsigned long)utime, val3);
|
|
}
|