Commit 1f2cac10 authored by Jens Axboe's avatar Jens Axboe

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: 6da127ad ("blktrace: Add blktrace ioctls to SCSI generic devices")
Tested-by: default avatarDmitry Vyukov <dvyukov@google.com>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent bf9fc98b
...@@ -336,7 +336,7 @@ static void blk_trace_cleanup(struct blk_trace *bt) ...@@ -336,7 +336,7 @@ static void blk_trace_cleanup(struct blk_trace *bt)
blk_unregister_tracepoints(); blk_unregister_tracepoints();
} }
int blk_trace_remove(struct request_queue *q) static int __blk_trace_remove(struct request_queue *q)
{ {
struct blk_trace *bt; struct blk_trace *bt;
...@@ -349,6 +349,17 @@ int blk_trace_remove(struct request_queue *q) ...@@ -349,6 +349,17 @@ int blk_trace_remove(struct request_queue *q)
return 0; return 0;
} }
int blk_trace_remove(struct request_queue *q)
{
int ret;
mutex_lock(&q->blk_trace_mutex);
ret = __blk_trace_remove(q);
mutex_unlock(&q->blk_trace_mutex);
return ret;
}
EXPORT_SYMBOL_GPL(blk_trace_remove); EXPORT_SYMBOL_GPL(blk_trace_remove);
static ssize_t blk_dropped_read(struct file *filp, char __user *buffer, 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, ...@@ -550,9 +561,8 @@ static int do_blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
return ret; return ret;
} }
int blk_trace_setup(struct request_queue *q, char *name, dev_t dev, static int __blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
struct block_device *bdev, struct block_device *bdev, char __user *arg)
char __user *arg)
{ {
struct blk_user_trace_setup buts; struct blk_user_trace_setup buts;
int ret; int ret;
...@@ -571,6 +581,19 @@ int blk_trace_setup(struct request_queue *q, char *name, dev_t dev, ...@@ -571,6 +581,19 @@ int blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
} }
return 0; return 0;
} }
int blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
struct block_device *bdev,
char __user *arg)
{
int ret;
mutex_lock(&q->blk_trace_mutex);
ret = __blk_trace_setup(q, name, dev, bdev, arg);
mutex_unlock(&q->blk_trace_mutex);
return ret;
}
EXPORT_SYMBOL_GPL(blk_trace_setup); EXPORT_SYMBOL_GPL(blk_trace_setup);
#if defined(CONFIG_COMPAT) && defined(CONFIG_X86_64) #if defined(CONFIG_COMPAT) && defined(CONFIG_X86_64)
...@@ -607,7 +630,7 @@ static int compat_blk_trace_setup(struct request_queue *q, char *name, ...@@ -607,7 +630,7 @@ static int compat_blk_trace_setup(struct request_queue *q, char *name,
} }
#endif #endif
int blk_trace_startstop(struct request_queue *q, int start) static int __blk_trace_startstop(struct request_queue *q, int start)
{ {
int ret; int ret;
struct blk_trace *bt = q->blk_trace; struct blk_trace *bt = q->blk_trace;
...@@ -646,6 +669,17 @@ int blk_trace_startstop(struct request_queue *q, int start) ...@@ -646,6 +669,17 @@ int blk_trace_startstop(struct request_queue *q, int start)
return ret; return ret;
} }
int blk_trace_startstop(struct request_queue *q, int start)
{
int ret;
mutex_lock(&q->blk_trace_mutex);
ret = __blk_trace_startstop(q, start);
mutex_unlock(&q->blk_trace_mutex);
return ret;
}
EXPORT_SYMBOL_GPL(blk_trace_startstop); EXPORT_SYMBOL_GPL(blk_trace_startstop);
/* /*
...@@ -676,7 +710,7 @@ int blk_trace_ioctl(struct block_device *bdev, unsigned cmd, char __user *arg) ...@@ -676,7 +710,7 @@ int blk_trace_ioctl(struct block_device *bdev, unsigned cmd, char __user *arg)
switch (cmd) { switch (cmd) {
case BLKTRACESETUP: case BLKTRACESETUP:
bdevname(bdev, b); bdevname(bdev, b);
ret = blk_trace_setup(q, b, bdev->bd_dev, bdev, arg); ret = __blk_trace_setup(q, b, bdev->bd_dev, bdev, arg);
break; break;
#if defined(CONFIG_COMPAT) && defined(CONFIG_X86_64) #if defined(CONFIG_COMPAT) && defined(CONFIG_X86_64)
case BLKTRACESETUP32: case BLKTRACESETUP32:
...@@ -687,10 +721,10 @@ int blk_trace_ioctl(struct block_device *bdev, unsigned cmd, char __user *arg) ...@@ -687,10 +721,10 @@ int blk_trace_ioctl(struct block_device *bdev, unsigned cmd, char __user *arg)
case BLKTRACESTART: case BLKTRACESTART:
start = 1; start = 1;
case BLKTRACESTOP: case BLKTRACESTOP:
ret = blk_trace_startstop(q, start); ret = __blk_trace_startstop(q, start);
break; break;
case BLKTRACETEARDOWN: case BLKTRACETEARDOWN:
ret = blk_trace_remove(q); ret = __blk_trace_remove(q);
break; break;
default: default:
ret = -ENOTTY; ret = -ENOTTY;
...@@ -708,10 +742,14 @@ int blk_trace_ioctl(struct block_device *bdev, unsigned cmd, char __user *arg) ...@@ -708,10 +742,14 @@ int blk_trace_ioctl(struct block_device *bdev, unsigned cmd, char __user *arg)
**/ **/
void blk_trace_shutdown(struct request_queue *q) void blk_trace_shutdown(struct request_queue *q)
{ {
mutex_lock(&q->blk_trace_mutex);
if (q->blk_trace) { if (q->blk_trace) {
blk_trace_startstop(q, 0); __blk_trace_startstop(q, 0);
blk_trace_remove(q); __blk_trace_remove(q);
} }
mutex_unlock(&q->blk_trace_mutex);
} }
#ifdef CONFIG_BLK_CGROUP #ifdef CONFIG_BLK_CGROUP
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment