2017-04-09 05:40:33

by Al Viro

[permalink] [raw]
Subject: [git pull] vfs fixes


The following changes since commit a71c9a1c779f2499fb2afc0553e543f18aff6edf:

Linux 4.11-rc5 (2017-04-02 17:23:54 -0700)

are available in the git repository at:

git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs.git for-linus

for you to fetch changes up to a8e28440016bfb23bec266c4c66eacca6ea2d48b:

Merge branch 'work.statx' into for-next (2017-04-03 01:06:59 -0400)

----------------------------------------------------------------
Al Viro (2):
alpha: fix stack smashing in old_adjtimex(2)
Merge branch 'work.statx' into for-next

Darrick J. Wong (1):
xfs: report crtime and attribute flags to statx

David Howells (3):
ext4: Add statx support
statx: Reserve the top bit of the mask for future struct expansion
statx: Include a mask for stx_attributes in struct statx

Eric Biggers (4):
Documentation/filesystems: fix documentation for ->getattr()
statx: reject unknown flags when using NULL path
statx: remove incorrect part of vfs_statx() comment
statx: optimize copy of struct statx to userspace

Documentation/filesystems/Locking | 3 +-
Documentation/filesystems/porting | 6 +++
Documentation/filesystems/vfs.txt | 3 +-
arch/alpha/kernel/osf_sys.c | 2 +-
fs/ext4/ext4.h | 1 +
fs/ext4/file.c | 2 +-
fs/ext4/inode.c | 41 +++++++++++++++++--
fs/ext4/namei.c | 2 +
fs/ext4/symlink.c | 3 ++
fs/stat.c | 86 ++++++++++++++++++---------------------
fs/xfs/xfs_iops.c | 14 +++++++
include/linux/stat.h | 1 +
include/uapi/linux/stat.h | 5 ++-
samples/statx/test-statx.c | 12 ++++--
14 files changed, 120 insertions(+), 61 deletions(-)


2017-04-11 06:10:21

by Linus Torvalds

[permalink] [raw]
Subject: Re: [git pull] vfs fixes

Hey Al,
mind looking at fs/namei,c line 2186:

if (likely(!nd_jump_root(nd)))
return s;
nd->root.mnt = NULL;
--> rcu_read_unlock(); <--
return ERR_PTR(-ECHILD);

because that rcu_read_unlock() looks odd.

It looks odd because the lock part is

if (flags & LOOKUP_RCU)
rcu_read_lock();

ie it's locked conditionally, and the code in between does not seem to
return every time LOOKUP_RCU is clear.

So mind giving this a look? Is it as obviously buggy as I think it is,
or is there something I'm missing?

Linus

2017-04-11 06:48:43

by Al Viro

[permalink] [raw]
Subject: Re: [git pull] vfs fixes

On Mon, Apr 10, 2017 at 11:10:19PM -0700, Linus Torvalds wrote:

> It looks odd because the lock part is
>
> if (flags & LOOKUP_RCU)
> rcu_read_lock();
>
> ie it's locked conditionally, and the code in between does not seem to
> return every time LOOKUP_RCU is clear.
>
> So mind giving this a look? Is it as obviously buggy as I think it is,
> or is there something I'm missing?

It's more obscure than I would like, and can grow into a bug one day, but...
nd_jump_root() can only return non-zero if you have LOOKUP_RCU. So without
LOOKUP_RCU in flags, this
if (flags & LOOKUP_RCU)
rcu_read_lock();
set_root(nd);
if (likely(!nd_jump_root(nd)))
return s;
nd->root.mnt = NULL;
rcu_read_unlock();
won't get to that rcu_read_unlock() at all - it'll get zero from nd_jump_root()
and proceed to return s;

2017-04-11 21:02:25

by Andreas Dilger

[permalink] [raw]
Subject: Re: [git pull] vfs fixes

On Apr 11, 2017, at 12:48 AM, Al Viro <[email protected]> wrote:
> On Mon, Apr 10, 2017 at 11:10:19PM -0700, Linus Torvalds wrote:
>
>> It looks odd because the lock part is
>>
>> if (flags & LOOKUP_RCU)
>> rcu_read_lock();
>>
>> ie it's locked conditionally, and the code in between does not seem to
>> return every time LOOKUP_RCU is clear.
>>
>> So mind giving this a look? Is it as obviously buggy as I think it is,
>> or is there something I'm missing?
>
> It's more obscure than I would like, and can grow into a bug one day, but...
> nd_jump_root() can only return non-zero if you have LOOKUP_RCU. So without
> LOOKUP_RCU in flags, this
> if (flags & LOOKUP_RCU)
> rcu_read_lock();
> set_root(nd);
> if (likely(!nd_jump_root(nd)))
> return s;
> nd->root.mnt = NULL;
> rcu_read_unlock();
> won't get to that rcu_read_unlock() at all - it'll get zero from nd_jump_root()
> and proceed to return s;

