Browse Source

build container namespace require root

master
Antoine 1 year ago
parent
commit
58431adc32
10 changed files with 211 additions and 14 deletions
  1. +1
    -0
      .gitignore
  2. +8
    -7
      Makefile
  3. BIN
      alpine-minirootfs-3.12.0-x86.tar.gz
  4. +0
    -0
      busybox/.gitkeep
  5. +95
    -0
      src/container.c
  6. +42
    -0
      src/errorUtils.c
  7. +24
    -0
      src/main.c
  8. +0
    -7
      src/main.cpp
  9. +19
    -0
      src/prototype.h
  10. +22
    -0
      src/type.h

+ 1
- 0
.gitignore View File

@@ -1,6 +1,7 @@
# Ignore everything in this directory
bin/*
doc/*
busybox/*
# Except this file
!.gitkeep



+ 8
- 7
Makefile View File

@@ -2,9 +2,9 @@
# https://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html
# http://www.partow.net/programming/makefile/index.html

CXX ?= g++
GCXX_DEBUG = -ggdb -DDEBUG -g
CFLAGS = -pedantic-errors -Wall -Wextra --std=c++14 $(GCXX_DEBUG) # -Werror
CXX = gcc
GCXX_DEBUG = -ggdb3 -DDEBUG -g -fstack-protector-all -Wstack-protector -fno-omit-frame-pointer
CFLAGS = -pedantic-errors -Wall -Wextra --std=gnu18 # -Werror
LDFLAGS = # $(shell pkg-config --libs libcrypto jsoncpp)
INCLUDE = -Iinclude/

@@ -12,7 +12,7 @@ INCLUDE = -Iinclude/
BIN_DIR = ./bin
OBJ_DIR = ./obj
SRC_DIR = ./src
SRC_EXT = .cpp
SRC_EXT = .c
TARGET = out.ex

# code lists #
@@ -33,8 +33,6 @@ $(OBJ_DIR)/%.o: %$(SRC_EXT)
$(BIN_DIR)/$(TARGET): $(OBJECTS)
$(CXX) $(CFLAGS) -o $(BIN_DIR)/$(TARGET) $^ $(LDFLAGS)

all:

.PHONY: all debug release valgrind clean markdown doxygenconf

debug: CFLAGS += $(GCXX_DEBUG)
@@ -45,7 +43,10 @@ release: all

# debug target
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:
@rm -f $(OBJ_DIR)/*.o


BIN
alpine-minirootfs-3.12.0-x86.tar.gz View File


+ 0
- 0
busybox/.gitkeep View File


+ 95
- 0
src/container.c View 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
- 0
src/errorUtils.c View 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
- 0
src/main.c View 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);
}

+ 0
- 7
src/main.cpp View File

@@ -1,7 +0,0 @@
#include <stdio.h>

int main(int argc, char const *argv[])
{
printf("c/c++ sample");
return 0;
}

+ 19
- 0
src/prototype.h View 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
- 0
src/type.h View 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…
Cancel
Save