Last active
October 17, 2018 21:28
-
-
Save rkubik/fbea73b060042f17f875697039815bbf to your computer and use it in GitHub Desktop.
Linux namespace utilities
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define _GNU_SOURCE | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <sched.h> | |
#include <sys/wait.h> | |
#include <errno.h> | |
#include <linux/limits.h> | |
#include <inttypes.h> | |
#include <sys/stat.h> | |
#define STACKSIZE (1024*1024) | |
static char _child_stack[STACKSIZE]; | |
struct clone_args { | |
char **argv; | |
}; | |
#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0) | |
static int _child_exec(void *stuff); | |
static void _print_mnt_namespace_id(void); | |
int main(int argc, char **argv) | |
{ | |
struct clone_args args; | |
int clone_flags = CLONE_NEWNS | SIGCHLD; | |
pid_t pid; | |
if (argc < 2) { | |
fprintf(stderr, "\n"); | |
fprintf(stderr, "%s <cmd>\n", argv[0]); | |
fprintf(stderr, "\n"); | |
fprintf(stderr, "Example: %s /bin/bash\n", argv[0]); | |
fprintf(stderr, "\n"); | |
exit(EXIT_FAILURE); | |
} | |
args.argv = &argv[1]; | |
_print_mnt_namespace_id(); | |
pid = clone(_child_exec, _child_stack + STACKSIZE, clone_flags, &args); | |
if (pid < 0) { | |
errExit("clone"); | |
} | |
if (waitpid(pid, NULL, 0) == -1) { | |
errExit("waitpid"); | |
} | |
return EXIT_SUCCESS; | |
} | |
static int _child_exec(void *stuff) | |
{ | |
struct clone_args *args = (struct clone_args *)stuff; | |
_print_mnt_namespace_id(); | |
if (execvp(args->argv[0], args->argv) != 0) { | |
errExit("execvp"); | |
} | |
abort(); | |
} | |
static void _print_mnt_namespace_id(void) | |
{ | |
char proc_path[PATH_MAX]; | |
int n; | |
struct stat sb; | |
n = snprintf(proc_path, sizeof(proc_path), "/proc/%d/ns/mnt", getpid()); | |
if (n < 0 || (size_t)n >= sizeof(proc_path)) { | |
errExit("snprintf"); | |
} | |
if (stat(proc_path, &sb)) { | |
errExit("stat"); | |
} | |
printf("mnt %" PRIu32 "\n", sb.st_ino); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <inttypes.h> | |
#include <sys/types.h> | |
#include <sys/stat.h> | |
#include <fcntl.h> | |
#include <linux/limits.h> | |
#include <asm-generic/unistd.h> | |
/* CentOS 6 */ | |
// #define setns(fd, nstype) syscall(__NR_setns, fd, nstype); | |
#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0) | |
static void _print_mnt_namespace_id(void); | |
static int _mnt_namespace_fd(pid_t pid); | |
int main(int argc, char *argv[]) | |
{ | |
int fd; | |
if (argc < 3) { | |
fprintf(stderr, "\n"); | |
fprintf(stderr, "%s <pid> <cmd> <args>...\n", argv[0]); | |
fprintf(stderr, "\n"); | |
fprintf(stderr, "pid\tPID of process to join the mnt namespace\n"); | |
fprintf(stderr, "cmd\tCommand to execute after joining namespace\n"); | |
fprintf(stderr, "args\tCommand arguments\n"); | |
fprintf(stderr, "\n"); | |
fprintf(stderr, "Example: %s $(pidof NetworkManager) /bin/bash\n", argv[0]); | |
fprintf(stderr, "\n"); | |
exit(EXIT_FAILURE); | |
} | |
/* Get file descriptor for namespace */ | |
fd = _mnt_namespace_fd(atoi(argv[1])); | |
if (fd == -1) { | |
errExit("open"); | |
} | |
_print_mnt_namespace_id(); | |
/* Join that namespace */ | |
if (setns(fd, 0) == -1) { | |
errExit("setns"); | |
} | |
_print_mnt_namespace_id(); | |
/* Execute a command in namespace */ | |
execvp(argv[2], &argv[2]); | |
errExit("execvp"); | |
} | |
static void _print_mnt_namespace_id(void) | |
{ | |
char proc_path[PATH_MAX]; | |
int n; | |
struct stat sb; | |
n = snprintf(proc_path, sizeof(proc_path), "/proc/%d/ns/mnt", getpid()); | |
if (n < 0 || (size_t)n >= sizeof(proc_path)) { | |
errExit("snprintf"); | |
} | |
if (stat(proc_path, &sb)) { | |
errExit("stat"); | |
} | |
printf("mnt %" PRIu32 "\n", sb.st_ino); | |
} | |
static int _mnt_namespace_fd(pid_t pid) | |
{ | |
char proc_path[PATH_MAX]; | |
int n; | |
n = snprintf(proc_path, sizeof(proc_path), "/proc/%d/ns/mnt", pid); | |
if (n < 0 || (size_t)n >= sizeof(proc_path)) { | |
errExit("snprintf"); | |
} | |
return open(proc_path, O_RDONLY); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment