]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/raw_syscalls.c
spelling: hoops
[mirror_lxc.git] / src / lxc / raw_syscalls.c
CommitLineData
13be2733
CB
1#ifndef _GNU_SOURCE
2#define _GNU_SOURCE 1
3#endif
4#include <errno.h>
38e5c2db
CB
5#include <sched.h>
6#include <signal.h>
13be2733
CB
7#include <stdio.h>
8#include <stdlib.h>
9#include <sys/syscall.h>
10#include <unistd.h>
11
12#include "config.h"
38e5c2db
CB
13#include "macro.h"
14#include "raw_syscalls.h"
13be2733
CB
15
16int lxc_raw_execveat(int dirfd, const char *pathname, char *const argv[],
17 char *const envp[], int flags)
18{
19#ifdef __NR_execveat
20 syscall(__NR_execveat, dirfd, pathname, argv, envp, flags);
21#else
22 errno = ENOSYS;
13be2733 23#endif
e4767d47 24 return -1;
13be2733 25}
38e5c2db
CB
26
27/*
28 * This is based on raw_clone in systemd but adapted to our needs. This uses
29 * copy on write semantics and doesn't pass a stack. CLONE_VM is tricky and
30 * doesn't really matter to us so disallow it.
31 *
32 * The nice thing about this is that we get fork() behavior. That is
33 * lxc_raw_clone() returns 0 in the child and the child pid in the parent.
34 */
35pid_t lxc_raw_clone(unsigned long flags)
36{
38e5c2db 37 /*
b6991178 38 * These flags don't interest at all so we don't jump through any hoops
38e5c2db
CB
39 * of retrieving them and passing them to the kernel.
40 */
41 errno = EINVAL;
42 if ((flags & (CLONE_VM | CLONE_PARENT_SETTID | CLONE_CHILD_SETTID |
43 CLONE_CHILD_CLEARTID | CLONE_SETTLS)))
44 return -EINVAL;
45
46#if defined(__s390x__) || defined(__s390__) || defined(__CRIS__)
47 /* On s390/s390x and cris the order of the first and second arguments
48 * of the system call is reversed.
49 */
50 return (int)syscall(__NR_clone, NULL, flags | SIGCHLD);
51#elif defined(__sparc__) && defined(__arch64__)
52 {
53 /*
54 * sparc64 always returns the other process id in %o0, and a
55 * boolean flag whether this is the child or the parent in %o1.
56 * Inline assembly is needed to get the flag returned in %o1.
57 */
58 int in_child;
59 int child_pid;
60 asm volatile("mov %2, %%g1\n\t"
61 "mov %3, %%o0\n\t"
62 "mov 0 , %%o1\n\t"
63 "t 0x6d\n\t"
64 "mov %%o1, %0\n\t"
65 "mov %%o0, %1"
66 : "=r"(in_child), "=r"(child_pid)
67 : "i"(__NR_clone), "r"(flags | SIGCHLD)
68 : "%o1", "%o0", "%g1");
69
70 if (in_child)
71 return 0;
72 else
73 return child_pid;
74 }
75#elif defined(__ia64__)
76 /* On ia64 the stack and stack size are passed as separate arguments. */
77 return (int)syscall(__NR_clone, flags | SIGCHLD, NULL, prctl_arg(0));
78#else
79 return (int)syscall(__NR_clone, flags | SIGCHLD, NULL);
80#endif
81}
82
83pid_t lxc_raw_clone_cb(int (*fn)(void *), void *args, unsigned long flags)
84{
85 pid_t pid;
86
87 pid = lxc_raw_clone(flags);
88 if (pid < 0)
89 return -1;
90
91 /*
92 * exit() is not thread-safe and might mess with the parent's signal
93 * handlers and other stuff when exec() fails.
94 */
95 if (pid == 0)
96 _exit(fn(args));
97
98 return pid;
99}