Message ID | 20201007103608.17349-1-cyphar@cyphar.com (mailing list archive) |
---|---|
State | Accepted |
Headers | show |
Series | openat2: reject RESOLVE_BENEATH|RESOLVE_IN_ROOT | expand |
On Wed, Oct 07, 2020 at 09:36:08PM +1100, Aleksa Sarai wrote: > This was an oversight in the original implementation, as it makes no > sense to specify both scoping flags to the same openat2(2) invocation > (before this patch, the result of such an invocation was equivalent to > RESOLVE_IN_ROOT being ignored). > > This is a userspace-visible ABI change, but the only user of openat2(2) > at the moment is LXC which doesn't specify both flags and so no > userspace programs will break as a result. Indeed! > > Fixes: fddb5d430ad9 ("open: introduce openat2(2) syscall") > Signed-off-by: Aleksa Sarai <cyphar@cyphar.com> > Acked-by: Christian Brauner <christian.brauner@ubuntu.com> > Cc: <stable@vger.kernel.org> # v5.6+ > --- Thanks! This is a good fix imho. Christian
On 10/7/20 4:36 AM, Aleksa Sarai wrote: > This was an oversight in the original implementation, as it makes no > sense to specify both scoping flags to the same openat2(2) invocation > (before this patch, the result of such an invocation was equivalent to > RESOLVE_IN_ROOT being ignored). > > This is a userspace-visible ABI change, but the only user of openat2(2) > at the moment is LXC which doesn't specify both flags and so no > userspace programs will break as a result. > > Cc: <stable@vger.kernel.org> # v5.6+ > Fixes: fddb5d430ad9 ("open: introduce openat2(2) syscall") > Acked-by: Christian Brauner <christian.brauner@ubuntu.com> > Signed-off-by: Aleksa Sarai <cyphar@cyphar.com> > --- > fs/open.c | 4 +++ > tools/testing/selftests/openat2/openat2_test.c | 8 +++++++- You are combining fs change with selftest change. Is there a reason why these two changes are combined? 2 separate patches is better. thanks, -- Shuah
diff --git a/fs/open.c b/fs/open.c index 9af548fb841b..4d7537ae59df 100644 --- a/fs/open.c +++ b/fs/open.c @@ -1010,6 +1010,10 @@ inline int build_open_flags(const struct open_how *how, struct open_flags *op) if (how->resolve & ~VALID_RESOLVE_FLAGS) return -EINVAL; + /* Scoping flags are mutually exclusive. */ + if ((how->resolve & RESOLVE_BENEATH) && (how->resolve & RESOLVE_IN_ROOT)) + return -EINVAL; + /* Deal with the mode. */ if (WILL_CREATE(flags)) { if (how->mode & ~S_IALLUGO) diff --git a/tools/testing/selftests/openat2/openat2_test.c b/tools/testing/selftests/openat2/openat2_test.c index b386367c606b..381d874cce99 100644 --- a/tools/testing/selftests/openat2/openat2_test.c +++ b/tools/testing/selftests/openat2/openat2_test.c @@ -155,7 +155,7 @@ struct flag_test { int err; }; -#define NUM_OPENAT2_FLAG_TESTS 23 +#define NUM_OPENAT2_FLAG_TESTS 24 void test_openat2_flags(void) { @@ -210,6 +210,12 @@ void test_openat2_flags(void) .how.flags = O_TMPFILE | O_RDWR, .how.mode = 0x0000A00000000000ULL, .err = -EINVAL }, + /* ->resolve flags must not conflict. */ + { .name = "incompatible resolve flags (BENEATH | IN_ROOT)", + .how.flags = O_RDONLY, + .how.resolve = RESOLVE_BENEATH | RESOLVE_IN_ROOT, + .err = -EINVAL }, + /* ->resolve must only contain RESOLVE_* flags. */ { .name = "invalid how.resolve and O_RDONLY", .how.flags = O_RDONLY,