# Check for some syscalls functions
AC_CHECK_FUNCS([setns pivot_root sethostname unshare rand_r confstr faccessat gettid memfd_create move_mount open_tree execveat clone3])
-# HAVE_STRUCT_CLONE_ARGS={0,1}
AC_CHECK_TYPES([struct clone_args], [], [], [[#include <linux/sched.h>]])
AC_CHECK_MEMBERS([struct clone_args.set_tid],[],[],[[#include <linux/sched.h>]])
AC_CHECK_MEMBERS([struct clone_args.cgroup],[],[],[[#include <linux/sched.h>]])
* The nice thing about this is that we get fork() behavior. That is
* lxc_raw_clone() returns 0 in the child and the child pid in the parent.
*/
-__returns_twice pid_t lxc_raw_clone(unsigned long flags, int *pidfd)
+__returns_twice static pid_t __lxc_raw_clone(unsigned long flags, int *pidfd)
{
- /*
- * These flags don't interest at all so we don't jump through any hoops
- * of retrieving them and passing them to the kernel.
- */
- errno = EINVAL;
- if ((flags & (CLONE_VM | CLONE_PARENT_SETTID | CLONE_CHILD_SETTID |
- CLONE_CHILD_CLEARTID | CLONE_SETTLS)))
- return -EINVAL;
#if defined(__s390x__) || defined(__s390__) || defined(__CRIS__)
/* On s390/s390x and cris the order of the first and second arguments
#endif
}
+__returns_twice pid_t lxc_raw_clone(unsigned long flags, int *pidfd)
+{
+ pid_t pid;
+ struct lxc_clone_args args = {
+ .flags = flags,
+ .pidfd = ptr_to_u64(pidfd),
+ };
+
+ if (flags & (CLONE_VM | CLONE_PARENT_SETTID | CLONE_CHILD_SETTID |
+ CLONE_CHILD_CLEARTID | CLONE_SETTLS))
+ return ret_errno(EINVAL);
+
+ /* On CLONE_PARENT we inherit the parent's exit signal. */
+ if (!(flags & CLONE_PARENT))
+ args.exit_signal = SIGCHLD;
+
+ pid = lxc_clone3(&args, CLONE_ARGS_SIZE_VER0);
+ if (pid < 0 && errno == ENOSYS) {
+ SYSTRACE("Falling back to legacy clone");
+ return __lxc_raw_clone(flags, pidfd);
+ }
+
+ return pid;
+}
+
pid_t lxc_raw_clone_cb(int (*fn)(void *), void *args, unsigned long flags,
int *pidfd)
{
#include <sys/syscall.h>
#include <unistd.h>
+#include "compiler.h"
#include "config.h"
#include "syscall_numbers.h"
#define CLONE_ARGS_SIZE_VER2 88 /* sizeof third published struct */
#endif
-#ifndef HAVE_STRUCT_CLONE_ARGS
-struct clone_args {
+#ifndef ptr_to_u64
+#define ptr_to_u64(ptr) ((__u64)((uintptr_t)(ptr)))
+#endif
+#ifndef u64_to_ptr
+#define u64_to_ptr(x) ((void *)(uintptr_t)x)
+#endif
+
+struct lxc_clone_args {
__aligned_u64 flags;
__aligned_u64 pidfd;
__aligned_u64 child_tid;
__aligned_u64 set_tid_size;
__aligned_u64 cgroup;
};
-#endif
-
-struct lxc_clone_args {
- struct clone_args;
-#ifndef HAVE_STRUCT_CLONE_ARGS_SET_TID
- __aligned_u64 set_tid;
- __aligned_u64 set_tid_size;
-#endif
-#ifndef HAVE_STRUCT_CLONE_ARGS_CGROUP
- __aligned_u64 cgroup;
-#endif
-};
-static inline pid_t lxc_clone3(struct lxc_clone_args *args, size_t size)
+__returns_twice static inline pid_t lxc_clone3(struct lxc_clone_args *args, size_t size)
{
- return syscall(__NR_clone3, (struct clone_args *)args, size);
+ return syscall(__NR_clone3, args, size);
}
#if defined(__ia64__)