_nfs4_open_and_get_state() should check d_splice_alias() return for error

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



In this code in fs/nfs/nfs4proc.c _nfs_open_and_get_state():

        dentry = opendata->dentry;
        if (d_really_is_negative(dentry)) {
                struct dentry *alias;
                d_drop(dentry);
                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;
                }

d_splice_alias() can fail, returning ERR_PTR(-ELOOP). Then this call
later on causes a crash:

                nfs_set_verifier(dentry, dir_verifier);

I've attached a demo program:

# uname -a
Linux xxx 6.17.0-rc4-00231-gc8ed9b5c02a5 #27 SMP PREEMPT_DYNAMIC Fri Sep  5 15:07:50 EDT 2025 x86_64 x86_64 x86_64 GNU/Linux
# cc nfs166c.c
# ./a.out
...
BUG: kernel NULL pointer dereference, address: 0000000000000058

Here's a gdb backtrace:

#0  nfs_set_verifier (dentry=dentry@entry=0xffffffffffffffd8, verf=verf@entry=0)
    at ./include/linux/spinlock.h:351
#1  0xffffffff8043a6c2 in _nfs4_open_and_get_state (ctx=0xffffffd602f93c00, 
    opendata=0xffffffd60558a000) at fs/nfs/nfs4proc.c:3197
#2  _nfs4_do_open (dir=0xffffffd60288c7e0, opened=0xffffffc6002f3b4c, 
    c=0xffffffc6002f3a30, flags=32768, ctx=0xffffffd602f93c00) at fs/nfs/nfs4proc.c:3274
#3  nfs4_do_open (dir=dir@entry=0xffffffd60288c7e0, ctx=ctx@entry=0xffffffd602f93c00, 
    flags=flags@entry=32768, sattr=sattr@entry=0xffffffc6002f3b78, 
    label=label@entry=0x0, opened=opened@entry=0xffffffc6002f3b4c)
    at fs/nfs/nfs4proc.c:3345
#4  0xffffffff8043aa92 in nfs4_atomic_open (dir=0xffffffd60288c7e0, 
    ctx=0xffffffd602f93c00, open_flags=32768, attr=0xffffffc6002f3b78, 
    opened=0xffffffc6002f3b4c) at fs/nfs/nfs4proc.c:3919
#5  0xffffffff804056c4 in nfs_atomic_open (dir=0xffffffd60288c7e0, 
    dentry=0xffffffd6029af9c8, file=0xffffffd604734040, open_flags=32768, 
    mode=<optimized out>) at fs/nfs/dir.c:2138
#6  0xffffffff802c2a8a in atomic_open (mode=0, open_flag=<optimized out>, 
    file=0xffffffd604734040, dentry=0xffffffd6029af9c8, nd=0xffffffc6002f3cf8)
    at fs/namei.c:3528
#7  lookup_open (op=0xffffffc6002f3e30, got_write=false, file=0xffffffd604734040, 
    nd=0xffffffc6002f3cf8) at fs/namei.c:3687
#8  open_last_lookups (op=0xffffffc6002f3e30, file=0xffffffd604734040, 
    nd=0xffffffc6002f3cf8) at fs/namei.c:3815
#9  path_openat (nd=nd@entry=0xffffffc6002f3cf8, op=op@entry=0xffffffc6002f3e30, 
    flags=flags@entry=257) at fs/namei.c:4051
#10 0xffffffff802c3098 in do_filp_open (dfd=dfd@entry=-100, 
    pathname=pathname@entry=0xffffffd6027f1100, op=op@entry=0xffffffc6002f3e30)
    at fs/namei.c:4081
#11 0xffffffff802ae234 in do_sys_openat2 (dfd=-100, filename=<optimized out>, 
    how=how@entry=0xffffffc6002f3e90) at fs/open.c:1435
#12 0xffffffff802ae5a2 in do_sys_open (mode=<optimized out>, flags=<optimized out>, 
    filename=<optimized out>, dfd=<optimized out>) at fs/open.c:1450
#13 __do_sys_openat (mode=<optimized out>, flags=<optimized out>, 
    filename=<optimized out>, dfd=<optimized out>) at fs/open.c:1466
#14 __se_sys_openat (mode=<optimized out>, flags=<optimized out>, 
    filename=<optimized out>, dfd=<optimized out>) at fs/open.c:1461
#15 __riscv_sys_openat (regs=<optimized out>) at fs/open.c:1461
#16 0xffffffff812197ee in syscall_handler (syscall=<optimized out>, 
    regs=0xffffffc6002f3ee0) at ./arch/riscv/include/asm/syscall.h:112
#17 do_trap_ecall_u (regs=0xffffffc6002f3ee0) at arch/riscv/kernel/traps.c:343

Robert Morris
rtm@xxxxxxx

Attachment: nfs166c.c
Description: Binary data


[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux