Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
L
lxc
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Chen Yisong
lxc
Commits
38e5c2db
Unverified
Commit
38e5c2db
authored
Sep 30, 2018
by
Christian Brauner
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
raw_syscalls: add lxc_raw_clone{_cb}()
Signed-off-by:
Christian Brauner
<
christian.brauner@ubuntu.com
>
parent
13be2733
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
128 additions
and
118 deletions
+128
-118
attach.c
src/lxc/attach.c
+1
-0
namespace.c
src/lxc/namespace.c
+0
-74
namespace.h
src/lxc/namespace.h
+1
-43
raw_syscalls.c
src/lxc/raw_syscalls.c
+79
-0
raw_syscalls.h
src/lxc/raw_syscalls.h
+44
-0
start.c
src/lxc/start.c
+1
-0
utils.c
src/lxc/utils.c
+1
-0
lxc_raw_clone.c
src/tests/lxc_raw_clone.c
+1
-1
No files found.
src/lxc/attach.c
View file @
38e5c2db
...
@@ -59,6 +59,7 @@
...
@@ -59,6 +59,7 @@
#include "macro.h"
#include "macro.h"
#include "mainloop.h"
#include "mainloop.h"
#include "namespace.h"
#include "namespace.h"
#include "raw_syscalls.h"
#include "terminal.h"
#include "terminal.h"
#include "utils.h"
#include "utils.h"
...
...
src/lxc/namespace.c
View file @
38e5c2db
...
@@ -75,80 +75,6 @@ pid_t lxc_clone(int (*fn)(void *), void *arg, int flags)
...
@@ -75,80 +75,6 @@ pid_t lxc_clone(int (*fn)(void *), void *arg, int flags)
return
ret
;
return
ret
;
}
}
/**
* This is based on raw_clone in systemd but adapted to our needs. This uses
* copy on write semantics and doesn't pass a stack. CLONE_VM is tricky and
* doesn't really matter to us so disallow it.
*
* 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.
*/
pid_t
lxc_raw_clone
(
unsigned
long
flags
)
{
/* These flags don't interest at all so we don't jump through any hoopes
* 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
* of the system call is reversed.
*/
return
(
int
)
syscall
(
__NR_clone
,
NULL
,
flags
|
SIGCHLD
);
#elif defined(__sparc__) && defined(__arch64__)
{
/**
* sparc64 always returns the other process id in %o0, and
* a boolean flag whether this is the child or the parent in
* %o1. Inline assembly is needed to get the flag returned
* in %o1.
*/
int
in_child
;
int
child_pid
;
asm
volatile
(
"mov %2, %%g1
\n\t
"
"mov %3, %%o0
\n\t
"
"mov 0 , %%o1
\n\t
"
"t 0x6d
\n\t
"
"mov %%o1, %0
\n\t
"
"mov %%o0, %1"
:
"=r"
(
in_child
),
"=r"
(
child_pid
)
:
"i"
(
__NR_clone
),
"r"
(
flags
|
SIGCHLD
)
:
"%o1"
,
"%o0"
,
"%g1"
);
if
(
in_child
)
return
0
;
else
return
child_pid
;
}
#elif defined(__ia64__)
/* On ia64 the stack and stack size are passed as separate arguments. */
return
(
int
)
syscall
(
__NR_clone
,
flags
|
SIGCHLD
,
NULL
,
0
);
#else
return
(
int
)
syscall
(
__NR_clone
,
flags
|
SIGCHLD
,
NULL
);
#endif
}
pid_t
lxc_raw_clone_cb
(
int
(
*
fn
)(
void
*
),
void
*
args
,
unsigned
long
flags
)
{
pid_t
pid
;
pid
=
lxc_raw_clone
(
flags
);
if
(
pid
<
0
)
return
-
1
;
/* exit() is not thread-safe and might mess with the parent's signal
* handlers and other stuff when exec() fails.
*/
if
(
pid
==
0
)
_exit
(
fn
(
args
));
return
pid
;
}
/* Leave the user namespace at the first position in the array of structs so
/* Leave the user namespace at the first position in the array of structs so
* that we always attach to it first when iterating over the struct and using
* that we always attach to it first when iterating over the struct and using
* setns() to switch namespaces. This especially affects lxc_attach(): Suppose
* setns() to switch namespaces. This especially affects lxc_attach(): Suppose
...
...
src/lxc/namespace.h
View file @
38e5c2db
...
@@ -128,55 +128,13 @@ int clone(int (*fn)(void *), void *child_stack,
...
@@ -128,55 +128,13 @@ int clone(int (*fn)(void *), void *child_stack,
* corresponding libc wrapper. glibc currently does not run pthread_atfork()
* corresponding libc wrapper. glibc currently does not run pthread_atfork()
* handlers but does not guarantee that they are not. Other libcs might or
* handlers but does not guarantee that they are not. Other libcs might or
* might not run pthread_atfork() handlers. If you require guarantees please
* might not run pthread_atfork() handlers. If you require guarantees please
* refer to the lxc_raw_clone*() functions
below
.
* refer to the lxc_raw_clone*() functions
in raw_syscalls.{c,h}
.
*
*
* - should call lxc_raw_getpid():
* - should call lxc_raw_getpid():
* The child should use lxc_raw_getpid() to retrieve its pid.
* The child should use lxc_raw_getpid() to retrieve its pid.
*/
*/
extern
pid_t
lxc_clone
(
int
(
*
fn
)(
void
*
),
void
*
arg
,
int
flags
);
extern
pid_t
lxc_clone
(
int
(
*
fn
)(
void
*
),
void
*
arg
,
int
flags
);
/**
* lxc_raw_clone() - create a new process
*
* - fork() behavior:
* This function returns 0 in the child and > 0 in the parent.
*
* - copy-on-write:
* This function does not allocate a new stack and relies on copy-on-write
* semantics.
*
* - supports subset of ClONE_* flags:
* lxc_raw_clone() intentionally only supports a subset of the flags available
* to the actual system call. Please refer to the implementation what flags
* cannot be used. Also, please don't assume that just because a flag isn't
* explicitly checked for as being unsupported that it is supported. If in
* doubt or not sufficiently familiar with process creation in the kernel and
* interactions with libcs this function should be used.
*
* - no pthread_atfork() handlers:
* This function circumvents - as much as this this is possible - any libc
* wrappers and thus does not run any pthread_atfork() handlers. Make sure
* that this is safe to do in the context you are trying to call this
* function.
*
* - must call lxc_raw_getpid():
* The child must use lxc_raw_getpid() to retrieve its pid.
*/
extern
pid_t
lxc_raw_clone
(
unsigned
long
flags
);
/**
* lxc_raw_clone_cb() - create a new process
*
* - non-fork() behavior:
* Function does return pid of the child or -1 on error. Pass in a callback
* function via the "fn" argument that gets executed in the child process. The
* "args" argument is passed to "fn".
*
* All other comments that apply to lxc_raw_clone() apply to lxc_raw_clone_cb()
* as well.
*/
extern
pid_t
lxc_raw_clone_cb
(
int
(
*
fn
)(
void
*
),
void
*
args
,
unsigned
long
flags
);
extern
int
lxc_namespace_2_cloneflag
(
const
char
*
namespace
);
extern
int
lxc_namespace_2_cloneflag
(
const
char
*
namespace
);
extern
int
lxc_namespace_2_ns_idx
(
const
char
*
namespace
);
extern
int
lxc_namespace_2_ns_idx
(
const
char
*
namespace
);
extern
int
lxc_namespace_2_std_identifiers
(
char
*
namespaces
);
extern
int
lxc_namespace_2_std_identifiers
(
char
*
namespaces
);
...
...
src/lxc/raw_syscalls.c
View file @
38e5c2db
...
@@ -2,12 +2,16 @@
...
@@ -2,12 +2,16 @@
#define _GNU_SOURCE 1
#define _GNU_SOURCE 1
#endif
#endif
#include <errno.h>
#include <errno.h>
#include <sched.h>
#include <signal.h>
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
#include <sys/syscall.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <unistd.h>
#include "config.h"
#include "config.h"
#include "macro.h"
#include "raw_syscalls.h"
int
lxc_raw_execveat
(
int
dirfd
,
const
char
*
pathname
,
char
*
const
argv
[],
int
lxc_raw_execveat
(
int
dirfd
,
const
char
*
pathname
,
char
*
const
argv
[],
char
*
const
envp
[],
int
flags
)
char
*
const
envp
[],
int
flags
)
...
@@ -19,3 +23,78 @@ int lxc_raw_execveat(int dirfd, const char *pathname, char *const argv[],
...
@@ -19,3 +23,78 @@ int lxc_raw_execveat(int dirfd, const char *pathname, char *const argv[],
return
-
1
;
return
-
1
;
#endif
#endif
}
}
/*
* This is based on raw_clone in systemd but adapted to our needs. This uses
* copy on write semantics and doesn't pass a stack. CLONE_VM is tricky and
* doesn't really matter to us so disallow it.
*
* 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.
*/
pid_t
lxc_raw_clone
(
unsigned
long
flags
)
{
/*
* These flags don't interest at all so we don't jump through any hoopes
* 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
* of the system call is reversed.
*/
return
(
int
)
syscall
(
__NR_clone
,
NULL
,
flags
|
SIGCHLD
);
#elif defined(__sparc__) && defined(__arch64__)
{
/*
* sparc64 always returns the other process id in %o0, and a
* boolean flag whether this is the child or the parent in %o1.
* Inline assembly is needed to get the flag returned in %o1.
*/
int
in_child
;
int
child_pid
;
asm
volatile
(
"mov %2, %%g1
\n\t
"
"mov %3, %%o0
\n\t
"
"mov 0 , %%o1
\n\t
"
"t 0x6d
\n\t
"
"mov %%o1, %0
\n\t
"
"mov %%o0, %1"
:
"=r"
(
in_child
),
"=r"
(
child_pid
)
:
"i"
(
__NR_clone
),
"r"
(
flags
|
SIGCHLD
)
:
"%o1"
,
"%o0"
,
"%g1"
);
if
(
in_child
)
return
0
;
else
return
child_pid
;
}
#elif defined(__ia64__)
/* On ia64 the stack and stack size are passed as separate arguments. */
return
(
int
)
syscall
(
__NR_clone
,
flags
|
SIGCHLD
,
NULL
,
prctl_arg
(
0
));
#else
return
(
int
)
syscall
(
__NR_clone
,
flags
|
SIGCHLD
,
NULL
);
#endif
}
pid_t
lxc_raw_clone_cb
(
int
(
*
fn
)(
void
*
),
void
*
args
,
unsigned
long
flags
)
{
pid_t
pid
;
pid
=
lxc_raw_clone
(
flags
);
if
(
pid
<
0
)
return
-
1
;
/*
* exit() is not thread-safe and might mess with the parent's signal
* handlers and other stuff when exec() fails.
*/
if
(
pid
==
0
)
_exit
(
fn
(
args
));
return
pid
;
}
src/lxc/raw_syscalls.h
View file @
38e5c2db
...
@@ -23,8 +23,52 @@
...
@@ -23,8 +23,52 @@
#ifndef _GNU_SOURCE
#ifndef _GNU_SOURCE
#define _GNU_SOURCE 1
#define _GNU_SOURCE 1
#endif
#endif
#include <sched.h>
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
#include <sys/syscall.h>
/*
* lxc_raw_clone() - create a new process
*
* - fork() behavior:
* This function returns 0 in the child and > 0 in the parent.
*
* - copy-on-write:
* This function does not allocate a new stack and relies on copy-on-write
* semantics.
*
* - supports subset of ClONE_* flags:
* lxc_raw_clone() intentionally only supports a subset of the flags available
* to the actual system call. Please refer to the implementation what flags
* cannot be used. Also, please don't assume that just because a flag isn't
* explicitly checked for as being unsupported that it is supported. If in
* doubt or not sufficiently familiar with process creation in the kernel and
* interactions with libcs this function should be used.
*
* - no pthread_atfork() handlers:
* This function circumvents - as much as this this is possible - any libc
* wrappers and thus does not run any pthread_atfork() handlers. Make sure
* that this is safe to do in the context you are trying to call this
* function.
*
* - must call lxc_raw_getpid():
* The child must use lxc_raw_getpid() to retrieve its pid.
*/
extern
pid_t
lxc_raw_clone
(
unsigned
long
flags
);
/*
* lxc_raw_clone_cb() - create a new process
*
* - non-fork() behavior:
* Function does return pid of the child or -1 on error. Pass in a callback
* function via the "fn" argument that gets executed in the child process.
* The "args" argument is passed to "fn".
*
* All other comments that apply to lxc_raw_clone() apply to lxc_raw_clone_cb()
* as well.
*/
extern
pid_t
lxc_raw_clone_cb
(
int
(
*
fn
)(
void
*
),
void
*
args
,
unsigned
long
flags
);
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
);
...
...
src/lxc/start.c
View file @
38e5c2db
...
@@ -70,6 +70,7 @@
...
@@ -70,6 +70,7 @@
#include "monitor.h"
#include "monitor.h"
#include "namespace.h"
#include "namespace.h"
#include "network.h"
#include "network.h"
#include "raw_syscalls.h"
#include "start.h"
#include "start.h"
#include "storage/storage.h"
#include "storage/storage.h"
#include "storage/storage_utils.h"
#include "storage/storage_utils.h"
...
...
src/lxc/utils.c
View file @
38e5c2db
...
@@ -51,6 +51,7 @@
...
@@ -51,6 +51,7 @@
#include "lxclock.h"
#include "lxclock.h"
#include "namespace.h"
#include "namespace.h"
#include "parse.h"
#include "parse.h"
#include "raw_syscalls.h"
#include "syscall_wrappers.h"
#include "syscall_wrappers.h"
#include "utils.h"
#include "utils.h"
...
...
src/tests/lxc_raw_clone.c
View file @
38e5c2db
...
@@ -38,7 +38,7 @@
...
@@ -38,7 +38,7 @@
#include <sys/types.h>
#include <sys/types.h>
#include "lxctest.h"
#include "lxctest.h"
#include "
namespace
.h"
#include "
raw_syscalls
.h"
#include "utils.h"
#include "utils.h"
int
main
(
int
argc
,
char
*
argv
[])
int
main
(
int
argc
,
char
*
argv
[])
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment