[RFC patch 3/7] futex: Make key init a helper function
From: Thomas Gleixner
Date: Sat Apr 02 2016 - 07:11:09 EST
Support for attached futexes requires to store information in the futex
key. Make the key init a helper function and let it return the futex uaddr.
At the call sites check the returned uaddr for NULL so the attached mode can
abort the operation when it detects that an attached operation is attempted on
a non attached futex.
Signed-off-by: Thomas Gleixner <tglx@xxxxxxxxxxxxx>
---
kernel/futex.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 61 insertions(+), 6 deletions(-)
Index: b/kernel/futex.c
===================================================================
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -433,6 +433,21 @@ static inline int match_futex(union fute
&& key1->both.offset == key2->both.offset);
}
+/**
+ * futex_key_init - Initialize a futex key
+ * @key: Pointer to the key to initialize
+ * @uaddr: User space address of the futex
+ * @flags: Flags to check for futex mode. Not yet used
+ *
+ * Returns: @uaddr
+ */
+static u32 __user *futex_key_init(union futex_key *key, u32 __user *uaddr,
+ unsigned int flags)
+{
+ *key = FUTEX_KEY_INIT;
+ return uaddr;
+}
+
/*
* Take a reference to the resource addressed by a key.
* Can be called while holding spinlocks.
@@ -1403,13 +1418,17 @@ futex_wake(u32 __user *uaddr, unsigned i
{
struct futex_hash_bucket *hb;
struct futex_q *this, *next;
- union futex_key key = FUTEX_KEY_INIT;
+ union futex_key key;
int ret;
WAKE_Q(wake_q);
if (!bitset)
return -EINVAL;
+ uaddr = futex_key_init(&key, uaddr, flags);
+ if (!uaddr)
+ return -EINVAL;
+
ret = get_futex_key(uaddr, flags & FLAGS_SHARED, &key, VERIFY_READ);
if (unlikely(ret != 0))
goto out;
@@ -1455,12 +1474,20 @@ static int
futex_wake_op(u32 __user *uaddr1, unsigned int flags, u32 __user *uaddr2,
int nr_wake, int nr_wake2, int op)
{
- union futex_key key1 = FUTEX_KEY_INIT, key2 = FUTEX_KEY_INIT;
struct futex_hash_bucket *hb1, *hb2;
struct futex_q *this, *next;
+ union futex_key key1, key2;
int ret, op_ret;
WAKE_Q(wake_q);
+ uaddr1 = futex_key_init(&key1, uaddr1, flags);
+ if (!uaddr1)
+ return -EINVAL;
+
+ uaddr2 = futex_key_init(&key2, uaddr2, flags);
+ if (!uaddr2)
+ return -EINVAL;
+
retry:
ret = get_futex_key(uaddr1, flags & FLAGS_SHARED, &key1, VERIFY_READ);
if (unlikely(ret != 0))
@@ -1693,11 +1720,11 @@ static int futex_requeue(u32 __user *uad
u32 __user *uaddr2, int nr_wake, int nr_requeue,
u32 *cmpval, int requeue_pi)
{
- union futex_key key1 = FUTEX_KEY_INIT, key2 = FUTEX_KEY_INIT;
int drop_count = 0, task_count = 0, ret;
struct futex_pi_state *pi_state = NULL;
struct futex_hash_bucket *hb1, *hb2;
struct futex_q *this, *next;
+ union futex_key key1, key2;
WAKE_Q(wake_q);
if (requeue_pi) {
@@ -1728,6 +1755,14 @@ static int futex_requeue(u32 __user *uad
return -EINVAL;
}
+ uaddr1 = futex_key_init(&key1, uaddr1, flags);
+ if (!uaddr1)
+ return -EINVAL;
+
+ uaddr2 = futex_key_init(&key2, uaddr2, flags);
+ if (!uaddr2)
+ return -EINVAL;
+
retry:
ret = get_futex_key(uaddr1, flags & FLAGS_SHARED, &key1, VERIFY_READ);
if (unlikely(ret != 0))
@@ -2398,6 +2433,11 @@ static int futex_wait(u32 __user *uaddr,
if (!bitset)
return -EINVAL;
+
+ uaddr = futex_key_init(&q.key, uaddr, flags);
+ if (!uaddr)
+ return -EINVAL;
+
q.bitset = bitset;
if (abs_time) {
@@ -2498,6 +2538,10 @@ static int futex_lock_pi(u32 __user *uad
if (refill_pi_state_cache())
return -ENOMEM;
+ uaddr = futex_key_init(&q.key, uaddr, flags);
+ if (!uaddr)
+ return -EINVAL;
+
if (time) {
to = &timeout;
hrtimer_init_on_stack(&to->timer, CLOCK_REALTIME,
@@ -2617,11 +2661,14 @@ static int futex_lock_pi(u32 __user *uad
static int futex_unlock_pi(u32 __user *uaddr, unsigned int flags)
{
u32 uninitialized_var(curval), uval, vpid = task_pid_vnr(current);
- union futex_key key = FUTEX_KEY_INIT;
struct futex_hash_bucket *hb;
struct futex_q *match;
+ union futex_key key;
int ret;
+ uaddr = futex_key_init(&key, uaddr, flags);
+ if (!uaddr)
+ return -EINVAL;
retry:
if (get_user(uval, uaddr))
return -EFAULT;
@@ -2793,9 +2840,9 @@ static int futex_wait_requeue_pi(u32 __u
struct hrtimer_sleeper timeout, *to = NULL;
struct rt_mutex_waiter rt_waiter;
struct rt_mutex *pi_mutex = NULL;
- struct futex_hash_bucket *hb;
- union futex_key key2 = FUTEX_KEY_INIT;
struct futex_q q = futex_q_init;
+ struct futex_hash_bucket *hb;
+ union futex_key key2;
int res, ret;
if (uaddr == uaddr2)
@@ -2804,6 +2851,14 @@ static int futex_wait_requeue_pi(u32 __u
if (!bitset)
return -EINVAL;
+ uaddr = futex_key_init(&q.key, uaddr, flags);
+ if (!uaddr)
+ return -EINVAL;
+
+ uaddr2 = futex_key_init(&key2, uaddr2, flags);
+ if (!uaddr2)
+ return -EINVAL;
+
if (abs_time) {
to = &timeout;
hrtimer_init_on_stack(&to->timer, (flags & FLAGS_CLOCKRT) ?