build container namespace require root
This commit is contained in:
parent
ba4e894ff2
commit
58431adc32
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,6 +1,7 @@
|
|||||||
# Ignore everything in this directory
|
# Ignore everything in this directory
|
||||||
bin/*
|
bin/*
|
||||||
doc/*
|
doc/*
|
||||||
|
busybox/*
|
||||||
# Except this file
|
# Except this file
|
||||||
!.gitkeep
|
!.gitkeep
|
||||||
|
|
||||||
|
15
Makefile
15
Makefile
@ -2,9 +2,9 @@
|
|||||||
# https://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html
|
# https://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html
|
||||||
# http://www.partow.net/programming/makefile/index.html
|
# http://www.partow.net/programming/makefile/index.html
|
||||||
|
|
||||||
CXX ?= g++
|
CXX = gcc
|
||||||
GCXX_DEBUG = -ggdb -DDEBUG -g
|
GCXX_DEBUG = -ggdb3 -DDEBUG -g -fstack-protector-all -Wstack-protector -fno-omit-frame-pointer
|
||||||
CFLAGS = -pedantic-errors -Wall -Wextra --std=c++14 $(GCXX_DEBUG) # -Werror
|
CFLAGS = -pedantic-errors -Wall -Wextra --std=gnu18 # -Werror
|
||||||
LDFLAGS = # $(shell pkg-config --libs libcrypto jsoncpp)
|
LDFLAGS = # $(shell pkg-config --libs libcrypto jsoncpp)
|
||||||
INCLUDE = -Iinclude/
|
INCLUDE = -Iinclude/
|
||||||
|
|
||||||
@ -12,7 +12,7 @@ INCLUDE = -Iinclude/
|
|||||||
BIN_DIR = ./bin
|
BIN_DIR = ./bin
|
||||||
OBJ_DIR = ./obj
|
OBJ_DIR = ./obj
|
||||||
SRC_DIR = ./src
|
SRC_DIR = ./src
|
||||||
SRC_EXT = .cpp
|
SRC_EXT = .c
|
||||||
TARGET = out.ex
|
TARGET = out.ex
|
||||||
|
|
||||||
# code lists #
|
# code lists #
|
||||||
@ -33,8 +33,6 @@ $(OBJ_DIR)/%.o: %$(SRC_EXT)
|
|||||||
$(BIN_DIR)/$(TARGET): $(OBJECTS)
|
$(BIN_DIR)/$(TARGET): $(OBJECTS)
|
||||||
$(CXX) $(CFLAGS) -o $(BIN_DIR)/$(TARGET) $^ $(LDFLAGS)
|
$(CXX) $(CFLAGS) -o $(BIN_DIR)/$(TARGET) $^ $(LDFLAGS)
|
||||||
|
|
||||||
all:
|
|
||||||
|
|
||||||
.PHONY: all debug release valgrind clean markdown doxygenconf
|
.PHONY: all debug release valgrind clean markdown doxygenconf
|
||||||
|
|
||||||
debug: CFLAGS += $(GCXX_DEBUG)
|
debug: CFLAGS += $(GCXX_DEBUG)
|
||||||
@ -45,7 +43,10 @@ release: all
|
|||||||
|
|
||||||
# debug target
|
# debug target
|
||||||
valgrind:
|
valgrind:
|
||||||
@valgrind --leak-check=full --track-origins=yes $(BIN_DIR)/$(TARGET) file
|
@valgrind --leak-check=full --show-leak-kinds=all --trace-children=yes --track-origins=yes $(BIN_DIR)/$(TARGET) ls -la
|
||||||
|
|
||||||
|
run:
|
||||||
|
$(BIN_DIR)/$(TARGET) ls -la
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@rm -f $(OBJ_DIR)/*.o
|
@rm -f $(OBJ_DIR)/*.o
|
||||||
|
BIN
alpine-minirootfs-3.12.0-x86.tar.gz
Normal file
BIN
alpine-minirootfs-3.12.0-x86.tar.gz
Normal file
Binary file not shown.
0
busybox/.gitkeep
Normal file
0
busybox/.gitkeep
Normal file
95
src/container.c
Normal file
95
src/container.c
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
#include "prototype.h"
|
||||||
|
|
||||||
|
#define __USE_GNU
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
#include <sched.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/mount.h>
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
#include <sys/stat.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 child_exec(void *stuff)
|
||||||
|
{
|
||||||
|
container_t *c = (container_t *)stuff;
|
||||||
|
struct clone_args *cloneArgs = &c->cloneArgs;
|
||||||
|
|
||||||
|
if (sethostname(cloneArgs->hostname, strlen(cloneArgs->hostname)) != 0)
|
||||||
|
{
|
||||||
|
container_error_handler(c, "fail to set new hostname");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (execvp(cloneArgs->argv[0], cloneArgs->argv) != 0)
|
||||||
|
{
|
||||||
|
container_error_handler(c, "failed to execvp arguments\n");
|
||||||
|
}
|
||||||
|
// we should never reach here!
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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_NEWNET | CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWPID | SIGCHLD;
|
||||||
|
c->cloneArgs = cloneArgs;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* launch command into container
|
||||||
|
*/
|
||||||
|
pid_t run(container_t *c)
|
||||||
|
{
|
||||||
|
// the result of this call is that our child_exec will be run in another
|
||||||
|
// process returning it's pid
|
||||||
|
pid_t pid = clone(child_exec, child_stack + STACKSIZE, c->_cloneFlags, c);
|
||||||
|
if (pid < 0)
|
||||||
|
{
|
||||||
|
container_error_handler(c, "failed to run clone");
|
||||||
|
}
|
||||||
|
// lets wait on our child process here before we, the parent, exits
|
||||||
|
if (waitpid(pid, NULL, 0) == -1)
|
||||||
|
{
|
||||||
|
container_error_handler(c, "failed to wait pid %d", pid);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
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 container_error_handler(container_t *c, const char *error_msg, ...)
|
||||||
|
{
|
||||||
|
va_list arg;
|
||||||
|
va_start(arg, error_msg);
|
||||||
|
|
||||||
|
destroy_container(c);
|
||||||
|
error(error_msg, arg);
|
||||||
|
va_end(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* container destructor
|
||||||
|
*/
|
||||||
|
void destroy_container(container_t *c)
|
||||||
|
{
|
||||||
|
free(c);
|
||||||
|
}
|
42
src/errorUtils.c
Normal file
42
src/errorUtils.c
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#ifndef _ERROR_UTILS
|
||||||
|
#define _ERROR_UTILS
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
// separator between user message and errno message
|
||||||
|
#define SEPARATOR ", "
|
||||||
|
#define BREAKLINE "\n"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* print error message and exit program with error
|
||||||
|
*/
|
||||||
|
void error(const char *sys_msg, va_list arg)
|
||||||
|
{
|
||||||
|
FILE *fd = fopen("/dev/stderr", "w");
|
||||||
|
char *errorTxt = strerror(errno);
|
||||||
|
|
||||||
|
// + 1 is due to strcpy on sys_msg which add \0 at the end of the string
|
||||||
|
char *concatenated_msg = malloc(
|
||||||
|
(sizeof(*(errorTxt)) * strlen(errorTxt)) +
|
||||||
|
(sizeof(*(sys_msg)) * strlen(sys_msg) + 1) +
|
||||||
|
strlen(SEPARATOR) +
|
||||||
|
strlen(BREAKLINE));
|
||||||
|
|
||||||
|
strcpy(concatenated_msg, sys_msg);
|
||||||
|
strcat(concatenated_msg, SEPARATOR);
|
||||||
|
strcat(concatenated_msg, errorTxt);
|
||||||
|
strcat(concatenated_msg, BREAKLINE);
|
||||||
|
|
||||||
|
vfprintf(fd, concatenated_msg, arg);
|
||||||
|
|
||||||
|
fclose(fd);
|
||||||
|
free(concatenated_msg);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
24
src/main.c
Normal file
24
src/main.c
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
|
||||||
|
#include "prototype.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main program, run container
|
||||||
|
*/
|
||||||
|
int main(int argc, char *const argv[])
|
||||||
|
{
|
||||||
|
if (argc <= 1)
|
||||||
|
{
|
||||||
|
error("Too few arguments");
|
||||||
|
}
|
||||||
|
|
||||||
|
struct clone_args cloneArgs;
|
||||||
|
cloneArgs.argv = &argv[1];
|
||||||
|
cloneArgs.hostname = "container-hostname";
|
||||||
|
|
||||||
|
container_t *c = initialize_container(cloneArgs);
|
||||||
|
run(c);
|
||||||
|
|
||||||
|
destroy_container(c);
|
||||||
|
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
@ -1,7 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
int main(int argc, char const *argv[])
|
|
||||||
{
|
|
||||||
printf("c/c++ sample");
|
|
||||||
return 0;
|
|
||||||
}
|
|
19
src/prototype.h
Normal file
19
src/prototype.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#ifndef _PROTOTYPE
|
||||||
|
#define _PROTOTYPE
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include "./type.h"
|
||||||
|
|
||||||
|
// public functions
|
||||||
|
|
||||||
|
void error(const char *sys_msg, ...);
|
||||||
|
|
||||||
|
container_t *initialize_container(struct clone_args);
|
||||||
|
pid_t run(container_t *c);
|
||||||
|
void container_error_handler(container_t *c, const char *error_msg, ...);
|
||||||
|
void destroy_container(container_t *c);
|
||||||
|
|
||||||
|
#endif
|
22
src/type.h
Normal file
22
src/type.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#ifndef _TYPE
|
||||||
|
#define _TYPE
|
||||||
|
|
||||||
|
/**
|
||||||
|
* running argument for clone call
|
||||||
|
*/
|
||||||
|
struct clone_args
|
||||||
|
{
|
||||||
|
char *const *argv;
|
||||||
|
const char *hostname;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* container object
|
||||||
|
*/
|
||||||
|
typedef struct container_t
|
||||||
|
{
|
||||||
|
int _cloneFlags;
|
||||||
|
struct clone_args cloneArgs;
|
||||||
|
} container_t;
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user