111 lines
2.6 KiB
C
111 lines
2.6 KiB
C
#ifndef _CONTAINER
|
|
#define _CONTAINER
|
|
|
|
#include "prototype.h"
|
|
|
|
#define __USE_GNU
|
|
#define _GNU_SOURCE
|
|
|
|
#include <sched.h>
|
|
#include <stdarg.h>
|
|
#include <sys/wait.h>
|
|
#include <string.h>
|
|
#include <signal.h>
|
|
#include <unistd.h>
|
|
|
|
#define STACKSIZE (1024 * 1024)
|
|
static char child_stack[STACKSIZE];
|
|
|
|
/**
|
|
* Child_exec is the func that will be executed as the result of clone
|
|
*/
|
|
int container_create(void *stuff)
|
|
{
|
|
char rootfs_path[] = "./busybox";
|
|
container_t *c = (container_t *)stuff;
|
|
struct clone_args *cloneArgs = &(c->cloneArgs);
|
|
|
|
if (pivot_root(rootfs_path) != 0)
|
|
{
|
|
error_handler_container(c, "failed to pivot root");
|
|
}
|
|
|
|
// mount dev, sys, proc into pivot root fs
|
|
remount();
|
|
|
|
if (sethostname(cloneArgs->hostname, strlen(cloneArgs->hostname)) != 0)
|
|
{
|
|
error_handler_container(c, "fail to set new hostname");
|
|
}
|
|
|
|
// run container command
|
|
if (run_subprocess_async(cloneArgs->argc, cloneArgs->argv) != 0)
|
|
{
|
|
error_handler_container(c, "failed to execvp arguments");
|
|
}
|
|
|
|
free(c); // free twice don't know why but maybe clone lost c reference
|
|
c = NULL;
|
|
|
|
// we end container
|
|
return EXIT_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* Container constructor initialize container_t object
|
|
*/
|
|
container_t *initialize_container(struct clone_args cloneArgs)
|
|
{
|
|
container_t *c = (container_t *)malloc(sizeof(container_t));
|
|
// in order new net ns, new mount ns, new hostname ns, new pid ns, child ns
|
|
c->_cloneFlags = CLONE_NEWUSER | CLONE_NEWNET | CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWPID | CLONE_NEWCGROUP;
|
|
c->cloneArgs = cloneArgs;
|
|
return c;
|
|
}
|
|
|
|
/**
|
|
* Launch command into container
|
|
*/
|
|
pid_t run_container(container_t *c)
|
|
{
|
|
// the result of this call is that our child_exec will be run_container in another
|
|
// process returning it's pid
|
|
pid_t pid = clone(container_create, child_stack + STACKSIZE, c->_cloneFlags | SIGCHLD, c);
|
|
if (pid < 0)
|
|
{
|
|
error_handler_container(c, "failed to run_container clone");
|
|
}
|
|
// lets wait on our child process here before we, the parent, exit
|
|
if (waitpid(pid, NULL, 0) == -1)
|
|
{
|
|
error_handler_container(c, "failed to wait pid %d", pid);
|
|
}
|
|
|
|
return pid;
|
|
}
|
|
|
|
/**
|
|
* Handle error occured during container creation
|
|
* this methode permit to call container_destroy
|
|
* before printing error
|
|
* take at last parameter variadic argument
|
|
*/
|
|
void error_handler_container(container_t *c, const char *error_msg, ...)
|
|
{
|
|
va_list arg;
|
|
va_start(arg, error_msg);
|
|
|
|
destroy_container(c);
|
|
last_error(error_msg, arg);
|
|
}
|
|
|
|
/**
|
|
* Container destructor
|
|
*/
|
|
void destroy_container(container_t *c)
|
|
{
|
|
free(c);
|
|
}
|
|
|
|
#endif
|