Skip to content

Instantly share code, notes, and snippets.

@rkubik
Last active October 17, 2018 21:28
Show Gist options
  • Save rkubik/fbea73b060042f17f875697039815bbf to your computer and use it in GitHub Desktop.
Save rkubik/fbea73b060042f17f875697039815bbf to your computer and use it in GitHub Desktop.
Linux namespace utilities
#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);
}
#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