From: Al Viro <viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn@public.gmane.org>
To: Aleksa Sarai <cyphar-gVpy/LI/lHzQT0dZR+AlfA@public.gmane.org>
Cc: Jeff Layton <jlayton-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>,
"J. Bruce Fields"
<bfields-uC3wQj2KruNg9hUCZPvPmw@public.gmane.org>,
Shuah Khan <shuah-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>,
Florian Weimer <fweimer-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>,
David Laight
<david.laight-JxhZ9S5GRejQT0dZR+AlfA@public.gmane.org>,
Christian Brauner
<christian.brauner-GeWIH/nMZzLQT0dZR+AlfA@public.gmane.org>,
quae-l4MFkWPWeOkX2WXlbB3fKg@public.gmane.org,
dev-IGmTWi+3HBZvNhPySn5qfx2eb7JE58TQ@public.gmane.org,
containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org,
libc-alpha-9JcytcrH/bA+uJoB2kUjGw@public.gmane.org,
linux-api-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-fsdevel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-kselftest-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Subject: Re: [PATCH v3 0/2] openat2: minor uapi cleanups
Date: Sat, 18 Jan 2020 18:09:41 +0000 [thread overview]
Message-ID: <20200118180941.GT8904@ZenIV.linux.org.uk> (raw)
In-Reply-To: <20200118152833.GS8904-3bDd1+5oDREiFSDQTTA3OLVCufUGDwFn@public.gmane.org>
On Sat, Jan 18, 2020 at 03:28:33PM +0000, Al Viro wrote:
> #work.openat2 updated, #for-next rebuilt and force-pushed. There's
> a massive update of #work.namei as well, also pushed out; not in
> #for-next yet, will post the patch series for review later today.
BTW, looking through that code again, how could this
static bool legitimize_root(struct nameidata *nd)
{
/*
* For scoped-lookups (where nd->root has been zeroed), we need to
* restart the whole lookup from scratch -- because set_root() is wrong
* for these lookups (nd->dfd is the root, not the filesystem root).
*/
if (!nd->root.mnt && (nd->flags & LOOKUP_IS_SCOPED))
return false;
possibly trigger? The only things that ever clean ->root.mnt are
1) failing legitimize_path(nd, &nd->root, nd->root_seq) in
legitimize_root() itself. If *ANY* legitimize_path() has failed,
we are through - RCU pathwalk is given up. In particular, if you
look at the call chains leading to legitimize_root(), you'll see
that it's called by unlazy_walk() or unlazy_child() and failure
has either of those buggger off immediately. The same goes for
their callers; fail any of those and we are done; the very next
thing that will be done with that nameidata is going to be
terminate_walk(). We don't look at its fields, etc. - just return
to the top level ASAP and call terminate_walk() on it. Which is where
we run into
if (nd->flags & LOOKUP_ROOT_GRABBED) {
path_put(&nd->root);
nd->flags &= ~LOOKUP_ROOT_GRABBED;
}
paired with setting LOOKUP_ROOT_GRABBED just before the attempt
to legitimize in legitimize_root(). The next thing *after*
terminate_walk() is either path_init() or the end of life for
that struct nameidata instance.
This is really, really fundamental for understanding the whole
thing - a failure of unlazy_walk/unlazy_child means that we are through
with that attempt.
2) complete_walk() doing
if (!(nd->flags & (LOOKUP_ROOT | LOOKUP_IS_SCOPED)))
nd->root.mnt = NULL;
Can't happen with LOOKUP_IS_SCOPED in flags, obviously.
3) path_init(). Where it's followed either by leaving through
if (*s == '/' && !(flags & LOOKUP_IN_ROOT)) {
....
}
(and LOOKUP_IS_SCOPED includes LOOKUP_IN_ROOT) or with a failure exit
(no calls of *anything* but terminate_walk() after that or with
if (flags & LOOKUP_IS_SCOPED) {
nd->root = nd->path;
... and that makes damn sure nd->root.mnt is not NULL.
And neither of the LOOKUP_IS_SCOPED bits ever gets changed in nd->flags -
they remain as path_init() has set them.
The same, BTW, goes for the check you've added in the beginning of
set_root() - set_root() is called only with NULL nd->root.mnt (trivial to
prove) and that is incompatible with LOOKUP_IS_SCOPED. I'm kinda-sorta
OK with having WARN_ON() there for a while, but IMO the check in the
beginning of legitimize_root() should go away - this kind of defensive
programming only makes harder to reason about the behaviour of the
entire thing. And fs/namei.c is too convoluted as it is...
WARNING: multiple messages have this Message-ID (diff)
From: Al Viro <viro@zeniv.linux.org.uk>
To: Aleksa Sarai <cyphar@cyphar.com>
Cc: Jeff Layton <jlayton@kernel.org>,
"J. Bruce Fields" <bfields@fieldses.org>,
Shuah Khan <shuah@kernel.org>,
Florian Weimer <fweimer@redhat.com>,
David Laight <david.laight@aculab.com>,
Christian Brauner <christian.brauner@ubuntu.com>,
quae@daurnimator.com, dev@opencontainers.org,
containers@lists.linux-foundation.org, libc-alpha@sourceware.org,
linux-api@vger.kernel.org, linux-fsdevel@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org
Subject: Re: [PATCH v3 0/2] openat2: minor uapi cleanups
Date: Sat, 18 Jan 2020 18:09:41 +0000 [thread overview]
Message-ID: <20200118180941.GT8904@ZenIV.linux.org.uk> (raw)
In-Reply-To: <20200118152833.GS8904@ZenIV.linux.org.uk>
On Sat, Jan 18, 2020 at 03:28:33PM +0000, Al Viro wrote:
> #work.openat2 updated, #for-next rebuilt and force-pushed. There's
> a massive update of #work.namei as well, also pushed out; not in
> #for-next yet, will post the patch series for review later today.
BTW, looking through that code again, how could this
static bool legitimize_root(struct nameidata *nd)
{
/*
* For scoped-lookups (where nd->root has been zeroed), we need to
* restart the whole lookup from scratch -- because set_root() is wrong
* for these lookups (nd->dfd is the root, not the filesystem root).
*/
if (!nd->root.mnt && (nd->flags & LOOKUP_IS_SCOPED))
return false;
possibly trigger? The only things that ever clean ->root.mnt are
1) failing legitimize_path(nd, &nd->root, nd->root_seq) in
legitimize_root() itself. If *ANY* legitimize_path() has failed,
we are through - RCU pathwalk is given up. In particular, if you
look at the call chains leading to legitimize_root(), you'll see
that it's called by unlazy_walk() or unlazy_child() and failure
has either of those buggger off immediately. The same goes for
their callers; fail any of those and we are done; the very next
thing that will be done with that nameidata is going to be
terminate_walk(). We don't look at its fields, etc. - just return
to the top level ASAP and call terminate_walk() on it. Which is where
we run into
if (nd->flags & LOOKUP_ROOT_GRABBED) {
path_put(&nd->root);
nd->flags &= ~LOOKUP_ROOT_GRABBED;
}
paired with setting LOOKUP_ROOT_GRABBED just before the attempt
to legitimize in legitimize_root(). The next thing *after*
terminate_walk() is either path_init() or the end of life for
that struct nameidata instance.
This is really, really fundamental for understanding the whole
thing - a failure of unlazy_walk/unlazy_child means that we are through
with that attempt.
2) complete_walk() doing
if (!(nd->flags & (LOOKUP_ROOT | LOOKUP_IS_SCOPED)))
nd->root.mnt = NULL;
Can't happen with LOOKUP_IS_SCOPED in flags, obviously.
3) path_init(). Where it's followed either by leaving through
if (*s == '/' && !(flags & LOOKUP_IN_ROOT)) {
....
}
(and LOOKUP_IS_SCOPED includes LOOKUP_IN_ROOT) or with a failure exit
(no calls of *anything* but terminate_walk() after that or with
if (flags & LOOKUP_IS_SCOPED) {
nd->root = nd->path;
... and that makes damn sure nd->root.mnt is not NULL.
And neither of the LOOKUP_IS_SCOPED bits ever gets changed in nd->flags -
they remain as path_init() has set them.
The same, BTW, goes for the check you've added in the beginning of
set_root() - set_root() is called only with NULL nd->root.mnt (trivial to
prove) and that is incompatible with LOOKUP_IS_SCOPED. I'm kinda-sorta
OK with having WARN_ON() there for a while, but IMO the check in the
beginning of legitimize_root() should go away - this kind of defensive
programming only makes harder to reason about the behaviour of the
entire thing. And fs/namei.c is too convoluted as it is...
next prev parent reply other threads:[~2020-01-18 18:09 UTC|newest]
Thread overview: 104+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-12-30 5:20 [PATCH RFC 0/1] mount: universally disallow mounting over symlinks Aleksa Sarai
2019-12-30 5:20 ` [PATCH RFC 1/1] " Aleksa Sarai
2019-12-30 5:20 ` Aleksa Sarai
2019-12-30 7:34 ` Linus Torvalds
2019-12-30 8:28 ` Aleksa Sarai
2020-01-08 4:39 ` Andy Lutomirski
2019-12-30 5:44 ` [PATCH RFC 0/1] " Al Viro
2019-12-30 5:49 ` Aleksa Sarai
2019-12-30 7:29 ` Aleksa Sarai
2019-12-30 7:53 ` Linus Torvalds
2019-12-30 8:32 ` Aleksa Sarai
2020-01-02 8:58 ` David Laight
2020-01-02 9:09 ` Aleksa Sarai
2020-01-01 0:43 ` Al Viro
2020-01-01 0:54 ` Al Viro
2020-01-01 3:08 ` Al Viro
2020-01-01 14:44 ` Aleksa Sarai
2020-01-01 23:40 ` Al Viro
2020-01-02 3:59 ` Aleksa Sarai
2020-01-03 1:49 ` Al Viro
2020-01-04 4:46 ` Ian Kent
2020-01-08 3:13 ` Al Viro
2020-01-08 3:54 ` Linus Torvalds
2020-01-08 21:34 ` Al Viro
2020-01-10 0:08 ` Linus Torvalds
2020-01-10 4:15 ` Al Viro
2020-01-10 5:03 ` Linus Torvalds
2020-01-10 6:20 ` Ian Kent
[not found] ` <979cf680b0fbdce515293a3449d564690cde6a3f.camel-PKsaG3nR2I+sTnJN9+BGXg@public.gmane.org>
2020-01-12 21:33 ` Al Viro
2020-01-12 21:33 ` Al Viro
2020-01-13 2:59 ` Ian Kent
2020-01-14 0:25 ` Ian Kent
2020-01-14 4:39 ` Al Viro
2020-01-14 5:01 ` Ian Kent
[not found] ` <d6cad1552171da1eb38c55d1d7b1ff45902b101f.camel-PKsaG3nR2I+sTnJN9+BGXg@public.gmane.org>
2020-01-14 5:59 ` Ian Kent
2020-01-14 5:59 ` Ian Kent
2020-01-10 21:07 ` Aleksa Sarai
2020-01-14 4:57 ` Al Viro
2020-01-14 5:12 ` Al Viro
[not found] ` <20200114045733.GW8904-3bDd1+5oDREiFSDQTTA3OLVCufUGDwFn@public.gmane.org>
2020-01-14 20:01 ` Aleksa Sarai
2020-01-14 20:01 ` Aleksa Sarai
2020-01-15 14:25 ` Al Viro
2020-01-15 14:29 ` Aleksa Sarai
2020-01-15 14:34 ` Aleksa Sarai
2020-01-15 14:48 ` Al Viro
2020-01-15 14:48 ` Al Viro
[not found] ` <20200115144831.GJ8904-3bDd1+5oDREiFSDQTTA3OLVCufUGDwFn@public.gmane.org>
2020-01-18 12:07 ` [PATCH v3 0/2] openat2: minor uapi cleanups Aleksa Sarai
2020-01-18 12:07 ` Aleksa Sarai
2020-01-18 12:07 ` [PATCH v3 1/2] open: introduce openat2(2) syscall Aleksa Sarai
2020-01-19 7:20 ` kbuild test robot
[not found] ` <20200118120800.16358-1-cyphar-gVpy/LI/lHzQT0dZR+AlfA@public.gmane.org>
2020-01-18 12:08 ` [PATCH v3 2/2] selftests: add openat2(2) selftests Aleksa Sarai
2020-01-18 12:08 ` Aleksa Sarai
2020-01-18 15:28 ` [PATCH v3 0/2] openat2: minor uapi cleanups Al Viro
[not found] ` <20200118152833.GS8904-3bDd1+5oDREiFSDQTTA3OLVCufUGDwFn@public.gmane.org>
2020-01-18 18:09 ` Al Viro [this message]
2020-01-18 18:09 ` Al Viro
[not found] ` <20200118180941.GT8904-3bDd1+5oDREiFSDQTTA3OLVCufUGDwFn@public.gmane.org>
2020-01-18 23:03 ` Aleksa Sarai
2020-01-18 23:03 ` Aleksa Sarai
2020-01-19 1:12 ` Al Viro
2020-01-15 13:57 ` [PATCH RFC 0/1] mount: universally disallow mounting over symlinks Aleksa Sarai
2020-01-19 3:14 ` [RFC][PATCHSET][CFT] pathwalk cleanups and fixes Al Viro
2020-01-19 3:14 ` Al Viro
2020-01-19 3:17 ` [PATCH 01/17] do_add_mount(): lift lock_mount/unlock_mount into callers Al Viro
2020-01-19 3:17 ` [PATCH 02/17] fix automount/automount race properly Al Viro
2020-01-30 14:34 ` Christian Brauner
2020-01-19 3:17 ` [PATCH 03/17] follow_automount(): get rid of dead^Wstillborn code Al Viro
2020-01-30 14:38 ` Christian Brauner
2020-01-19 3:17 ` [PATCH 04/17] follow_automount() doesn't need the entire nameidata Al Viro
2020-01-30 14:45 ` Christian Brauner
2020-01-30 15:38 ` Al Viro
2020-01-30 15:55 ` Al Viro
2020-01-19 3:17 ` [PATCH 05/17] make build_open_flags() treat O_CREAT | O_EXCL as implying O_NOFOLLOW Al Viro
2020-01-19 3:17 ` [PATCH 06/17] handle_mounts(): start building a sane wrapper for follow_managed() Al Viro
2020-01-19 3:17 ` [PATCH 07/17] atomic_open(): saner calling conventions (return dentry on success) Al Viro
2020-01-19 3:17 ` [PATCH 08/17] lookup_open(): " Al Viro
2020-01-19 3:17 ` [PATCH 09/17] do_last(): collapse the call of path_to_nameidata() Al Viro
2020-01-19 3:17 ` [PATCH 10/17] handle_mounts(): pass dentry in, turn path into a pure out argument Al Viro
2020-01-19 3:17 ` [PATCH 11/17] lookup_fast(): consolidate the RCU success case Al Viro
2020-01-19 3:17 ` [PATCH 12/17] teach handle_mounts() to handle RCU mode Al Viro
2020-01-19 3:17 ` [PATCH 13/17] lookup_fast(): take mount traversal into callers Al Viro
2020-01-19 3:17 ` [PATCH 14/17] new step_into() flag: WALK_NOFOLLOW Al Viro
2020-01-19 3:17 ` [PATCH 15/17] fold handle_mounts() into step_into() Al Viro
2020-01-19 3:17 ` [PATCH 16/17] LOOKUP_MOUNTPOINT: fold path_mountpointat() into path_lookupat() Al Viro
2020-01-19 3:17 ` [PATCH 17/17] expand the only remaining call of path_lookup_conditional() Al Viro
2020-01-19 3:17 ` [PATCH 1/9] merging pick_link() with get_link(), part 1 Al Viro
2020-01-19 3:17 ` [PATCH 2/9] merging pick_link() with get_link(), part 2 Al Viro
2020-01-19 3:17 ` [PATCH 3/9] merging pick_link() with get_link(), part 3 Al Viro
2020-01-19 3:17 ` [PATCH 4/9] merging pick_link() with get_link(), part 4 Al Viro
2020-01-19 3:17 ` [PATCH 5/9] merging pick_link() with get_link(), part 5 Al Viro
2020-01-19 3:17 ` [PATCH 6/9] merging pick_link() with get_link(), part 6 Al Viro
2020-01-19 3:17 ` [PATCH 7/9] finally fold get_link() into pick_link() Al Viro
2020-01-19 3:17 ` [PATCH 8/9] massage __follow_mount_rcu() a bit Al Viro
2020-01-19 3:17 ` [PATCH 9/9] new helper: traverse_mounts() Al Viro
2020-01-30 14:13 ` [PATCH 01/17] do_add_mount(): lift lock_mount/unlock_mount into callers Christian Brauner
2020-01-19 14:33 ` [RFC][PATCHSET][CFT] pathwalk cleanups and fixes Ian Kent
2020-01-10 23:19 ` [PATCH RFC 0/1] mount: universally disallow mounting over symlinks Al Viro
2020-01-13 1:48 ` Ian Kent
2020-01-13 3:54 ` Al Viro
2020-01-13 6:00 ` Ian Kent
2020-01-13 6:03 ` Ian Kent
2020-01-13 13:30 ` Al Viro
[not found] ` <20200113133047.GR8904-3bDd1+5oDREiFSDQTTA3OLVCufUGDwFn@public.gmane.org>
2020-01-14 7:25 ` Ian Kent
2020-01-14 7:25 ` Ian Kent
2020-01-14 12:17 ` Ian Kent
2020-01-04 5:52 ` Andy Lutomirski
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=20200118180941.GT8904@ZenIV.linux.org.uk \
--to=viro-rmsdqhl/ynmifsdqtta3olvcufugdwfn@public.gmane.org \
--cc=bfields-uC3wQj2KruNg9hUCZPvPmw@public.gmane.org \
--cc=christian.brauner-GeWIH/nMZzLQT0dZR+AlfA@public.gmane.org \
--cc=containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org \
--cc=cyphar-gVpy/LI/lHzQT0dZR+AlfA@public.gmane.org \
--cc=david.laight-JxhZ9S5GRejQT0dZR+AlfA@public.gmane.org \
--cc=dev-IGmTWi+3HBZvNhPySn5qfx2eb7JE58TQ@public.gmane.org \
--cc=fweimer-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org \
--cc=jlayton-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org \
--cc=libc-alpha-9JcytcrH/bA+uJoB2kUjGw@public.gmane.org \
--cc=linux-api-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=linux-fsdevel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=linux-kselftest-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=quae-l4MFkWPWeOkX2WXlbB3fKg@public.gmane.org \
--cc=shuah-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.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.