diff options
author | Matthew Wilcox (Oracle) <willy@infradead.org> | 2021-10-25 19:16:34 +0100 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2021-10-25 11:27:31 -0700 |
commit | cb685432398122053f3e1dc6a1d68924e5b77be4 (patch) | |
tree | b106a405cf11e949a1495c9605c6cbc2c435a105 /mm/secretmem.c | |
parent | ac8a6eba2a117e0fdc04da62ab568d1b7ca4c8f6 (diff) | |
download | lwn-cb685432398122053f3e1dc6a1d68924e5b77be4.tar.gz lwn-cb685432398122053f3e1dc6a1d68924e5b77be4.zip |
secretmem: Prevent secretmem_users from wrapping to zero
Commit 110860541f44 ("mm/secretmem: use refcount_t instead of atomic_t")
attempted to fix the problem of secretmem_users wrapping to zero and
allowing suspend once again.
But it was reverted in commit 87066fdd2e30 ("Revert 'mm/secretmem: use
refcount_t instead of atomic_t'") because of the problems it caused - a
refcount_t was not semantically the right type to use.
Instead prevent secretmem_users from wrapping to zero by forbidding new
users if the number of users has wrapped from positive to negative.
This stops a long way short of reaching the necessary 4 billion users
where it wraps to zero again, so there's no need to be clever with
special anti-wrap types or checking the return value from atomic_inc().
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Cc: Jordy Zomer <jordy@pwning.systems>
Cc: Kees Cook <keescook@chromium.org>,
Cc: James Bottomley <James.Bottomley@HansenPartnership.com>
Cc: Mike Rapoport <rppt@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/secretmem.c')
-rw-r--r-- | mm/secretmem.c | 2 |
1 files changed, 2 insertions, 0 deletions
diff --git a/mm/secretmem.c b/mm/secretmem.c index 030f02ddc7c1..c2dda408bb36 100644 --- a/mm/secretmem.c +++ b/mm/secretmem.c @@ -203,6 +203,8 @@ SYSCALL_DEFINE1(memfd_secret, unsigned int, flags) if (flags & ~(SECRETMEM_FLAGS_MASK | O_CLOEXEC)) return -EINVAL; + if (atomic_read(&secretmem_users) < 0) + return -ENFILE; fd = get_unused_fd_flags(flags & O_CLOEXEC); if (fd < 0) |