Skip to content

Commit 5e0e02f

Browse files
axboeKAGA-KOKO
authored andcommitted
futex: Pass in task to futex_queue()
futex_queue() -> __futex_queue() uses 'current' as the task to store in the struct futex_q->task field. This is fine for synchronous usage of the futex infrastructure, but it's not always correct when used by io_uring where the task doing the initial futex_queue() might not be available later on. This doesn't lead to any issues currently, as the io_uring side doesn't support PI futexes, but it does leave a potentially dangling pointer which is never a good idea. Have futex_queue() take a task_struct argument, and have the regular callers pass in 'current' for that. Meanwhile io_uring can just pass in NULL, as the task should never be used off that path. In theory req->tctx->task could be used here, but there's no point populating it with a task field that will never be used anyway. Reported-by: Jann Horn <jannh@google.com> Signed-off-by: Jens Axboe <axboe@kernel.dk> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Link: https://lore.kernel.org/all/22484a23-542c-4003-b721-400688a0d055@kernel.dk
1 parent bc8198d commit 5e0e02f

File tree

5 files changed

+15
-9
lines changed

5 files changed

+15
-9
lines changed

io_uring/futex.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ int io_futex_wait(struct io_kiocb *req, unsigned int issue_flags)
338338
hlist_add_head(&req->hash_node, &ctx->futex_list);
339339
io_ring_submit_unlock(ctx, issue_flags);
340340

341-
futex_queue(&ifd->q, hb);
341+
futex_queue(&ifd->q, hb, NULL);
342342
return IOU_ISSUE_SKIP_COMPLETE;
343343
}
344344

kernel/futex/core.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,8 @@ void futex_q_unlock(struct futex_hash_bucket *hb)
532532
futex_hb_waiters_dec(hb);
533533
}
534534

535-
void __futex_queue(struct futex_q *q, struct futex_hash_bucket *hb)
535+
void __futex_queue(struct futex_q *q, struct futex_hash_bucket *hb,
536+
struct task_struct *task)
536537
{
537538
int prio;
538539

@@ -548,7 +549,7 @@ void __futex_queue(struct futex_q *q, struct futex_hash_bucket *hb)
548549

549550
plist_node_init(&q->list, prio);
550551
plist_add(&q->list, &hb->chain);
551-
q->task = current;
552+
q->task = task;
552553
}
553554

554555
/**

kernel/futex/futex.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -285,25 +285,30 @@ static inline int futex_get_value_locked(u32 *dest, u32 __user *from)
285285
}
286286

287287
extern void __futex_unqueue(struct futex_q *q);
288-
extern void __futex_queue(struct futex_q *q, struct futex_hash_bucket *hb);
288+
extern void __futex_queue(struct futex_q *q, struct futex_hash_bucket *hb,
289+
struct task_struct *task);
289290
extern int futex_unqueue(struct futex_q *q);
290291

291292
/**
292293
* futex_queue() - Enqueue the futex_q on the futex_hash_bucket
293294
* @q: The futex_q to enqueue
294295
* @hb: The destination hash bucket
296+
* @task: Task queueing this futex
295297
*
296298
* The hb->lock must be held by the caller, and is released here. A call to
297299
* futex_queue() is typically paired with exactly one call to futex_unqueue(). The
298300
* exceptions involve the PI related operations, which may use futex_unqueue_pi()
299301
* or nothing if the unqueue is done as part of the wake process and the unqueue
300302
* state is implicit in the state of woken task (see futex_wait_requeue_pi() for
301303
* an example).
304+
*
305+
* Note that @task may be NULL, for async usage of futexes.
302306
*/
303-
static inline void futex_queue(struct futex_q *q, struct futex_hash_bucket *hb)
307+
static inline void futex_queue(struct futex_q *q, struct futex_hash_bucket *hb,
308+
struct task_struct *task)
304309
__releases(&hb->lock)
305310
{
306-
__futex_queue(q, hb);
311+
__futex_queue(q, hb, task);
307312
spin_unlock(&hb->lock);
308313
}
309314

kernel/futex/pi.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -982,7 +982,7 @@ int futex_lock_pi(u32 __user *uaddr, unsigned int flags, ktime_t *time, int tryl
982982
/*
983983
* Only actually queue now that the atomic ops are done:
984984
*/
985-
__futex_queue(&q, hb);
985+
__futex_queue(&q, hb, current);
986986

987987
if (trylock) {
988988
ret = rt_mutex_futex_trylock(&q.pi_state->pi_mutex);

kernel/futex/waitwake.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,7 @@ void futex_wait_queue(struct futex_hash_bucket *hb, struct futex_q *q,
350350
* access to the hash list and forcing another memory barrier.
351351
*/
352352
set_current_state(TASK_INTERRUPTIBLE|TASK_FREEZABLE);
353-
futex_queue(q, hb);
353+
futex_queue(q, hb, current);
354354

355355
/* Arm the timer */
356356
if (timeout)
@@ -461,7 +461,7 @@ int futex_wait_multiple_setup(struct futex_vector *vs, int count, int *woken)
461461
* next futex. Queue each futex at this moment so hb can
462462
* be unlocked.
463463
*/
464-
futex_queue(q, hb);
464+
futex_queue(q, hb, current);
465465
continue;
466466
}
467467

0 commit comments

Comments
 (0)