* [PATCH 1/2] dm mpath: fix infinite recursion in ioctl when no paths and queue_if_no_path is not set
@ 2015-11-17 9:36 Junichi Nomura
2015-11-18 22:52 ` Bart Van Assche
2015-11-19 19:39 ` Mike Snitzer
0 siblings, 2 replies; 3+ messages in thread
From: Junichi Nomura @ 2015-11-17 9:36 UTC (permalink / raw)
To: device-mapper development, Christoph Hellwig, Mike Snitzer
In multipath_prepare_ioctl(),
- pgpath is a path selected from available paths
- m->queue_io is true if we cannot send a request immediately to
paths, either because:
* there is no available path
* the path group needs activation (pg_init)
- pg_init is not started
- pg_init is still running
- m->queue_if_no_path is true if the device is configured to queue
I/O if there is no available path
If !pgpath && !m->queue_if_no_path, the handler should return -EIO.
However in the course of refactoring the condition check has broken
and returns success in that case. Since bdev points to the dm device
itself, dm_blk_ioctl() calls __blk_dev_driver_ioctl() for itself and
recurses until crash.
You could reproduce the problem like this:
# dmsetup create mp --table '0 1024 multipath 0 0 0 0'
# sg_inq /dev/mapper/mp
<crash>
[ 172.648615] BUG: unable to handle kernel paging request at fffffffc81b10268
[ 172.662843] PGD 19dd067 PUD 0
[ 172.666269] Thread overran stack, or stack corrupted
[ 172.671808] Oops: 0000 [#1] SMP
...
This patch fixes the condition check with some clarifications.
Fixes: e56f81e0b01e ("dm: refactor ioctl handling")
Signed-off-by: Jun'ichi Nomura <j-nomura@ce.jp.nec.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Mike Snitzer <snitzer@redhat.com>
---
drivers/md/dm-mpath.c | 28 +++++++++++++++-------------
1 file changed, 15 insertions(+), 13 deletions(-)
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index aaa6caa..0ad50ff 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -1537,29 +1537,31 @@ static int multipath_prepare_ioctl(struct dm_target *ti,
struct block_device **bdev, fmode_t *mode)
{
struct multipath *m = ti->private;
- struct pgpath *pgpath;
unsigned long flags;
int r;
- r = 0;
-
spin_lock_irqsave(&m->lock, flags);
if (!m->current_pgpath)
__choose_pgpath(m, 0);
- pgpath = m->current_pgpath;
-
- if (pgpath) {
- *bdev = pgpath->path.dev->bdev;
- *mode = pgpath->path.dev->mode;
+ if (m->current_pgpath) {
+ if (!m->queue_io) {
+ *bdev = m->current_pgpath->path.dev->bdev;
+ *mode = m->current_pgpath->path.dev->mode;
+ r = 0;
+ } else {
+ /* pg_init has not started or completed */
+ r = -ENOTCONN;
+ }
+ } else {
+ /* No path is available */
+ if (m->queue_if_no_path)
+ r = -ENOTCONN;
+ else
+ r = -EIO;
}
- if ((pgpath && m->queue_io) || (!pgpath && m->queue_if_no_path))
- r = -ENOTCONN;
- else if (!*bdev)
- r = -EIO;
-
spin_unlock_irqrestore(&m->lock, flags);
if (r == -ENOTCONN && !fatal_signal_pending(current)) {
--
2.4.3
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH 1/2] dm mpath: fix infinite recursion in ioctl when no paths and queue_if_no_path is not set
2015-11-17 9:36 [PATCH 1/2] dm mpath: fix infinite recursion in ioctl when no paths and queue_if_no_path is not set Junichi Nomura
@ 2015-11-18 22:52 ` Bart Van Assche
2015-11-19 19:39 ` Mike Snitzer
1 sibling, 0 replies; 3+ messages in thread
From: Bart Van Assche @ 2015-11-18 22:52 UTC (permalink / raw)
To: device-mapper development, Christoph Hellwig, Mike Snitzer
On 11/17/2015 01:36 AM, Junichi Nomura wrote:
> In multipath_prepare_ioctl(),
> - pgpath is a path selected from available paths
> - m->queue_io is true if we cannot send a request immediately to
> paths, either because:
> * there is no available path
> * the path group needs activation (pg_init)
> - pg_init is not started
> - pg_init is still running
> - m->queue_if_no_path is true if the device is configured to queue
> I/O if there is no available path
>
> If !pgpath && !m->queue_if_no_path, the handler should return -EIO.
> However in the course of refactoring the condition check has broken
> and returns success in that case. Since bdev points to the dm device
> itself, dm_blk_ioctl() calls __blk_dev_driver_ioctl() for itself and
> recurses until crash.
>
> You could reproduce the problem like this:
>
> # dmsetup create mp --table '0 1024 multipath 0 0 0 0'
> # sg_inq /dev/mapper/mp
> <crash>
> [ 172.648615] BUG: unable to handle kernel paging request at fffffffc81b10268
> [ 172.662843] PGD 19dd067 PUD 0
> [ 172.666269] Thread overran stack, or stack corrupted
> [ 172.671808] Oops: 0000 [#1] SMP
> ...
>
> This patch fixes the condition check with some clarifications.
>
> Fixes: e56f81e0b01e ("dm: refactor ioctl handling")
> Signed-off-by: Jun'ichi Nomura <j-nomura@ce.jp.nec.com>
> Cc: Christoph Hellwig <hch@lst.de>
> Cc: Mike Snitzer <snitzer@redhat.com>
Since I was able to reproduce this crash and since I haven't seen that
crash anymore after I had applied this patch,
Tested-by: Bart Van Assche <bart.vanassche@sandisk.com>
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH 1/2] dm mpath: fix infinite recursion in ioctl when no paths and queue_if_no_path is not set
2015-11-17 9:36 [PATCH 1/2] dm mpath: fix infinite recursion in ioctl when no paths and queue_if_no_path is not set Junichi Nomura
2015-11-18 22:52 ` Bart Van Assche
@ 2015-11-19 19:39 ` Mike Snitzer
1 sibling, 0 replies; 3+ messages in thread
From: Mike Snitzer @ 2015-11-19 19:39 UTC (permalink / raw)
To: Junichi Nomura; +Cc: device-mapper development, Christoph Hellwig
On Tue, Nov 17 2015 at 4:36am -0500,
Junichi Nomura <j-nomura@ce.jp.nec.com> wrote:
> In multipath_prepare_ioctl(),
> - pgpath is a path selected from available paths
> - m->queue_io is true if we cannot send a request immediately to
> paths, either because:
> * there is no available path
> * the path group needs activation (pg_init)
> - pg_init is not started
> - pg_init is still running
> - m->queue_if_no_path is true if the device is configured to queue
> I/O if there is no available path
>
> If !pgpath && !m->queue_if_no_path, the handler should return -EIO.
> However in the course of refactoring the condition check has broken
> and returns success in that case. Since bdev points to the dm device
> itself, dm_blk_ioctl() calls __blk_dev_driver_ioctl() for itself and
> recurses until crash.
>
> You could reproduce the problem like this:
>
> # dmsetup create mp --table '0 1024 multipath 0 0 0 0'
> # sg_inq /dev/mapper/mp
> <crash>
> [ 172.648615] BUG: unable to handle kernel paging request at fffffffc81b10268
> [ 172.662843] PGD 19dd067 PUD 0
> [ 172.666269] Thread overran stack, or stack corrupted
> [ 172.671808] Oops: 0000 [#1] SMP
> ...
>
> This patch fixes the condition check with some clarifications.
>
> Fixes: e56f81e0b01e ("dm: refactor ioctl handling")
> Signed-off-by: Jun'ichi Nomura <j-nomura@ce.jp.nec.com>
> Cc: Christoph Hellwig <hch@lst.de>
> Cc: Mike Snitzer <snitzer@redhat.com>
I've staged this fix for 4.4-rc, see:
https://git.kernel.org/cgit/linux/kernel/git/device-mapper/linux-dm.git/commit/?h=dm-4.4&id=43e43c9ea60a7a1831ec823773e924d2dadefd44
I think your fix improves the readability of the code.
But I also applied this fix based on the above patch header (which would
also resolve this issue without your fix):
https://git.kernel.org/cgit/linux/kernel/git/device-mapper/linux-dm.git/commit/?h=dm-4.4&id=647a20d5cad7477033bc021ec9dd75edf4bbf9a0
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2015-11-19 19:39 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-11-17 9:36 [PATCH 1/2] dm mpath: fix infinite recursion in ioctl when no paths and queue_if_no_path is not set Junichi Nomura
2015-11-18 22:52 ` Bart Van Assche
2015-11-19 19:39 ` Mike Snitzer
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.