Skip to content

Commit

Permalink
always set up memory space for the child stack in clone(2)
Browse files Browse the repository at this point in the history
Signed-off-by: lifubang <[email protected]>
  • Loading branch information
lifubang committed Mar 30, 2024
1 parent 286166c commit 6fb24a2
Showing 1 changed file with 26 additions and 26 deletions.
52 changes: 26 additions & 26 deletions libcontainer/nsenter/nsexec.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,19 +52,15 @@ enum sync_t {
/* Stores the current stage of nsexec. */
int current_stage = STAGE_SETUP;

/* Assume the stack grows down, so arguments should be above it. */
struct clone_t {
/*
* Reserve some space for clone() to locate arguments
* and retcode in this place
*/
char stack[4096] __attribute__((aligned(16)));
char stack_ptr[0];
jmp_buf env;

/* There's two children. This is used to execute the different code. */
jmp_buf *env;
int jmpval;
};
/* stack is used to set up memory space for the child stack in clone(2)*/
char *stack;
#define STACK_SIZE (1024 * 1024)
#define freestack() { \
if (stack != NULL) \
free(stack); \
}

struct nlconfig_t {
char *data;
Expand Down Expand Up @@ -307,19 +303,18 @@ static void update_oom_score_adj(char *data, size_t len)
static int child_func(void *arg) __attribute__((noinline));
static int child_func(void *arg)
{
struct clone_t *ca = (struct clone_t *)arg;
longjmp(*ca->env, ca->jmpval);
int *jmpval = (int *)arg;
longjmp(env, *jmpval);
}

static int clone_parent(jmp_buf *env, int jmpval) __attribute__((noinline));
static int clone_parent(jmp_buf *env, int jmpval)
static int clone_parent(int jmpval) __attribute__((noinline));
static int clone_parent(int jmpval)
{
struct clone_t ca = {
.env = env,
.jmpval = jmpval,
};
stack = (char *)malloc(STACK_SIZE);
if (stack == NULL)
bail("can't allocate stack to clone a new process");

return clone(child_func, ca.stack_ptr, CLONE_PARENT | SIGCHLD, &ca);
return clone(child_func, stack + STACK_SIZE, CLONE_PARENT | SIGCHLD, &jmpval);
}

/* Returns the clone(2) flag for a namespace, given the name of a namespace. */
Expand Down Expand Up @@ -550,7 +545,6 @@ static void update_timens_offsets(pid_t pid, char *map, size_t map_len)
void nsexec(void)
{
int pipenum;
jmp_buf env;
int sync_child_pipe[2], sync_grandchild_pipe[2];
struct nlconfig_t config = { 0 };

Expand Down Expand Up @@ -687,9 +681,11 @@ void nsexec(void)

/* Start the process of getting a container. */
write_log(DEBUG, "spawn stage-1");
stage1_pid = clone_parent(&env, STAGE_CHILD);
if (stage1_pid < 0)
stage1_pid = clone_parent(STAGE_CHILD);
if (stage1_pid < 0) {
freestack();
bail("unable to spawn stage-1");
}

syncfd = sync_child_pipe[1];
if (close(sync_child_pipe[0]) < 0)
Expand Down Expand Up @@ -834,6 +830,7 @@ void nsexec(void)
* (stage 0).
*/
case STAGE_CHILD:{
freestack();
pid_t stage2_pid = -1;
enum sync_t s;

Expand Down Expand Up @@ -955,9 +952,11 @@ void nsexec(void)
* to actually enter the new PID namespace.
*/
write_log(DEBUG, "spawn stage-2");
stage2_pid = clone_parent(&env, STAGE_INIT);
if (stage2_pid < 0)
stage2_pid = clone_parent(STAGE_INIT);
if (stage2_pid < 0) {
freestack();
bail("unable to spawn stage-2");
}

/* Send the child to our parent, which knows what it's doing. */
write_log(DEBUG, "request stage-0 to forward stage-2 pid (%d)", stage2_pid);
Expand Down Expand Up @@ -1001,6 +1000,7 @@ void nsexec(void)
* init_linux.go to run.
*/
case STAGE_INIT:{
freestack();
/*
* We're inside the child now, having jumped from the
* start_child() code after forking in the parent.
Expand Down

0 comments on commit 6fb24a2

Please sign in to comment.