From: Al Viro <viro@zeniv.linux.org.uk>
To: Qian Cai <cai@lca.pw>
Cc: Linus Torvalds <torvalds@linux-foundation.org>,
linux-fsdevel@vger.kernel.org,
LKML <linux-kernel@vger.kernel.org>
Subject: Re: Null-ptr-deref due to "sanitized pathwalk machinery (v4)"
Date: Tue, 24 Mar 2020 21:46:37 +0000 [thread overview]
Message-ID: <20200324214637.GI23230@ZenIV.linux.org.uk> (raw)
In-Reply-To: <4CBDE0F3-FB73-43F3-8535-6C75BA004233@lca.pw>
On Tue, Mar 24, 2020 at 05:06:03PM -0400, Qian Cai wrote:
> Reverted the series on the top of today's linux-next fixed boot crashes.
Umm... How about a reproducer (or bisect of vfs.git#work.dotdot, assuming
it reproduces there)?
> [ 53.027443][ T3519] BUG: Kernel NULL pointer dereference on read at 0x00000000
> [ 53.027480][ T3519] Faulting instruction address: 0xc0000000004dbfa4
> [ 53.027498][ T3519] Oops: Kernel access of bad area, sig: 11 [#1]
> [ 53.027521][ T3519] LE PAGE_SIZE=64K MMU=Radix SMP NR_CPUS=256 DEBUG_PAGEALLOC NUMA PowerNV
> [ 53.027538][ T3519] Modules linked in: kvm_hv kvm ip_tables x_tables xfs sd_mod bnx2x ahci libahci mdio libata tg3 libphy firmware_class dm_mirror dm_region_hash dm_log dm_mod
> [ 53.027594][ T3519] CPU: 36 PID: 3519 Comm: polkitd Not tainted 5.6.0-rc7-next-20200324 #1
> [ 53.027618][ T3519] NIP: c0000000004dbfa4 LR: c0000000004dc040 CTR: 0000000000000000
> [ 53.027634][ T3519] REGS: c0002013879af810 TRAP: 0300 Not tainted (5.6.0-rc7-next-20200324)
> [ 53.027668][ T3519] MSR: 9000000000009033 <SF,HV,EE,ME,IR,DR,RI,LE> CR: 24004422 XER: 20040000
> [ 53.027708][ T3519] CFAR: c0000000004dc044 DAR: 0000000000000000 DSISR: 40000000 IRQMASK: 0
> [ 53.027708][ T3519] GPR00: c0000000004dc040 c0002013879afaa0 c00000000165a500 0000000000000000
> [ 53.027708][ T3519] GPR04: c000000001511408 0000000000000000 c0002013879af834 0000000000000002
> [ 53.027708][ T3519] GPR08: 0000000000000001 0000000000000000 0000000000000000 0000000000000001
> [ 53.027708][ T3519] GPR12: 0000000000004000 c000001ffffe1e00 0000000000000000 0000000000000000
> [ 53.027708][ T3519] GPR16: 0000000000000000 0000000000000001 0000000000000000 0000000000000000
> [ 53.027708][ T3519] GPR20: c000200ea1eacf38 c000201c8102f043 2f2f2f2f2f2f2f2f 0000000000000003
> [ 53.027708][ T3519] GPR24: 0000000000000000 c0002013879afbc8 fffffffffffff000 0000000000200000
> [ 53.027708][ T3519] GPR28: ffffffffffffffff 61c8864680b583eb 0000000000000000 0000000000002e2e
> [ 53.027931][ T3519] NIP [c0000000004dbfa4] link_path_walk+0x284/0x4c0
> __d_entry_type at include/linux/dcache.h:389
> (inlined by) d_can_lookup at include/linux/dcache.h:404
> (inlined by) link_path_walk at fs/namei.c:2178
... and apparently NULL nd->path.dentry there. After walk_component()
having returned NULL. Which means either handle_dots() returning NULL
or step_into() doing the same. The former means either (for "..")
step_into() having returned NULL, or nd->path.dentry left unchanged.
So we either have step_into() returning NULL with nd->path.dentry ending up
NULL, or we'd entered link_path_walk() with nd->path.dentry being NULL (it
must have been that way on the entry, or we would've barfed on the previous
iteration).
1) step_into() returns NULL either after
if (likely(!d_is_symlink(path.dentry)) ||
((flags & WALK_TRAILING) && !(nd->flags & LOOKUP_FOLLOW)) ||
(flags & WALK_NOFOLLOW)) {
/* not a symlink or should not follow */
if (!(nd->flags & LOOKUP_RCU)) {
dput(nd->path.dentry);
if (nd->path.mnt != path.mnt)
mntput(nd->path.mnt);
}
nd->path = path;
nd->inode = inode;
nd->seq = seq;
return NULL;
in which case nd->path.dentry is left equal to path.dentry, which can't be
NULL (we would've oopsed on d_is_symlink() if it had been) or it's
pick_link() returning NULL and leaving NULL nd->path.dentry.
pick_link() either leaves nd->path unchanged (in which case we are back to
the "had NULL nd->path.dentry on entry into link_path_walk()") or does
nd_jump_root() (absolute symlinks) or has ->get_link() call nd_jump_link().
nd_jump_root() cannot survive leaving NULL in ->path.dentry - it hits
either
d = nd->path.dentry;
nd->inode = d->d_inode;
or
nd->inode = nd->path.dentry->d_inode;
and either would've ooped right there.
nd_jump_link() hits
nd->inode = nd->path.dentry->d_inode;
on the way out, which also should be impossible to survive.
So we appear to have hit link_path_walk() with NULL nd->path.dentry. And
it's path_lookupat() from vfs_statx(), so we don't have LOOKUP_DOWN there.
Which means either path_init() leaving NULL nd->path.dentry or lookup_last()
returning NULL and leaving NULL nd->path.dentry... The latter is basically
walk_component(), so we would've had left link_path_walk() without an
error, with symlink picked and with NULL nd->path.dentry. Which means
having the previous call of link_path_walk() also entered with NULL
nd->path.dentry...
OK, so it looks like path_init() returning a string and leaving that...
And I don't see any way for that to happen...
Right, so... Could you slap the following
if (WARN_ON(!nd->path.dentry))
printk(KERN_ERR "pathname = %s\n", nd->name->name);
1) into beginning of link_path_walk(), right before
while (*name=='/')
name++;
if (!*name)
return 0;
in there.
2) into pick_link(), right after
all_done: // pure jump
and see what your reproducer catches?
next prev parent reply other threads:[~2020-03-24 21:48 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-03-24 21:06 Null-ptr-deref due to "sanitized pathwalk machinery (v4)" Qian Cai
2020-03-24 21:46 ` Al Viro [this message]
2020-03-25 1:49 ` Qian Cai
2020-03-25 2:13 ` Al Viro
2020-03-25 3:24 ` Qian Cai
2020-03-25 4:03 ` Al Viro
2020-03-25 5:58 ` Al Viro
2020-03-25 14:02 ` Al Viro
2020-03-25 14:05 ` Al Viro
2020-03-25 19:43 ` Qian Cai
2020-03-25 21:07 ` Al Viro
2020-03-25 13:21 ` Qian Cai
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200324214637.GI23230@ZenIV.linux.org.uk \
--to=viro@zeniv.linux.org.uk \
--cc=cai@lca.pw \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=torvalds@linux-foundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.