Skip to content

Commit ee37edd

Browse files
Ming Leiaxboe
authored andcommitted
block: avoid use-after-free on throttle data
In throtl_pending_timer_fn(), request queue is retrieved from throttle data. And tg's pending timer is deleted synchronously when releasing the associated blkg, at that time, throttle data may have been freed since commit 1059699 ("block: move blkcg initialization/destroy into disk allocation/release handler") moves freeing q->td to disk_release() from blk_release_queue(). So use-after-free on q->td in throtl_pending_timer_fn can be triggered. Fixes the issue by: - do nothing in case that disk is released, when there isn't any bio to dispatch - retrieve request queue from blkg instead of throttle data for non top-level pending timer. Signed-off-by: Ming Lei <ming.lei@redhat.com> Link: https://lore.kernel.org/r/20220318130144.1066064-2-ming.lei@redhat.com Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent 572299f commit ee37edd

1 file changed

Lines changed: 11 additions & 1 deletion

File tree

block/blk-throttle.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1137,12 +1137,22 @@ static void throtl_pending_timer_fn(struct timer_list *t)
11371137
struct throtl_service_queue *sq = from_timer(sq, t, pending_timer);
11381138
struct throtl_grp *tg = sq_to_tg(sq);
11391139
struct throtl_data *td = sq_to_td(sq);
1140-
struct request_queue *q = td->queue;
11411140
struct throtl_service_queue *parent_sq;
1141+
struct request_queue *q;
11421142
bool dispatched;
11431143
int ret;
11441144

1145+
/* throtl_data may be gone, so figure out request queue by blkg */
1146+
if (tg)
1147+
q = tg->pd.blkg->q;
1148+
else
1149+
q = td->queue;
1150+
11451151
spin_lock_irq(&q->queue_lock);
1152+
1153+
if (!q->root_blkg)
1154+
goto out_unlock;
1155+
11461156
if (throtl_can_upgrade(td, NULL))
11471157
throtl_upgrade_state(td);
11481158

0 commit comments

Comments
 (0)