From: Al Viro <viro@ZenIV.linux.org.uk> To: "Mickaël Salaün" <mic@digikod.net> Cc: Dmitry Vyukov <dvyukov@google.com>, "linux-fsdevel@vger.kernel.org" <linux-fsdevel@vger.kernel.org>, LKML <linux-kernel@vger.kernel.org>, syzkaller <syzkaller@googlegroups.com>, Kostya Serebryany <kcc@google.com>, Alexander Potapenko <glider@google.com>, Sasha Levin <sasha.levin@oracle.com> Subject: Re: fs: NULL deref in atime_needs_update Date: Sat, 20 Feb 2016 17:10:45 +0000 [thread overview] Message-ID: <20160220171044.GH17997@ZenIV.linux.org.uk> (raw) In-Reply-To: <56C86954.6030101@digikod.net> On Sat, Feb 20, 2016 at 02:25:40PM +0100, Mickaël Salaün wrote: > I think the bug may be somewhere in the nd->depth handling (when its value is 0) in fs/namei.c:get_link(): struct saved *last = nd->stack + nd->depth - 1 Getting there with nd->depth == 0 would certainly be a bug - it would mean that we got there without should_follow_link() having returned 1. In case of open() it would be "do_last() has returned positive without should_follow_link() having returned 1". <looks> OK, there are several places where we rely on not getting bogus return values - inode_permission() should not return positives, neither should vfs_open(), security_path_truncate() and notify_change(). Other similar "handle the last component" functions are guaranteed to never return positives other than directly from should_follow_link(), so they are OK. IIRC, you used LSM to inject a positive value to inode_permission(), right? Another way to trigger that would've been ->open() returning positive - a bug on *anything* since ->open() had been introduced in 0.95. Amount of harm would vary - e.g. 0.95 would simply have that positive number returned to userland, looking like successful open(2). With no new descriptor, of course... Short-term we probably want just if (unlikely(error > 0)) { WARN_ON(1); error = -EINVAL; } added right after out: in do_last(), try to trigger Dmitry's reproducers on it and then work back to the source of that thing *if* that's what's happening in his case. Yours almost certainly is just that. Longer-term... I'm not sure. Having a method that is supposed to return 0 or -E<something> actually return positive is going to be a bad thing, no matter what, but "that bogus value gets passed to userland" is a lot more tolerable than "kernel memory corruption". do_last() calling conventions make it vulnerable to the latter, and as far as nd->stack underruns that's it, but I'm not sure we don't have other places where such bug in driver, etc. would translate into mess ;-/ OK, in any case, let's start with checking if Dmitry is seeing that and not something else. I still don't understand his stack traces - the fault address quoted in his first posting doesn't match the register values in the same trace, and there's also a possibility that it's an RCU-related crap. This should give a warning and prevent an oops if we are hitting a stack underrun on bogus positive from do_last(). Dmitry, could you try to build with delta below and run your reproducer(s)? diff --git a/fs/namei.c b/fs/namei.c index f624d13..e30deef 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -3273,6 +3273,10 @@ opened: goto exit_fput; } out: + if (unlikely(error > 0)) { + WARN_ON(1); + error = -EINVAL; + } if (got_write) mnt_drop_write(nd->path.mnt); path_put(&save_parent);
WARNING: multiple messages have this Message-ID (diff)
From: Al Viro <viro@ZenIV.linux.org.uk> To: "Mickaël Salaün" <mic@digikod.net> Cc: Dmitry Vyukov <dvyukov@google.com>, "linux-fsdevel@vger.kernel.org" <linux-fsdevel@vger.kernel.org>, LKML <linux-kernel@vger.kernel.org>, syzkaller <syzkaller@googlegroups.com>, Kostya Serebryany <kcc@google.com>, Alexander Potapenko <glider@google.com>, Sasha Levin <sasha.levin@oracle.com> Subject: Re: fs: NULL deref in atime_needs_update Date: Sat, 20 Feb 2016 17:10:45 +0000 [thread overview] Message-ID: <20160220171044.GH17997@ZenIV.linux.org.uk> (raw) In-Reply-To: <56C86954.6030101@digikod.net> On Sat, Feb 20, 2016 at 02:25:40PM +0100, Micka�l Sala�n wrote: > I think the bug may be somewhere in the nd->depth handling (when its value is 0) in fs/namei.c:get_link(): struct saved *last = nd->stack + nd->depth - 1 Getting there with nd->depth == 0 would certainly be a bug - it would mean that we got there without should_follow_link() having returned 1. In case of open() it would be "do_last() has returned positive without should_follow_link() having returned 1". <looks> OK, there are several places where we rely on not getting bogus return values - inode_permission() should not return positives, neither should vfs_open(), security_path_truncate() and notify_change(). Other similar "handle the last component" functions are guaranteed to never return positives other than directly from should_follow_link(), so they are OK. IIRC, you used LSM to inject a positive value to inode_permission(), right? Another way to trigger that would've been ->open() returning positive - a bug on *anything* since ->open() had been introduced in 0.95. Amount of harm would vary - e.g. 0.95 would simply have that positive number returned to userland, looking like successful open(2). With no new descriptor, of course... Short-term we probably want just if (unlikely(error > 0)) { WARN_ON(1); error = -EINVAL; } added right after out: in do_last(), try to trigger Dmitry's reproducers on it and then work back to the source of that thing *if* that's what's happening in his case. Yours almost certainly is just that. Longer-term... I'm not sure. Having a method that is supposed to return 0 or -E<something> actually return positive is going to be a bad thing, no matter what, but "that bogus value gets passed to userland" is a lot more tolerable than "kernel memory corruption". do_last() calling conventions make it vulnerable to the latter, and as far as nd->stack underruns that's it, but I'm not sure we don't have other places where such bug in driver, etc. would translate into mess ;-/ OK, in any case, let's start with checking if Dmitry is seeing that and not something else. I still don't understand his stack traces - the fault address quoted in his first posting doesn't match the register values in the same trace, and there's also a possibility that it's an RCU-related crap. This should give a warning and prevent an oops if we are hitting a stack underrun on bogus positive from do_last(). Dmitry, could you try to build with delta below and run your reproducer(s)? diff --git a/fs/namei.c b/fs/namei.c index f624d13..e30deef 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -3273,6 +3273,10 @@ opened: goto exit_fput; } out: + if (unlikely(error > 0)) { + WARN_ON(1); + error = -EINVAL; + } if (got_write) mnt_drop_write(nd->path.mnt); path_put(&save_parent);
next prev parent reply other threads:[~2016-02-20 17:10 UTC|newest] Thread overview: 49+ messages / expand[flat|nested] mbox.gz Atom feed top 2016-02-05 21:11 fs: NULL deref in atime_needs_update Dmitry Vyukov 2016-02-16 23:40 ` Mickaël Salaün 2016-02-19 19:32 ` Dmitry Vyukov 2016-02-20 3:21 ` Al Viro 2016-02-20 3:54 ` Al Viro 2016-02-20 3:54 ` Al Viro 2016-02-20 13:25 ` Mickaël Salaün 2016-02-20 17:10 ` Al Viro [this message] 2016-02-20 17:10 ` Al Viro 2016-02-20 20:26 ` Mickaël Salaün 2016-02-20 20:50 ` Al Viro 2016-02-20 20:50 ` Al Viro 2016-02-22 11:20 ` Dmitry Vyukov 2016-02-22 17:23 ` Al Viro 2016-02-23 15:34 ` Dmitry Vyukov 2016-02-23 18:17 ` Al Viro 2016-02-20 10:36 ` Dmitry Vyukov 2016-02-24 3:12 ` Ian Kent 2016-02-24 4:46 ` Al Viro 2016-02-24 4:46 ` Al Viro 2016-02-24 10:03 ` Dmitry Vyukov 2016-02-24 10:15 ` Dmitry Vyukov 2016-02-24 13:35 ` Dmitry Vyukov 2016-02-24 15:15 ` Al Viro 2016-02-25 8:29 ` Dmitry Vyukov 2016-02-25 16:39 ` Al Viro 2016-02-26 21:21 ` Al Viro 2016-02-26 21:25 ` Dmitry Vyukov 2016-02-26 22:07 ` Al Viro 2016-02-26 22:07 ` Al Viro 2016-02-27 22:27 ` Al Viro 2016-02-27 22:27 ` Al Viro 2016-02-28 15:43 ` Dmitry Vyukov 2016-02-28 16:04 ` Dmitry Vyukov 2016-02-28 17:01 ` Al Viro 2016-02-28 20:01 ` Al Viro 2016-02-29 9:38 ` Dmitry Vyukov 2016-02-29 12:34 ` Dmitry Vyukov 2016-02-29 16:11 ` Al Viro 2016-02-29 13:09 ` Al Viro 2016-02-29 15:54 ` Dmitry Vyukov 2016-02-29 16:19 ` Al Viro 2016-02-29 18:19 ` Dmitry Vyukov 2016-03-01 8:59 ` Dmitry Vyukov 2016-02-29 16:45 ` Linus Torvalds 2016-02-29 16:50 ` Al Viro 2016-02-29 17:20 ` Al Viro 2016-02-29 17:24 ` Linus Torvalds 2016-02-29 13:43 ` David Howells
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=20160220171044.GH17997@ZenIV.linux.org.uk \ --to=viro@zeniv.linux.org.uk \ --cc=dvyukov@google.com \ --cc=glider@google.com \ --cc=kcc@google.com \ --cc=linux-fsdevel@vger.kernel.org \ --cc=linux-kernel@vger.kernel.org \ --cc=mic@digikod.net \ --cc=sasha.levin@oracle.com \ --cc=syzkaller@googlegroups.com \ /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: linkBe 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.