Hi Linus, /* Summary */ syzbot reported a bug when asking close_range() to unshare the file descriptor table and making all fds close-on-exec. If CLOSE_RANGE_UNSHARE the caller will receive a private file descriptor table in case their file descriptor table is currently shared before operating on the requested file descriptor range. For the case where the caller has requested all file descriptors to be actually closed via e.g. close_range(3, ~0U, CLOSE_RANGE_UNSHARE) the kernel knows that the caller does not need any of the file descriptors anymore and will optimize the close operation by only copying all files in the range from 0 to 3 and no others. However, if the caller requested CLOSE_RANGE_CLOEXEC together with CLOSE_RANGE_UNSHARE the caller wants to still make use of the file descriptors so the kernel needs to copy all of them and can't optimize.
The original patch didn't account for this and thus could cause oopses as evidenced by the syzbot report because it assumed that all fds had been copied. Fix this by handling the CLOSE_RANGE_CLOEXEC case and copying all fds if the two flags are specified together. This should've been caught in the selftests but the original patch didn't cover this case and I didn't catch it during review. So in addition to the bugfix I'm also adding selftests. They will reliably reproduce the bug on a non-fixed kernel and allows us to catch regressions and verify correct behavior. Note, the kernel selftest tree contained a bunch of changes that made the original selftest fail to compile so there are small fixups in this pr to make them compile without warnings. The following changes since commit accefff5b547a9a1d959c7e76ad539bf2480e78b: Merge tag 'arm-soc-omap-genpd-5.11' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc (2020-12-16 16:53:54 -0800) are available in the Git repository at: g...@gitolite.kernel.org:pub/scm/linux/kernel/git/brauner/linux tags/close-range-cloexec-unshare-v5.11 for you to fetch changes up to 6abc20f8f879d891930f37186b19c9dc3ecc34dd: selftests/core: add regression test for CLOSE_RANGE_UNSHARE | CLOSE_RANGE_CLOEXEC (2020-12-19 16:23:19 +0100) /* Testing */ No build failures or warnings were observed. All old and new tests are passing. The selftests manage to reliably reproduce the bug on a non-fixed kernel and pass on a fixed kernel. Syzbot reported the bug gone with the fix in this pr. /* Conflicts */ At the time of creating this PR no merge conflicts were reported when test-pulling the tag into current mainline at 3644e2d2dda7 ("mm/filemap: fix infinite loop in generic_file_buffered_read()"). Please consider pulling these changes from the signed close-range-cloexec-unshare-v5.11 tag. Thanks! Christian ---------------------------------------------------------------- close-range-cloexec-unshare-v5.11 ---------------------------------------------------------------- Christian Brauner (4): close_range: unshare all fds for CLOSE_RANGE_UNSHARE | CLOSE_RANGE_CLOEXEC selftests/core: handle missing syscall number for close_range selftests/core: add test for CLOSE_RANGE_UNSHARE | CLOSE_RANGE_CLOEXEC selftests/core: add regression test for CLOSE_RANGE_UNSHARE | CLOSE_RANGE_CLOEXEC Tobias Klauser (1): selftests/core: fix close_range_test build after XFAIL removal fs/file.c | 4 +- tools/testing/selftests/core/close_range_test.c | 281 +++++++++++++++++++++++- 2 files changed, 278 insertions(+), 7 deletions(-)