2022-01-03 19:03:04

by rtm

[permalink] [raw]
Subject: _nfs4_open_and_get_state() should check IS_ERR() from d_splice_alias()

_nfs4_open_and_get_state() says:

if (!alias)
alias = d_splice_alias(igrab(state->inode), dentry);
/* d_splice_alias() can't fail here - it's a non-directory */
if (alias) {
dput(ctx->dentry);
ctx->dentry = dentry = alias;
...;
nfs_set_verifier(dentry, dir_verifier);

d_splice_alias() can return an ERR_PTR(), causing nfs_set_verifier() to
page-fault on &dentry->d_lock; I've attached a demo.

# uname -a
Linux (none) 5.16.0-rc7-00108-g800829388818-dirty #12 SMP Mon Jan 3 18:38:50 UTC 2022 riscv64 riscv64 riscv64 GNU/Linux
# cc nfs_18.c
# ./a.out
...
[ 71.811841] VFS: Lookup of 'x' in nfs4 0:16 would have caused loop
[ 71.825707] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000034
[ 72.064187] status: 0000000200000121 badaddr: 0000000000000034 cause: 000000000000000d
[ 72.079110] [<ffffffff8004dfbc>] do_raw_spin_lock+0xa/0xd8
[ 72.090221] [<ffffffff8064b9f2>] _raw_spin_lock+0x1a/0x22
[ 72.101284] [<ffffffff80201944>] nfs_set_verifier+0x20/0x6a
[ 72.112387] [<ffffffff8022a8b2>] nfs4_do_open.constprop.0+0x30e/0x874
[ 72.125597] [<ffffffff8022aeb0>] nfs4_atomic_open+0xc/0x1c
[ 72.136676] [<ffffffff802036f8>] nfs_atomic_open+0x1a0/0x35e
[ 72.150205] [<ffffffff80137a7c>] path_openat+0x59e/0xadc
[ 72.161311] [<ffffffff801391c8>] do_filp_open+0x70/0xea
[ 72.172464] [<ffffffff801286f4>] do_sys_openat2+0x86/0x11a
[ 72.183523] [<ffffffff80128a6a>] sys_openat+0x40/0x80
[ 72.194578] [<ffffffff80003030>] ret_from_syscall+0x0/0x2
[ 72.213692] ---[ end trace 107b62634b79d2f7 ]---


Attachments:
nfs_18.c (31.07 kB)