mirror of
https://git.proxmox.com/git/mirror_lxc
synced 2025-08-15 06:06:57 +00:00
Merge pull request #2984 from brauner/2019-05-09/clone_pidfd
clone: add infrastructure for CLONE_PIDFD
This commit is contained in:
commit
1ab73d3800
@ -1426,7 +1426,7 @@ int lxc_attach(const char *name, const char *lxcpath,
|
|||||||
payload.exec_function = exec_function;
|
payload.exec_function = exec_function;
|
||||||
payload.exec_payload = exec_payload;
|
payload.exec_payload = exec_payload;
|
||||||
|
|
||||||
pid = lxc_raw_clone(CLONE_PARENT);
|
pid = lxc_raw_clone(CLONE_PARENT, NULL);
|
||||||
if (pid < 0) {
|
if (pid < 0) {
|
||||||
SYSERROR("Failed to clone attached process");
|
SYSERROR("Failed to clone attached process");
|
||||||
shutdown(ipc_sockets[1], SHUT_RDWR);
|
shutdown(ipc_sockets[1], SHUT_RDWR);
|
||||||
|
@ -4337,7 +4337,7 @@ int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data,
|
|||||||
d.p[1] = p[1];
|
d.p[1] = p[1];
|
||||||
|
|
||||||
/* Clone child in new user namespace. */
|
/* Clone child in new user namespace. */
|
||||||
pid = lxc_raw_clone_cb(run_userns_fn, &d, CLONE_NEWUSER);
|
pid = lxc_raw_clone_cb(run_userns_fn, &d, CLONE_NEWUSER, NULL);
|
||||||
if (pid < 0) {
|
if (pid < 0) {
|
||||||
ERROR("Failed to clone process in new user namespace");
|
ERROR("Failed to clone process in new user namespace");
|
||||||
goto on_error;
|
goto on_error;
|
||||||
|
@ -33,7 +33,7 @@ int lxc_raw_execveat(int dirfd, const char *pathname, char *const argv[],
|
|||||||
* The nice thing about this is that we get fork() behavior. That is
|
* 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.
|
* 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)
|
__returns_twice 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
|
* These flags don't interest at all so we don't jump through any hoops
|
||||||
@ -48,7 +48,7 @@ __returns_twice pid_t lxc_raw_clone(unsigned long flags)
|
|||||||
/* On s390/s390x and cris the order of the first and second arguments
|
/* On s390/s390x and cris the order of the first and second arguments
|
||||||
* of the system call is reversed.
|
* of the system call is reversed.
|
||||||
*/
|
*/
|
||||||
return syscall(__NR_clone, NULL, flags | SIGCHLD);
|
return syscall(__NR_clone, NULL, flags | SIGCHLD, pidfd);
|
||||||
#elif defined(__sparc__) && defined(__arch64__)
|
#elif defined(__sparc__) && defined(__arch64__)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -56,46 +56,58 @@ __returns_twice pid_t lxc_raw_clone(unsigned long flags)
|
|||||||
* boolean flag whether this is the child or the parent in %o1.
|
* boolean flag whether this is the child or the parent in %o1.
|
||||||
* Inline assembly is needed to get the flag returned in %o1.
|
* Inline assembly is needed to get the flag returned in %o1.
|
||||||
*/
|
*/
|
||||||
int child_pid, in_child, ret;
|
register long g1 asm("g1") = __NR_clone;
|
||||||
|
register long o0 asm("o0") = flags | SIGCHLD;
|
||||||
|
register long o1 asm("o1") = 0; /* is parent/child indicator */
|
||||||
|
register long o2 asm("o2") = (unsigned long)pidfd;
|
||||||
|
long is_error, retval, in_child;
|
||||||
|
pid_t child_pid;
|
||||||
|
|
||||||
asm volatile("mov %3, %%g1\n\t"
|
asm volatile(
|
||||||
"mov %4, %%o0\n\t"
|
|
||||||
"mov 0 , %%o1\n\t"
|
|
||||||
#if defined(__arch64__)
|
#if defined(__arch64__)
|
||||||
"t 0x6d\n\t"
|
"t 0x6d\n\t" /* 64-bit trap */
|
||||||
#else
|
#else
|
||||||
"t 0x10\n\t"
|
"t 0x10\n\t" /* 32-bit trap */
|
||||||
#endif
|
#endif
|
||||||
"addx %%g0, 0, %2\n\t"
|
/*
|
||||||
"mov %%o1, %0\n\t"
|
* catch errors: On sparc, the carry bit (csr) in the
|
||||||
"mov %%o0, %1" :
|
* processor status register (psr) is used instead of a
|
||||||
"=r"(in_child), "=r"(child_pid), "=r"(ret) :
|
* full register.
|
||||||
"i"(__NR_clone), "r"(flags | SIGCHLD) :
|
*/
|
||||||
"%o1", "%o0", "%g1", "cc" );
|
"addx %%g0, 0, %g1"
|
||||||
|
: "=r"(g1), "=r"(o0), "=r"(o1), "=r"(o2) /* outputs */
|
||||||
|
: "r"(g1), "r"(o0), "r"(o1), "r"(o2) /* inputs */
|
||||||
|
: "%cc"); /* clobbers */
|
||||||
|
|
||||||
if (ret) {
|
is_error = g1;
|
||||||
errno = child_pid;
|
retval = o0;
|
||||||
|
in_child = o1;
|
||||||
|
|
||||||
|
if (is_error) {
|
||||||
|
errno = retval;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (in_child)
|
if (in_child)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
child_pid = retval;
|
||||||
return child_pid;
|
return child_pid;
|
||||||
}
|
}
|
||||||
#elif defined(__ia64__)
|
#elif defined(__ia64__)
|
||||||
/* On ia64 the stack and stack size are passed as separate arguments. */
|
/* On ia64 the stack and stack size are passed as separate arguments. */
|
||||||
return syscall(__NR_clone, flags | SIGCHLD, NULL, prctl_arg(0));
|
return syscall(__NR_clone, flags | SIGCHLD, NULL, prctl_arg(0), pidfd);
|
||||||
#else
|
#else
|
||||||
return syscall(__NR_clone, flags | SIGCHLD, NULL);
|
return syscall(__NR_clone, flags | SIGCHLD, NULL, pidfd);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
pid_t lxc_raw_clone_cb(int (*fn)(void *), void *args, unsigned long flags)
|
pid_t lxc_raw_clone_cb(int (*fn)(void *), void *args, unsigned long flags,
|
||||||
|
int *pidfd)
|
||||||
{
|
{
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
|
||||||
pid = lxc_raw_clone(flags);
|
pid = lxc_raw_clone(flags, pidfd);
|
||||||
if (pid < 0)
|
if (pid < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -30,6 +30,11 @@
|
|||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
/* clone */
|
||||||
|
#ifndef CLONE_PIDFD
|
||||||
|
#define CLONE_PIDFD 0x00001000
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* lxc_raw_clone() - create a new process
|
* lxc_raw_clone() - create a new process
|
||||||
*
|
*
|
||||||
@ -57,7 +62,7 @@
|
|||||||
* - must call lxc_raw_getpid():
|
* - must call lxc_raw_getpid():
|
||||||
* The child must use lxc_raw_getpid() to retrieve its pid.
|
* The child must use lxc_raw_getpid() to retrieve its pid.
|
||||||
*/
|
*/
|
||||||
extern pid_t lxc_raw_clone(unsigned long flags);
|
extern pid_t lxc_raw_clone(unsigned long flags, int *pidfd);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* lxc_raw_clone_cb() - create a new process
|
* lxc_raw_clone_cb() - create a new process
|
||||||
@ -70,7 +75,8 @@ extern pid_t lxc_raw_clone(unsigned long flags);
|
|||||||
* All other comments that apply to lxc_raw_clone() apply to lxc_raw_clone_cb()
|
* All other comments that apply to lxc_raw_clone() apply to lxc_raw_clone_cb()
|
||||||
* as well.
|
* as well.
|
||||||
*/
|
*/
|
||||||
extern pid_t lxc_raw_clone_cb(int (*fn)(void *), void *args, unsigned long flags);
|
extern pid_t lxc_raw_clone_cb(int (*fn)(void *), void *args,
|
||||||
|
unsigned long flags, int *pidfd);
|
||||||
|
|
||||||
extern int lxc_raw_execveat(int dirfd, const char *pathname, char *const argv[],
|
extern int lxc_raw_execveat(int dirfd, const char *pathname, char *const argv[],
|
||||||
char *const envp[], int flags);
|
char *const envp[], int flags);
|
||||||
|
@ -1601,7 +1601,7 @@ static inline int do_share_ns(void *arg)
|
|||||||
|
|
||||||
flags = handler->ns_on_clone_flags;
|
flags = handler->ns_on_clone_flags;
|
||||||
flags |= CLONE_PARENT;
|
flags |= CLONE_PARENT;
|
||||||
handler->pid = lxc_raw_clone_cb(do_start, handler, flags);
|
handler->pid = lxc_raw_clone_cb(do_start, handler, flags, NULL);
|
||||||
if (handler->pid < 0)
|
if (handler->pid < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -1748,7 +1748,7 @@ static int lxc_spawn(struct lxc_handler *handler)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
handler->pid = lxc_raw_clone_cb(do_start, handler,
|
handler->pid = lxc_raw_clone_cb(do_start, handler,
|
||||||
handler->ns_on_clone_flags);
|
handler->ns_on_clone_flags, NULL);
|
||||||
}
|
}
|
||||||
if (handler->pid < 0) {
|
if (handler->pid < 0) {
|
||||||
SYSERROR(LXC_CLONE_ERROR);
|
SYSERROR(LXC_CLONE_ERROR);
|
||||||
|
@ -1611,7 +1611,7 @@ int run_command_internal(char *buf, size_t buf_size, int (*child_fn)(void *), vo
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
child = lxc_raw_clone(0);
|
child = lxc_raw_clone(0, NULL);
|
||||||
if (child < 0) {
|
if (child < 0) {
|
||||||
close(pipefd[0]);
|
close(pipefd[0]);
|
||||||
close(pipefd[1]);
|
close(pipefd[1]);
|
||||||
|
@ -48,42 +48,42 @@ int main(int argc, char *argv[])
|
|||||||
pid_t pid;
|
pid_t pid;
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
|
|
||||||
pid = lxc_raw_clone(CLONE_PARENT_SETTID);
|
pid = lxc_raw_clone(CLONE_PARENT_SETTID, NULL);
|
||||||
if (pid >= 0 || pid != -EINVAL) {
|
if (pid >= 0 || pid != -EINVAL) {
|
||||||
lxc_error("%s\n", "Calling lxc_raw_clone(CLONE_PARENT_SETTID) "
|
lxc_error("%s\n", "Calling lxc_raw_clone(CLONE_PARENT_SETTID) "
|
||||||
"should not be possible");
|
"should not be possible");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
pid = lxc_raw_clone(CLONE_CHILD_SETTID);
|
pid = lxc_raw_clone(CLONE_CHILD_SETTID, NULL);
|
||||||
if (pid >= 0 || pid != -EINVAL) {
|
if (pid >= 0 || pid != -EINVAL) {
|
||||||
lxc_error("%s\n", "Calling lxc_raw_clone(CLONE_CHILD_SETTID) "
|
lxc_error("%s\n", "Calling lxc_raw_clone(CLONE_CHILD_SETTID) "
|
||||||
"should not be possible");
|
"should not be possible");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
pid = lxc_raw_clone(CLONE_CHILD_CLEARTID);
|
pid = lxc_raw_clone(CLONE_CHILD_CLEARTID, NULL);
|
||||||
if (pid >= 0 || pid != -EINVAL) {
|
if (pid >= 0 || pid != -EINVAL) {
|
||||||
lxc_error("%s\n", "Calling lxc_raw_clone(CLONE_CHILD_CLEARTID) "
|
lxc_error("%s\n", "Calling lxc_raw_clone(CLONE_CHILD_CLEARTID) "
|
||||||
"should not be possible");
|
"should not be possible");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
pid = lxc_raw_clone(CLONE_SETTLS);
|
pid = lxc_raw_clone(CLONE_SETTLS, NULL);
|
||||||
if (pid >= 0 || pid != -EINVAL) {
|
if (pid >= 0 || pid != -EINVAL) {
|
||||||
lxc_error("%s\n", "Calling lxc_raw_clone(CLONE_SETTLS) should "
|
lxc_error("%s\n", "Calling lxc_raw_clone(CLONE_SETTLS) should "
|
||||||
"not be possible");
|
"not be possible");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
pid = lxc_raw_clone(CLONE_VM);
|
pid = lxc_raw_clone(CLONE_VM, NULL);
|
||||||
if (pid >= 0 || pid != -EINVAL) {
|
if (pid >= 0 || pid != -EINVAL) {
|
||||||
lxc_error("%s\n", "Calling lxc_raw_clone(CLONE_VM) should "
|
lxc_error("%s\n", "Calling lxc_raw_clone(CLONE_VM) should "
|
||||||
"not be possible");
|
"not be possible");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
pid = lxc_raw_clone(0);
|
pid = lxc_raw_clone(0, NULL);
|
||||||
if (pid < 0) {
|
if (pid < 0) {
|
||||||
lxc_error("%s\n", "Failed to call lxc_raw_clone(0)");
|
lxc_error("%s\n", "Failed to call lxc_raw_clone(0)");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
@ -100,7 +100,7 @@ int main(int argc, char *argv[])
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
pid = lxc_raw_clone(0);
|
pid = lxc_raw_clone(0, NULL);
|
||||||
if (pid < 0) {
|
if (pid < 0) {
|
||||||
lxc_error("%s\n", "Failed to call lxc_raw_clone(0)");
|
lxc_error("%s\n", "Failed to call lxc_raw_clone(0)");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
@ -127,7 +127,7 @@ int main(int argc, char *argv[])
|
|||||||
flags |= CLONE_NEWPID;
|
flags |= CLONE_NEWPID;
|
||||||
flags |= CLONE_NEWUTS;
|
flags |= CLONE_NEWUTS;
|
||||||
|
|
||||||
pid = lxc_raw_clone(flags);
|
pid = lxc_raw_clone(flags, NULL);
|
||||||
if (pid < 0) {
|
if (pid < 0) {
|
||||||
lxc_error("%s\n", "Failed to call lxc_raw_clone(CLONE_NEWUSER "
|
lxc_error("%s\n", "Failed to call lxc_raw_clone(CLONE_NEWUSER "
|
||||||
"| CLONE_NEWCGROUP | CLONE_NEWNS | "
|
"| CLONE_NEWCGROUP | CLONE_NEWNS | "
|
||||||
@ -147,7 +147,7 @@ int main(int argc, char *argv[])
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
pid = lxc_raw_clone(flags);
|
pid = lxc_raw_clone(flags, NULL);
|
||||||
if (pid < 0) {
|
if (pid < 0) {
|
||||||
lxc_error("%s\n", "Failed to call lxc_raw_clone(CLONE_NEWUSER "
|
lxc_error("%s\n", "Failed to call lxc_raw_clone(CLONE_NEWUSER "
|
||||||
"| CLONE_NEWCGROUP | CLONE_NEWNS | "
|
"| CLONE_NEWCGROUP | CLONE_NEWNS | "
|
||||||
@ -168,7 +168,7 @@ int main(int argc, char *argv[])
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
pid = lxc_raw_clone(CLONE_VFORK);
|
pid = lxc_raw_clone(CLONE_VFORK, NULL);
|
||||||
if (pid < 0) {
|
if (pid < 0) {
|
||||||
lxc_error("%s\n", "Failed to call lxc_raw_clone(CLONE_VFORK);");
|
lxc_error("%s\n", "Failed to call lxc_raw_clone(CLONE_VFORK);");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
@ -185,7 +185,7 @@ int main(int argc, char *argv[])
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
pid = lxc_raw_clone(CLONE_VFORK);
|
pid = lxc_raw_clone(CLONE_VFORK, NULL);
|
||||||
if (pid < 0) {
|
if (pid < 0) {
|
||||||
lxc_error("%s\n", "Failed to call lxc_raw_clone(CLONE_VFORK);");
|
lxc_error("%s\n", "Failed to call lxc_raw_clone(CLONE_VFORK);");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
@ -202,7 +202,7 @@ int main(int argc, char *argv[])
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
pid = lxc_raw_clone(CLONE_FILES);
|
pid = lxc_raw_clone(CLONE_FILES, NULL);
|
||||||
if (pid < 0) {
|
if (pid < 0) {
|
||||||
lxc_error("%s\n", "Failed to call lxc_raw_clone(CLONE_FILES);");
|
lxc_error("%s\n", "Failed to call lxc_raw_clone(CLONE_FILES);");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
@ -219,7 +219,7 @@ int main(int argc, char *argv[])
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
pid = lxc_raw_clone(CLONE_FILES);
|
pid = lxc_raw_clone(CLONE_FILES, NULL);
|
||||||
if (pid < 0) {
|
if (pid < 0) {
|
||||||
lxc_error("%s\n", "Failed to call lxc_raw_clone(CLONE_FILES);");
|
lxc_error("%s\n", "Failed to call lxc_raw_clone(CLONE_FILES);");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
Loading…
Reference in New Issue
Block a user