Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+48 −10
Original line number Original line Diff line number Diff line
@@ -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)


	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,
	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,
	}
	}
	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,
}
}
#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)


	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)
	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)
	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)
 **/
 **/
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