fs.openat2.unknown_flags.v5.14
-----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQRAhzRXHqcMeLMyaSiRxhvAZXjcogUCYNnKewAKCRCRxhvAZXjc oo/DAQCgKsDJTSht/QXuA0bMqdsQW27AWFfKacbk5lY4EjXz1gD/ZsYU2Si1fgkB 7mEl32JsfgcIBv0VdIulAh2F29Fa0A0= =/b8l -----END PGP SIGNATURE----- Merge tag 'fs.openat2.unknown_flags.v5.14' of git://git.kernel.org/pub/scm/linux/kernel/git/brauner/linux Pull openat2 fixes from Christian Brauner: - Remove the unused VALID_UPGRADE_FLAGS define we carried from an extension to openat2() that we haven't merged. Aleksa might be getting back to it at some point but just not right now. - openat2() used to accidently ignore unknown flag values in the upper 32 bits. The new openat2() syscall verifies that no unknown O-flag values are set and returns an error to userspace if they are while the older open syscalls like open() and openat() simply ignore unknown flag values: #define O_FLAG_CURRENTLY_INVALID (1 << 31) struct open_how how = { .flags = O_RDONLY | O_FLAG_CURRENTLY_INVALID, .resolve = 0, }; /* fails */ fd = openat2(-EBADF, "/dev/null", &how, sizeof(how)); /* succeeds */ fd = openat(-EBADF, "/dev/null", O_RDONLY | O_FLAG_CURRENTLY_INVALID); However, openat2() silently truncates the upper 32 bits meaning: #define O_FLAG_CURRENTLY_INVALID_LOWER32 (1 << 31) #define O_FLAG_CURRENTLY_INVALID_UPPER32 (1 << 40) struct open_how how_lowe32 = { .flags = O_RDONLY | O_FLAG_CURRENTLY_INVALID_LOWER32, }; struct open_how how_upper32 = { .flags = O_RDONLY | O_FLAG_CURRENTLY_INVALID_UPPER32, }; /* fails */ fd = openat2(-EBADF, "/dev/null", &how_lower32, sizeof(how_lower32)); /* succeeds */ fd = openat2(-EBADF, "/dev/null", &how_upper32, sizeof(how_upper32)); Fix this by preventing the immediate truncation in build_open_flags() and add a compile-time check to catch when we add flags in the upper 32 bit range. * tag 'fs.openat2.unknown_flags.v5.14' of git://git.kernel.org/pub/scm/linux/kernel/git/brauner/linux: test: add openat2() test for invalid upper 32 bit flag value open: don't silently ignore unknown O-flags in openat2() fcntl: remove unused VALID_UPGRADE_FLAGS
This commit is contained in:
commit
b97902b62a
14
fs/open.c
14
fs/open.c
@ -1002,12 +1002,20 @@ inline struct open_how build_open_how(int flags, umode_t mode)
|
||||
|
||||
inline int build_open_flags(const struct open_how *how, struct open_flags *op)
|
||||
{
|
||||
int flags = how->flags;
|
||||
u64 flags = how->flags;
|
||||
u64 strip = FMODE_NONOTIFY | O_CLOEXEC;
|
||||
int lookup_flags = 0;
|
||||
int acc_mode = ACC_MODE(flags);
|
||||
|
||||
/* Must never be set by userspace */
|
||||
flags &= ~(FMODE_NONOTIFY | O_CLOEXEC);
|
||||
BUILD_BUG_ON_MSG(upper_32_bits(VALID_OPEN_FLAGS),
|
||||
"struct open_flags doesn't yet handle flags > 32 bits");
|
||||
|
||||
/*
|
||||
* Strip flags that either shouldn't be set by userspace like
|
||||
* FMODE_NONOTIFY or that aren't relevant in determining struct
|
||||
* open_flags like O_CLOEXEC.
|
||||
*/
|
||||
flags &= ~strip;
|
||||
|
||||
/*
|
||||
* Older syscalls implicitly clear all of the invalid flags or argument
|
||||
|
@ -12,10 +12,6 @@
|
||||
FASYNC | O_DIRECT | O_LARGEFILE | O_DIRECTORY | O_NOFOLLOW | \
|
||||
O_NOATIME | O_CLOEXEC | O_PATH | __O_TMPFILE)
|
||||
|
||||
/* List of all valid flags for the how->upgrade_mask argument: */
|
||||
#define VALID_UPGRADE_FLAGS \
|
||||
(UPGRADE_NOWRITE | UPGRADE_NOREAD)
|
||||
|
||||
/* List of all valid flags for the how->resolve argument: */
|
||||
#define VALID_RESOLVE_FLAGS \
|
||||
(RESOLVE_NO_XDEV | RESOLVE_NO_MAGICLINKS | RESOLVE_NO_SYMLINKS | \
|
||||
|
@ -155,7 +155,7 @@ struct flag_test {
|
||||
int err;
|
||||
};
|
||||
|
||||
#define NUM_OPENAT2_FLAG_TESTS 24
|
||||
#define NUM_OPENAT2_FLAG_TESTS 25
|
||||
|
||||
void test_openat2_flags(void)
|
||||
{
|
||||
@ -229,6 +229,11 @@ void test_openat2_flags(void)
|
||||
{ .name = "invalid how.resolve and O_PATH",
|
||||
.how.flags = O_PATH,
|
||||
.how.resolve = 0x1337, .err = -EINVAL },
|
||||
|
||||
/* currently unknown upper 32 bit rejected. */
|
||||
{ .name = "currently unknown bit (1 << 63)",
|
||||
.how.flags = O_RDONLY | (1ULL << 63),
|
||||
.how.resolve = 0, .err = -EINVAL },
|
||||
};
|
||||
|
||||
BUILD_BUG_ON(ARRAY_LEN(tests) != NUM_OPENAT2_FLAG_TESTS);
|
||||
|
Loading…
Reference in New Issue
Block a user