summaryrefslogtreecommitdiff
path: root/src/basic/missing_syscall.h
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2020-10-13 17:53:25 +0200
committerLennart Poettering <lennart@poettering.net>2020-10-14 10:40:10 +0200
commit441e0fdb900b49888fb6d7901a2b5aa92c0a2017 (patch)
tree7296762a960b44eb8800783aaad2abae82e8420a /src/basic/missing_syscall.h
parent6ea0d25c573c6ef64f62333b7e850067a202c7ee (diff)
downloadsystemd-441e0fdb900b49888fb6d7901a2b5aa92c0a2017.tar.gz
missing: add close_range() wrapper
The syscall was added in 5.9 and is not yet exposed in glibc, hence define our own wrapper.
Diffstat (limited to 'src/basic/missing_syscall.h')
-rw-r--r--src/basic/missing_syscall.h46
1 files changed, 46 insertions, 0 deletions
diff --git a/src/basic/missing_syscall.h b/src/basic/missing_syscall.h
index c11382b564..01fec6f2f5 100644
--- a/src/basic/missing_syscall.h
+++ b/src/basic/missing_syscall.h
@@ -734,3 +734,49 @@ static inline int missing_rt_sigqueueinfo(pid_t tgid, int sig, siginfo_t *info)
# define rt_sigqueueinfo missing_rt_sigqueueinfo
#endif
+
+/* ======================================================================= */
+
+#define systemd_NR_close_range systemd_SC_arch_bias(436)
+
+/* may be (invalid) negative number due to libseccomp, see PR 13319 */
+#if defined __NR_close_range && __NR_close_range >= 0
+# if defined systemd_NR_close_range
+assert_cc(__NR_close_range == systemd_NR_close_range);
+# endif
+#else
+# if defined __NR_close_range
+# undef __NR_close_range
+# endif
+# if defined systemd_NR_close_range
+# define __NR_close_range systemd_NR_close_range
+# endif
+#endif
+
+#if !HAVE_CLOSE_RANGE
+static inline int missing_close_range(int first_fd, int end_fd, unsigned flags) {
+# ifdef __NR_close_range
+ /* Kernel-side the syscall expects fds as unsigned integers (just like close() actually), while
+ * userspace exclusively uses signed integers for fds. We don't know just yet how glibc is going to
+ * wrap this syscall, but let's assume it's going to be similar to what they do for close(),
+ * i.e. make the same unsigned → signed type change from the raw kernel syscall compared to the
+ * userspace wrapper. There's only one caveat for this: unlike for close() there's the special
+ * UINT_MAX fd value for the 'end_fd' argument. Let's safely map that to -1 here. And let's refuse
+ * any other negative values. */
+ if ((first_fd < 0) || (end_fd < 0 && end_fd != -1)) {
+ errno = -EBADF;
+ return -1;
+ }
+
+ return syscall(__NR_close_range,
+ (unsigned) first_fd,
+ end_fd == -1 ? UINT_MAX : (unsigned) end_fd, /* Of course, the compiler should figure out that this is the identity mapping IRL */
+ flags);
+# else
+ errno = ENOSYS;
+ return -1;
+# endif
+}
+
+# define close_range missing_close_range
+#endif