diff options
author | Toni Uhlig <matzeton@googlemail.com> | 2018-06-09 14:50:17 +0200 |
---|---|---|
committer | Toni Uhlig <matzeton@googlemail.com> | 2018-06-09 14:50:17 +0200 |
commit | ef10351f70c3d41e536c024b71d811bad6e98884 (patch) | |
tree | 81d38abf1e91f9ed9bde28453621f3a16467abba | |
parent | 0e1a9f70b3e720b506d69db6c920ce017834ae94 (diff) |
POTD skeleton #99.
Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
-rw-r--r-- | configure.ac | 3 | ||||
-rw-r--r-- | src/jail.c | 7 | ||||
-rw-r--r-- | src/options.c | 22 | ||||
-rw-r--r-- | src/options.h | 1 | ||||
-rw-r--r-- | src/pseccomp.c | 4 | ||||
-rw-r--r-- | src/utils.c | 95 | ||||
-rw-r--r-- | src/utils.h | 4 |
7 files changed, 126 insertions, 10 deletions
diff --git a/configure.ac b/configure.ac index 46e219e..26f491d 100644 --- a/configure.ac +++ b/configure.ac @@ -232,5 +232,8 @@ AC_DEFINE_UNQUOTED([POTD_LOGFILE], ["$potd_logfile"], potd_defroot="/var/run/potd-root" AC_DEFINE_UNQUOTED([POTD_DEFROOT], ["$potd_defroot"], [default path to potd rootfs image/directory]) +potd_netns_run_dir="/var/run/potd-netns" +AC_DEFINE_UNQUOTED([POTD_NETNS_RUN_DIR], ["$potd_netns_run_dir"], + [default path to network namespace run directory]) AC_OUTPUT(Makefile src/Makefile) @@ -253,7 +253,7 @@ static int jail_childfn(prisoner_process *ctx) const char *path_shell = "/bin/sh"; int i, s, master_fd; int unshare_flags = CLONE_NEWUTS|CLONE_NEWPID|CLONE_NEWIPC| - CLONE_NEWNS|CLONE_NEWNET/*|CLONE_NEWUSER*/; + CLONE_NEWNS/*|CLONE_NEWUSER*/; //unsigned int ug_map[3] = { 0, 10000, 65535 }; pid_t self_pid, child_pid; pseccomp_ctx *psc = NULL; @@ -274,6 +274,11 @@ static int jail_childfn(prisoner_process *ctx) if (cgroups_activate()) FATAL("Activating cgroups for pid %d", self_pid); + D2("Setup network namespace for pid %d", self_pid); + if (setup_network_namespace("default")) + if (switch_network_namespace("default")) + FATAL("Setup network namespace for pid %d", self_pid); + caps_drop_dac_override(0); //caps_drop_all(); diff --git a/src/options.c b/src/options.c index 343bfc5..f06cbb1 100644 --- a/src/options.c +++ b/src/options.c @@ -70,13 +70,15 @@ static struct opt options[OPT_MAX+1] = { "format [listen]:[forward-to-jail]\n" "where [listen] contains [listen-addr]:[listen-port]\n" "and [forward-to-jail] contains [forward-addr]:[forward-port]\n" - "Example: 0.0.0.0:2222:127.0.0.1:22222\n"), + "Example: 127.0.0.1:22222:127.0.0.1:33333\n"), OPT_LIST(OT_STR, .str = NULL, "jail", "setup jail service\n", "format [listen]\n" "where [listen] contains [listen-addr]:[listen-port]\n" "Example: 127.0.0.1:33333\n"), OPT(OT_PATH, .str = POTD_DEFROOT, "rootfs", "path to root directory/image\n", NULL), + OPT(OT_PATH, .str = POTD_NETNS_RUN_DIR, "netns-rundir", + "set the network namespace run directory\n", NULL), OPT_NOARG("help", "this\n", NULL), OPT(OT_INVALID, .ll = 0, NULL, NULL, NULL) @@ -88,7 +90,7 @@ static int setopt(struct opt *o, const char *optarg); static size_t snprint_multilined_ljust(const char *prefix, const char *multiline, char *buf, size_t siz); -static void usage(int print_copyright); +static void usage(const char *arg0, int print_copyright); static int opt_convert(opt_type t, opt_ptr *d) @@ -182,7 +184,7 @@ static size_t snprint_multilined_ljust(const char *prefix, return off; } -static void usage(int print_copyright) +static void usage(const char *arg0, int print_copyright) { int i, has_default; size_t off; @@ -253,6 +255,16 @@ static void usage(int print_copyright) "%s\n", buf_arg, buf_shorthelp, buf_help); } + fprintf(stderr, + "For example: %s \\\n" + " --redirect 0.0.0.0:2222:127.0.0.1:22222\n" + " --protocol 127.0.0.1:22222:127.0.0.1:33333\n" + " --jail 127.0.0.1:33333\n" + " will process/filter all incoming traffic\n" + " at 0.0.0.0:2222 and redirect it\n" + " to 127.0.0.1:22222 (libssh) which will redirect it finally\n" + " to 127.0.0.1:33333 (jail service).\n\n", + arg0); } int parse_cmdline(int argc, char **argv) @@ -298,9 +310,9 @@ error: free(o); if (rc) - usage(0); + usage(argv[0], 0); else if (getopt_used(OPT_HELP)) { - usage(1); + usage(argv[0], 1); exit(EXIT_SUCCESS); } diff --git a/src/options.h b/src/options.h index 5cd7c0d..1e4832a 100644 --- a/src/options.h +++ b/src/options.h @@ -10,6 +10,7 @@ typedef enum opt_name { OPT_PROTOCOL, OPT_JAIL, OPT_ROOT, + OPT_NETNS_RUN_DIR, OPT_HELP, OPT_MAX diff --git a/src/pseccomp.c b/src/pseccomp.c index 0e77494..a7a2f6f 100644 --- a/src/pseccomp.c +++ b/src/pseccomp.c @@ -51,8 +51,8 @@ static const int default_allowed_syscalls[] = { /* operations on processes */ SCMP_SYS(getpgrp), SCMP_SYS(setpgid), SCMP_SYS(getpid), SCMP_SYS(kill), /* other */ - SCMP_SYS(unshare), SCMP_SYS(chroot), SCMP_SYS(chdir), SCMP_SYS(mount), - SCMP_SYS(umount2), + SCMP_SYS(unshare), SCMP_SYS(setns), + SCMP_SYS(chroot), SCMP_SYS(chdir), SCMP_SYS(mount), SCMP_SYS(umount2), SCMP_SYS(mknod), SCMP_SYS(mkdir), SCMP_SYS(rmdir), SCMP_SYS(statfs), SCMP_SYS(ioctl), SCMP_SYS(umask), SCMP_SYS(chown), SCMP_SYS(chmod), SCMP_SYS(setsid), diff --git a/src/utils.c b/src/utils.c index 7bbdc1e..049e3d5 100644 --- a/src/utils.c +++ b/src/utils.c @@ -8,6 +8,7 @@ #include <signal.h> #include <pwd.h> #include <grp.h> +#include <sched.h> #include <sys/types.h> #include <sys/sysmacros.h> #include <sys/stat.h> @@ -19,6 +20,7 @@ #include "utils.h" #include "log.h" +#include "options.h" #define _POSIX_PATH_MAX 256 @@ -345,9 +347,9 @@ void chk_chroot(void) void mount_root(void) { int s; - s = mount("none", "/", "", MS_SLAVE|MS_REC, NULL); + s = mount("", "/", "none", MS_SLAVE|MS_REC, NULL); if (s) - s = mount("none", "/", "", MS_PRIVATE|MS_REC, NULL); + s = mount("", "/", "none", MS_PRIVATE|MS_REC, NULL); if (s) chk_chroot(); } @@ -399,6 +401,95 @@ int mount_proc(const char *mount_path) return 0; } +int setup_network_namespace(const char *name) +{ + int fd; + char netns_path[PATH_MAX]; + int made_netns_run_dir_mount = 0; + + snprintf(netns_path, sizeof netns_path, "%s/%s", + getopt_str(OPT_NETNS_RUN_DIR), name); + D2("Network Namespace path '%s'", netns_path); + + if (mkdir(getopt_str(OPT_NETNS_RUN_DIR), + S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)) + { + if (errno != EEXIST) { + E_STRERR("Create netns directory '%s'", + getopt_str(OPT_NETNS_RUN_DIR)); + return 1; + } + } + + while (mount("", getopt_str(OPT_NETNS_RUN_DIR), "none", + MS_SHARED|MS_REC, NULL)) + { + /* Fail unless we need to make the mount point */ + if (errno != EINVAL || made_netns_run_dir_mount) { + E_STRERR("Mount netns directory '%s' as shared", + getopt_str(OPT_NETNS_RUN_DIR)); + return 1; + } + + /* Upgrade NETNS_RUN_DIR to a mount point */ + if (mount(getopt_str(OPT_NETNS_RUN_DIR), getopt_str(OPT_NETNS_RUN_DIR), + "none", MS_BIND | MS_REC, NULL)) + { + E_STRERR("Bind mount netns directory '%s'", + getopt_str(OPT_NETNS_RUN_DIR)); + return 1; + } + made_netns_run_dir_mount = 1; + } + + /* Create the filesystem state */ + fd = open(netns_path, O_RDONLY|O_CREAT|O_EXCL, 0); + if (fd < 0 && errno != EEXIST) { + E_STRERR("Create namespace file '%s'", netns_path); + return 1; + } + close(fd); + + if (unshare(CLONE_NEWNET) < 0) { + E_STRERR("Create network namespace '%s'", name); + goto error; + } + + /* Bind the netns last so I can watch for it */ + if (mount("/proc/self/ns/net", netns_path, "none", MS_BIND, NULL) < 0) { + E_STRERR("Bind /proc/self/ns/net to '%s'", netns_path); + goto error; + } + + return 0; +error: + /* cleanup netns? */ + return 1; +} + +int switch_network_namespace(const char *name) +{ + char net_path[PATH_MAX]; + int netns; + + snprintf(net_path, sizeof(net_path), "%s/%s", + getopt_str(OPT_NETNS_RUN_DIR), name); + netns = open(net_path, O_RDONLY | O_CLOEXEC); + if (netns < 0) { + E_STRERR("Cannot open network namespace '%s'", name); + return 1; + } + + if (setns(netns, CLONE_NEWNET) < 0) { + E_STRERR("Setting the network namespace '%s'", name); + close(netns); + return 1; + } + close(netns); + + return 0; +} + int create_device_file_checked(const char *mount_path, const char *device_file, mode_t mode, int add_mode, dev_t dev) { diff --git a/src/utils.h b/src/utils.h index 8e7adc9..f72255b 100644 --- a/src/utils.h +++ b/src/utils.h @@ -46,6 +46,10 @@ int mount_pts(const char *mount_path); int mount_proc(const char *mount_path); +int setup_network_namespace(const char *name); + +int switch_network_namespace(const char *name); + int create_device_file_checked(const char *mount_path, const char *device_file, mode_t mode, int add_mode, dev_t dev); |