selftests/core: add regression test for CLOSE_RANGE_UNSHARE | CLOSE_RANGE_CLOEXEC

This test is a minimalized version of the reproducer given by syzbot
(cf. [1]).

After introducing CLOSE_RANGE_CLOEXEC syzbot reported a crash when
CLOSE_RANGE_CLOEXEC is specified in conjunction with
CLOSE_RANGE_UNSHARE.  When CLOSE_RANGE_UNSHARE is specified the caller
will receive a private file descriptor table in case their file
descriptor table is currently shared. When the caller requests that all
file descriptors are supposed to be operated on via e.g. a call like
close_range(3, ~0U) and the caller shares their file descriptor table
then the kernel will only copy all files in the range from 0 to 3 and no
others.
The original bug used the maximum of the old file descriptor table not
the new one. In order to test this bug we need to first create a huge
large gap in the fd table. When we now call CLOSE_RANGE_UNSHARE with a
shared fd table and and with ~0U as upper bound the kernel will only
copy up to fd1 file descriptors into the new fd table. If max_fd in the
close_range() codepaths isn't correctly set when requesting
CLOSE_RANGE_CLOEXEC with all of these fds we will see NULL pointer
derefs!

This test passes on a fixed kernel.

Cc: Giuseppe Scrivano <gscrivan@redhat.com>
[1]: https://syzkaller.appspot.com/text?tag=KernelConfig&x=db720fe37a6a41d8
Link: syzbot+96cfd2b22b3213646a93@syzkaller.appspotmail.com
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
2 files changed