[GIT PULL] libnvdimm fix for 4.12-rc5

From: Williams, Dan J
Date: Sat Jun 10 2017 - 15:28:03 EST


Hi Linus, please pull from:

git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm libnvdimm-fixes

...to receive a fix for an oversight spotted by Sasha.

We expanded the device-dax fs type in 4.12 to be a generic provider of
a struct dax+AF8-device with an embedded inode. However, Sasha found some
basic negative testing was not run to verify that this fs cleanly
handles being mounted directly. Note that the fresh rebase was done to
remove an unnecessary Cc: +ADw-stable+AD4- tag, but this commit otherwise had a
build success notification from the 0day robot.

---

The following changes since commit 3c2993b8c6143d8a5793746a54eba8f86f95240f:

Linux 4.12-rc4 (2017-06-04 16:47:43 -0700)

are available in the git repository at:

git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm libnvdimm-fixes

for you to fetch changes up to b9d39d17e4819ca2e69ad1f14acaad12240a1de5:

device-dax: fix 'dax' device filesystem inode destruction crash (2017-06-09 08:50:49 -0700)

----------------------------------------------------------------
Dan Williams (1):
device-dax: fix 'dax' device filesystem inode destruction crash

drivers/dax/super.c +AHw- 9 +-+-+-+-+-+-+---
1 file changed, 7 insertions(+-), 2 deletions(-)

commit b9d39d17e4819ca2e69ad1f14acaad12240a1de5
Author: Dan Williams +ADw-dan.j.williams+AEA-intel.com+AD4-
Date: Fri Jun 9 08:50:49 2017 -0700

device-dax: fix 'dax' device filesystem inode destruction crash

The inode destruction path for the 'dax' device filesystem incorrectly
assumes that the inode was initialized through 'alloc+AF8-dax()'. However,
if someone attempts to directly mount the dax filesystem with 'mount -t
dax dax mnt' that will bypass 'alloc+AF8-dax()' and the following failure
signatures may occur as a result:

kill+AF8-dax() must be called before final iput()
WARNING: CPU: 2 PID: 1188 at drivers/dax/super.c:243 dax+AF8-destroy+AF8-inode+-0x48/0x50
RIP: 0010:dax+AF8-destroy+AF8-inode+-0x48/0x50
Call Trace:
destroy+AF8-inode+-0x3b/0x60
evict+-0x139/0x1c0
iput+-0x1f9/0x2d0
dentry+AF8-unlink+AF8-inode+-0xc3/0x160
+AF8AXw-dentry+AF8-kill+-0xcf/0x180
? dput+-0x37/0x3b0
dput+-0x3a3/0x3b0
do+AF8-one+AF8-tree+-0x36/0x40
shrink+AF8-dcache+AF8-for+AF8-umount+-0x2d/0x90
generic+AF8-shutdown+AF8-super+-0x1f/0x120
kill+AF8-anon+AF8-super+-0x12/0x20
deactivate+AF8-locked+AF8-super+-0x43/0x70
deactivate+AF8-super+-0x4e/0x60

general protection fault: 0000 +AFsAIw-1+AF0- SMP DEBUG+AF8-PAGEALLOC
RIP: 0010:kfree+-0x6d/0x290
Call Trace:
+ADw-IRQ+AD4-
dax+AF8-i+AF8-callback+-0x22/0x60
? dax+AF8-destroy+AF8-inode+-0x50/0x50
rcu+AF8-process+AF8-callbacks+-0x298/0x740

ida+AF8-remove called for id+AD0-0 which is not allocated.
WARNING: CPU: 0 PID: 0 at lib/idr.c:383 ida+AF8-remove+-0x110/0x120
+AFs-..+AF0-
Call Trace:
+ADw-IRQ+AD4-
ida+AF8-simple+AF8-remove+-0x2b/0x50
? dax+AF8-destroy+AF8-inode+-0x50/0x50
dax+AF8-i+AF8-callback+-0x3c/0x60
rcu+AF8-process+AF8-callbacks+-0x298/0x740

Add missing initialization of the 'struct dax+AF8-device' and inode so that
the destruction path does not kfree() or ida+AF8-simple+AF8-remove()
uninitialized data.

Fixes: 7b6be8444e0f (+ACI-dax: refactor dax-fs into a generic provider of 'struct dax+AF8-device' instances+ACI-)
Reported-by: Sasha Levin +ADw-alexander.levin+AEA-verizon.com+AD4-
Signed-off-by: Dan Williams +ADw-dan.j.williams+AEA-intel.com+AD4-
---
drivers/dax/super.c +AHw- 9 +-+-+-+-+-+-+---
1 file changed, 7 insertions(+-), 2 deletions(-)

diff --git a/drivers/dax/super.c b/drivers/dax/super.c
index 6ed32aac8bbe..922d0823f8ec 100644
--- a/drivers/dax/super.c
+-+-+- b/drivers/dax/super.c
+AEAAQA- -210,9 +-210,12 +AEAAQA- EXPORT+AF8-SYMBOL+AF8-GPL(kill+AF8-dax)+ADs-
static struct inode +ACo-dax+AF8-alloc+AF8-inode(struct super+AF8-block +ACo-sb)
+AHs-
struct dax+AF8-device +ACo-dax+AF8-dev+ADs-
+- struct inode +ACo-inode+ADs-

dax+AF8-dev +AD0- kmem+AF8-cache+AF8-alloc(dax+AF8-cache, GFP+AF8-KERNEL)+ADs-
- return +ACY-dax+AF8-dev-+AD4-inode+ADs-
+- inode +AD0- +ACY-dax+AF8-dev-+AD4-inode+ADs-
+- inode-+AD4-i+AF8-rdev +AD0- 0+ADs-
+- return inode+ADs-
+AH0-

static struct dax+AF8-device +ACo-to+AF8-dax+AF8-dev(struct inode +ACo-inode)
+AEAAQA- -227,7 +-230,8 +AEAAQA- static void dax+AF8-i+AF8-callback(struct rcu+AF8-head +ACo-head)

kfree(dax+AF8-dev-+AD4-host)+ADs-
dax+AF8-dev-+AD4-host +AD0- NULL+ADs-
- ida+AF8-simple+AF8-remove(+ACY-dax+AF8-minor+AF8-ida, MINOR(inode-+AD4-i+AF8-rdev))+ADs-
+- if (inode-+AD4-i+AF8-rdev)
+- ida+AF8-simple+AF8-remove(+ACY-dax+AF8-minor+AF8-ida, MINOR(inode-+AD4-i+AF8-rdev))+ADs-
kmem+AF8-cache+AF8-free(dax+AF8-cache, dax+AF8-dev)+ADs-
+AH0-

+AEAAQA- -423,6 +-427,7 +AEAAQA- static void init+AF8-once(void +ACoAXw-dax+AF8-dev)
struct dax+AF8-device +ACo-dax+AF8-dev +AD0- +AF8-dax+AF8-dev+ADs-
struct inode +ACo-inode +AD0- +ACY-dax+AF8-dev-+AD4-inode+ADs-

+- memset(dax+AF8-dev, 0, sizeof(+ACo-dax+AF8-dev))+ADs-
inode+AF8-init+AF8-once(inode)+ADs-
+AH0-