Skip to content

Commit 1f2cac1

Browse files
committed
blktrace: fix unlocked access to init/start-stop/teardown
sg.c calls into the blktrace functions without holding the proper queue mutex for doing setup, start/stop, or teardown. Add internal unlocked variants, and export the ones that do the proper locking. Fixes: 6da127a ("blktrace: Add blktrace ioctls to SCSI generic devices") Tested-by: Dmitry Vyukov <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent bf9fc98 commit 1f2cac1

File tree

1 file changed

+48
-10
lines changed

1 file changed

+48
-10
lines changed

kernel/trace/blktrace.c

+48-10
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ static void blk_trace_cleanup(struct blk_trace *bt)
336336
blk_unregister_tracepoints();
337337
}
338338

339-
int blk_trace_remove(struct request_queue *q)
339+
static int __blk_trace_remove(struct request_queue *q)
340340
{
341341
struct blk_trace *bt;
342342

@@ -349,6 +349,17 @@ int blk_trace_remove(struct request_queue *q)
349349

350350
return 0;
351351
}
352+
353+
int blk_trace_remove(struct request_queue *q)
354+
{
355+
int ret;
356+
357+
mutex_lock(&q->blk_trace_mutex);
358+
ret = __blk_trace_remove(q);
359+
mutex_unlock(&q->blk_trace_mutex);
360+
361+
return ret;
362+
}
352363
EXPORT_SYMBOL_GPL(blk_trace_remove);
353364

354365
static ssize_t blk_dropped_read(struct file *filp, char __user *buffer,
@@ -550,9 +561,8 @@ static int do_blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
550561
return ret;
551562
}
552563

553-
int blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
554-
struct block_device *bdev,
555-
char __user *arg)
564+
static int __blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
565+
struct block_device *bdev, char __user *arg)
556566
{
557567
struct blk_user_trace_setup buts;
558568
int ret;
@@ -571,6 +581,19 @@ int blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
571581
}
572582
return 0;
573583
}
584+
585+
int blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
586+
struct block_device *bdev,
587+
char __user *arg)
588+
{
589+
int ret;
590+
591+
mutex_lock(&q->blk_trace_mutex);
592+
ret = __blk_trace_setup(q, name, dev, bdev, arg);
593+
mutex_unlock(&q->blk_trace_mutex);
594+
595+
return ret;
596+
}
574597
EXPORT_SYMBOL_GPL(blk_trace_setup);
575598

576599
#if defined(CONFIG_COMPAT) && defined(CONFIG_X86_64)
@@ -607,7 +630,7 @@ static int compat_blk_trace_setup(struct request_queue *q, char *name,
607630
}
608631
#endif
609632

610-
int blk_trace_startstop(struct request_queue *q, int start)
633+
static int __blk_trace_startstop(struct request_queue *q, int start)
611634
{
612635
int ret;
613636
struct blk_trace *bt = q->blk_trace;
@@ -646,6 +669,17 @@ int blk_trace_startstop(struct request_queue *q, int start)
646669

647670
return ret;
648671
}
672+
673+
int blk_trace_startstop(struct request_queue *q, int start)
674+
{
675+
int ret;
676+
677+
mutex_lock(&q->blk_trace_mutex);
678+
ret = __blk_trace_startstop(q, start);
679+
mutex_unlock(&q->blk_trace_mutex);
680+
681+
return ret;
682+
}
649683
EXPORT_SYMBOL_GPL(blk_trace_startstop);
650684

651685
/*
@@ -676,7 +710,7 @@ int blk_trace_ioctl(struct block_device *bdev, unsigned cmd, char __user *arg)
676710
switch (cmd) {
677711
case BLKTRACESETUP:
678712
bdevname(bdev, b);
679-
ret = blk_trace_setup(q, b, bdev->bd_dev, bdev, arg);
713+
ret = __blk_trace_setup(q, b, bdev->bd_dev, bdev, arg);
680714
break;
681715
#if defined(CONFIG_COMPAT) && defined(CONFIG_X86_64)
682716
case BLKTRACESETUP32:
@@ -687,10 +721,10 @@ int blk_trace_ioctl(struct block_device *bdev, unsigned cmd, char __user *arg)
687721
case BLKTRACESTART:
688722
start = 1;
689723
case BLKTRACESTOP:
690-
ret = blk_trace_startstop(q, start);
724+
ret = __blk_trace_startstop(q, start);
691725
break;
692726
case BLKTRACETEARDOWN:
693-
ret = blk_trace_remove(q);
727+
ret = __blk_trace_remove(q);
694728
break;
695729
default:
696730
ret = -ENOTTY;
@@ -708,10 +742,14 @@ int blk_trace_ioctl(struct block_device *bdev, unsigned cmd, char __user *arg)
708742
**/
709743
void blk_trace_shutdown(struct request_queue *q)
710744
{
745+
mutex_lock(&q->blk_trace_mutex);
746+
711747
if (q->blk_trace) {
712-
blk_trace_startstop(q, 0);
713-
blk_trace_remove(q);
748+
__blk_trace_startstop(q, 0);
749+
__blk_trace_remove(q);
714750
}
751+
752+
mutex_unlock(&q->blk_trace_mutex);
715753
}
716754

717755
#ifdef CONFIG_BLK_CGROUP

0 commit comments

Comments
 (0)