So possibly a comment like the following would be helpful:

rcu_read_unlock(); /* nd_jump_root() returns if !LOOKUP_RCU */

so that us mere mortals have a chance to understand this in the future?

Cheers, Andreas






Attachments:
signature.asc (195.00 B)
Message signed with OpenPGP

2017-04-12 07:00:30

by Linus Torvalds

[permalink] [raw]
Subject: Re: [git pull] vfs fixes

On Tue, Apr 11, 2017 at 2:02 PM, Andreas Dilger <[email protected]> wrote:
> On Apr 11, 2017, at 12:48 AM, Al Viro <[email protected]> wrote:
>>
>> It's more obscure than I would like, and can grow into a bug one day, but...
>> nd_jump_root() can only return non-zero if you have LOOKUP_RCU.
>
> So possibly a comment like the following would be helpful:
>
> rcu_read_unlock(); /* nd_jump_root() returns if !LOOKUP_RCU */
>
> so that us mere mortals have a chance to understand this in the future?

That might be good, but the reason I noticed this at all was that I
looked at all those "if (LOOKUP_RCU)" in that function, and was
thinking that the whole function would be better being split up into
the RCU case and the non-RCU case. Because the two cases do have
shared code, but the sharing is almost less than the non-shared stuff.

And when I started doing that split to see what it looked like, that
rcu_read_unlock() really stood out like a sore thumb.

Linus

2017-04-15 06:41:09

by Vegard Nossum

[permalink] [raw]
Subject: Re: [git pull] vfs fixes

On 9 April 2017 at 07:40, Al Viro <[email protected]> wrote:
>
> The following changes since commit a71c9a1c779f2499fb2afc0553e543f18aff6edf:
>
> Linux 4.11-rc5 (2017-04-02 17:23:54 -0700)
>
> are available in the git repository at:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs.git for-linus
>
> for you to fetch changes up to a8e28440016bfb23bec266c4c66eacca6ea2d48b:
>
> Merge branch 'work.statx' into for-next (2017-04-03 01:06:59 -0400)
>
> ----------------------------------------------------------------
> Al Viro (2):
> alpha: fix stack smashing in old_adjtimex(2)
> Merge branch 'work.statx' into for-next

I'm seeing the same memfd_create/name_to_handle_at/path_lookupat
use-after-free that Dmitry was seeing here:

https://lkml.org/lkml/2017/3/4/118

I haven't tried the patch from that thread yet, but was there any
reason for it not to get merged so far?


Vegard

2017-04-15 16:51:45

by Linus Torvalds

[permalink] [raw]
Subject: Re: [git pull] vfs fixes

On Fri, Apr 14, 2017 at 11:41 PM, Vegard Nossum <[email protected]> wrote:
>
> I'm seeing the same memfd_create/name_to_handle_at/path_lookupat
> use-after-free that Dmitry was seeing here:

Ok, see if that is gone in current git with commit c0eb027e5aef ("vfs:
don't do RCU lookup of empty pathnames")

Linus

2017-04-15 17:08:48

by Al Viro

[permalink] [raw]
Subject: Re: [git pull] vfs fixes

On Sat, Apr 15, 2017 at 09:51:40AM -0700, Linus Torvalds wrote:
> On Fri, Apr 14, 2017 at 11:41 PM, Vegard Nossum <[email protected]> wrote:
> >
> > I'm seeing the same memfd_create/name_to_handle_at/path_lookupat
> > use-after-free that Dmitry was seeing here:
>
> Ok, see if that is gone in current git with commit c0eb027e5aef ("vfs:
> don't do RCU lookup of empty pathnames")

FWIW, I'm finishing testing of fixes for crap found during the discussion
of that stuff last week (making sure that mntns_install() can't be abused
into setting ->fs->root/->fs->pwd to dentry of NFS referral and its ilk
and doing that in a sane way).