login: use close_range() system call when possible

This system call was added while back, but does not have glibc support yet.
Lets try to use the new facility early on.  The promise in reference link is
that the new call is faster, and works when /proc is not mounted.

Reference: https://lwn.net/Articles/789000/
Reference: https://lwn.net/Articles/789023/
Reference: https://kernelnewbies.org/LinuxChanges#Linux_5.9.New_close_range.28.29_system_call_for_easier_closing_of_file_descriptors
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
This commit is contained in:
Sami Kerola 2020-11-14 12:55:10 +00:00
parent 931e60982e
commit f0649c0d83
No known key found for this signature in database
GPG Key ID: 0D46FEF7E61DBB46
3 changed files with 22 additions and 1 deletions

View File

@ -497,6 +497,7 @@ AC_CHECK_DECL([SO_PASSCRED],
AC_CHECK_FUNCS([ \
clearenv \
close_range \
__fpurge \
fpurge \
__fpending \
@ -571,6 +572,7 @@ AS_IF([test "x$ul_cv_syscall_setns" = xno], [
UL_CHECK_SYSCALL([pidfd_open])
UL_CHECK_SYSCALL([pidfd_send_signal])
UL_CHECK_SYSCALL([close_range])
AC_CHECK_FUNCS([isnan], [],
[AC_CHECK_LIB([m], [isnan], [MATH_LIBS="-lm"])]

View File

@ -72,6 +72,20 @@ static inline struct dirent *xreaddir(DIR *dp)
return d;
}
#if defined(__linux__)
# include <sys/syscall.h>
# if defined(SYS_close_range)
# include <sys/types.h>
# ifndef HAVE_CLOSE_RANGE
static inline int close_range(unsigned int first, unsigned int last)
{
return syscall(SYS_close_range, first, last);
}
# endif
# define HAVE_CLOSE_RANGE 1
# endif /* SYS_close_range */
#endif /* __linux__ */
extern void close_all_fds(const int exclude[], size_t exsz);
#define UL_COPY_READ_ERROR (-1)

View File

@ -1294,9 +1294,11 @@ static void initialize(int argc, char **argv, struct login_context *cxt)
{"version", no_argument, NULL, 'V'},
{NULL, 0, NULL, 0}
};
#ifndef HAVE_CLOSE_RANGE
const int wanted_fds[] = {
STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO
};
#endif
timeout = (unsigned int)getlogindefs_num("LOGIN_TIMEOUT", LOGIN_TIMEOUT);
@ -1365,8 +1367,11 @@ static void initialize(int argc, char **argv, struct login_context *cxt)
*p++ = ' ';
#endif
}
#ifdef HAVE_CLOSE_RANGE
close_range(STDERR_FILENO + 1, ~0U);
#else
close_all_fds(wanted_fds, ARRAY_SIZE(wanted_fds));
#endif
}
int main(int argc, char **argv)