diff --git a/sys/compat/linux/linux_dummy.c b/sys/compat/linux/linux_dummy.c --- a/sys/compat/linux/linux_dummy.c +++ b/sys/compat/linux/linux_dummy.c @@ -135,7 +135,6 @@ DUMMY(fsmount); DUMMY(fspick); DUMMY(pidfd_open); -DUMMY(close_range); DUMMY(openat2); DUMMY(pidfd_getfd); DUMMY(process_madvise); diff --git a/sys/compat/linux/linux_file.h b/sys/compat/linux/linux_file.h --- a/sys/compat/linux/linux_file.h +++ b/sys/compat/linux/linux_file.h @@ -197,4 +197,7 @@ unsigned char f_handle[0]; }; +#define LINUX_CLOSE_RANGE_UNSHARE (1U << 1) +#define LINUX_CLOSE_RANGE_CLOEXEC (1U << 2) + #endif /* !_LINUX_FILE_H_ */ diff --git a/sys/compat/linux/linux_file.c b/sys/compat/linux/linux_file.c --- a/sys/compat/linux/linux_file.c +++ b/sys/compat/linux/linux_file.c @@ -1806,3 +1806,34 @@ */ return (EINVAL); } + +int +linux_close_range(struct thread *td, struct linux_close_range_args *args) +{ + u_int flags = 0; + + /* + * Due to the fact that the Linux does not make distinction between + * processes and threads, sharing process resources, including filedesc + * table, is at thread level in the Linux, while in the FreeBSD is at + * process level. Implementing close_range(CLOSE_RANGE_UNSHARE) allows + * Linux to unshare filedesc table of the calling thread from others + * threads in a thread group (i.e., process in the FreeBSD) or others + * processes, which shares the same table, before closing files. + * The primary goal is to avoid reaces between threads and gracefully + * close files before execve call.Thats strange, as to raceless + * garantie anyway there should be some synchronization point at the + * user space level to avoid files manipulation after close and before + * execve. And in that case the CLOSE_RANGE_UNSSHARE is not needed. + * Simply speaking, leave implementing of this flag till better times. + * XXX. Perhaps, the flag should be silencly ignored. + */ + + if ((args->flags & ~(LINUX_CLOSE_RANGE_CLOEXEC)) != 0) + return (EINVAL); + if (args->first > args->last) + return (EINVAL); + if ((args->flags & LINUX_CLOSE_RANGE_CLOEXEC) != 0) + flags |= CLOSE_RANGE_CLOEXEC; + return (kern_close_range(td, flags, args->first, args->last)); +}