Patch "block, bfq: fix uaf for accessing waker_bfqq after splitting" has been added to the 6.10-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    block, bfq: fix uaf for accessing waker_bfqq after splitting

to the 6.10-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     block-bfq-fix-uaf-for-accessing-waker_bfqq-after-spl.patch
and it can be found in the queue-6.10 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 23f8a317d8916d612569e770c9f1f87e65650761
Author: Yu Kuai <yukuai3@xxxxxxxxxx>
Date:   Mon Sep 9 21:41:48 2024 +0800

    block, bfq: fix uaf for accessing waker_bfqq after splitting
    
    [ Upstream commit 1ba0403ac6447f2d63914fb760c44a3b19c44eaf ]
    
    After commit 42c306ed7233 ("block, bfq: don't break merge chain in
    bfq_split_bfqq()"), if the current procress is the last holder of bfqq,
    the bfqq can be freed after bfq_split_bfqq(). Hence recored the bfqq and
    then access bfqq->waker_bfqq may trigger UAF. What's more, the waker_bfqq
    may in the merge chain of bfqq, hence just recored waker_bfqq is still
    not safe.
    
    Fix the problem by adding a helper bfq_waker_bfqq() to check if
    bfqq->waker_bfqq is in the merge chain, and current procress is the only
    holder.
    
    Fixes: 42c306ed7233 ("block, bfq: don't break merge chain in bfq_split_bfqq()")
    Signed-off-by: Yu Kuai <yukuai3@xxxxxxxxxx>
    Link: https://lore.kernel.org/r/20240909134154.954924-2-yukuai1@xxxxxxxxxxxxxxx
    Signed-off-by: Jens Axboe <axboe@xxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
index 2b6fff39b9f4b..2423e25fc23ae 100644
--- a/block/bfq-iosched.c
+++ b/block/bfq-iosched.c
@@ -6823,6 +6823,31 @@ static void bfq_prepare_request(struct request *rq)
 	rq->elv.priv[0] = rq->elv.priv[1] = NULL;
 }
 
+static struct bfq_queue *bfq_waker_bfqq(struct bfq_queue *bfqq)
+{
+	struct bfq_queue *new_bfqq = bfqq->new_bfqq;
+	struct bfq_queue *waker_bfqq = bfqq->waker_bfqq;
+
+	if (!waker_bfqq)
+		return NULL;
+
+	while (new_bfqq) {
+		if (new_bfqq == waker_bfqq) {
+			/*
+			 * If waker_bfqq is in the merge chain, and current
+			 * is the only procress.
+			 */
+			if (bfqq_process_refs(waker_bfqq) == 1)
+				return NULL;
+			break;
+		}
+
+		new_bfqq = new_bfqq->new_bfqq;
+	}
+
+	return waker_bfqq;
+}
+
 /*
  * If needed, init rq, allocate bfq data structures associated with
  * rq, and increment reference counters in the destination bfq_queue
@@ -6884,7 +6909,7 @@ static struct bfq_queue *bfq_init_rq(struct request *rq)
 		/* If the queue was seeky for too long, break it apart. */
 		if (bfq_bfqq_coop(bfqq) && bfq_bfqq_split_coop(bfqq) &&
 			!bic->bfqq_data[a_idx].stably_merged) {
-			struct bfq_queue *old_bfqq = bfqq;
+			struct bfq_queue *waker_bfqq = bfq_waker_bfqq(bfqq);
 
 			/* Update bic before losing reference to bfqq */
 			if (bfq_bfqq_in_large_burst(bfqq))
@@ -6904,7 +6929,7 @@ static struct bfq_queue *bfq_init_rq(struct request *rq)
 				bfqq_already_existing = true;
 
 			if (!bfqq_already_existing) {
-				bfqq->waker_bfqq = old_bfqq->waker_bfqq;
+				bfqq->waker_bfqq = waker_bfqq;
 				bfqq->tentative_waker_bfqq = NULL;
 
 				/*
@@ -6914,7 +6939,7 @@ static struct bfq_queue *bfq_init_rq(struct request *rq)
 				 * woken_list of the waker. See
 				 * bfq_check_waker for details.
 				 */
-				if (bfqq->waker_bfqq)
+				if (waker_bfqq)
 					hlist_add_head(&bfqq->woken_list_node,
 						       &bfqq->waker_bfqq->woken_list);
 			}




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux