Merge pull request #14 from google/deprecate-iface-flag-names

Deprecate current iface/macvlan options.
This commit is contained in:
robertswiecki 2017-05-11 17:20:38 +02:00 committed by GitHub
commit 761ceae285
2 changed files with 206 additions and 177 deletions

381
cmdline.c
View File

@ -30,12 +30,12 @@
#include <limits.h>
#include <pwd.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/personality.h>
#include <sys/mount.h>
#include <sys/personality.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
@ -49,24 +49,127 @@ struct custom_option {
const char *descr;
};
/* *INDENT-OFF* */
struct custom_option custom_opts[] = {
{{"help", no_argument, NULL, 'h'}, "Help plz.."},
{{"mode", required_argument, NULL, 'M'},
"Execution mode (default: o [MODE_STANDALONE_ONCE]):\n"
"\tl: Wait for connections on a TCP port (specified with --port) "
"[MODE_LISTEN_TCP]\n"
"\to: Immediately launch a single process on the console using "
"clone/execve [MODE_STANDALONE_ONCE]\n"
"\te: Immediately launch a single process on the console using execve "
"[MODE_STANDALONE_EXECVE]\n"
"\tr: Immediately launch a single process on the console, keep doing it "
"forever [MODE_STANDALONE_RERUN]"},
{{"chroot", required_argument, NULL, 'c'}, "Directory containing / of the jail (default: none)"},
{{"rw", no_argument, NULL, 0x601}, "Mount / and /proc as RW (default: RO)"},
{{"user", required_argument, NULL, 'u'}, "Username/uid of processess inside the jail (default: your current uid). You can also use inside_ns_uid:outside_ns_uid convention here. Can be specified multiple times"},
{{"group", required_argument, NULL, 'g'}, "Groupname/gid of processess inside the jail (default: your current gid). You can also use inside_ns_gid:global_ns_gid convention here. Can be specified multiple times"},
{{"hostname", required_argument, NULL, 'H'}, "UTS name (hostname) of the jail (default: 'NSJAIL')"},
{{"cwd", required_argument, NULL, 'D'}, "Directory in the namespace the process will run (default: '/')"},
{{"port", required_argument, NULL, 'p'}, "TCP port to bind to (enables MODE_LISTEN_TCP) (default: 0)"},
{{"bindhost", required_argument, NULL, 0x604}, "IP address port to bind to (only in [MODE_LISTEN_TCP]), '::ffff:127.0.0.1' for locahost (default: '::')"},
{{"max_conns_per_ip", required_argument, NULL, 'i'}, "Maximum number of connections per one IP (only in [MODE_LISTEN_TCP]), (default: 0 (unlimited))"},
{{"log", required_argument, NULL, 'l'}, "Log file (default: /proc/self/fd/2)"},
{{"time_limit", required_argument, NULL, 't'}, "Maximum time that a jail can exist, in seconds (default: 600)"},
{{"daemon", no_argument, NULL, 'd'}, "Daemonize after start"},
{{"verbose", no_argument, NULL, 'v'}, "Verbose output"},
{{"quiet", no_argument, NULL, 'q'}, "Only output warning and more important messages"},
{{"keep_env", no_argument, NULL, 'e'}, "Should all environment variables be passed to the child?"},
{{"env", required_argument, NULL, 'E'}, "Environment variable (can be used multiple times)"},
{{"keep_caps", no_argument, NULL, 0x0501}, "Don't drop capabilities (DANGEROUS)"},
{{"silent", no_argument, NULL, 0x0502}, "Redirect child's fd:0/1/2 to /dev/null"},
{{"skip_setsid", no_argument, NULL, 0x0504}, "Don't call setsid(), allows for terminal signal handling in the sandboxed process"},
{{"pass_fd", required_argument, NULL, 0x0505}, "Don't close this FD before executing child (can be specified multiple times), by default: 0/1/2 are kept open"},
{{"pivot_root_only", no_argument, NULL, 0x0506}, "Only perform pivot_root, no chroot. This will enable nested namespaces"},
{{"disable_no_new_privs", no_argument, NULL, 0x0507}, "Don't set the prctl(NO_NEW_PRIVS, 1) (DANGEROUS)"},
{{"rlimit_as", required_argument, NULL, 0x0201}, "RLIMIT_AS in MB, 'max' for RLIM_INFINITY, 'def' for the current value (default: 512)"},
{{"rlimit_core", required_argument, NULL, 0x0202}, "RLIMIT_CORE in MB, 'max' for RLIM_INFINITY, 'def' for the current value (default: 0)"},
{{"rlimit_cpu", required_argument, NULL, 0x0203}, "RLIMIT_CPU, 'max' for RLIM_INFINITY, 'def' for the current value (default: 600)"},
{{"rlimit_fsize", required_argument, NULL, 0x0204}, "RLIMIT_FSIZE in MB, 'max' for RLIM_INFINITY, 'def' for the current value (default: 1)"},
{{"rlimit_nofile", required_argument, NULL, 0x0205}, "RLIMIT_NOFILE, 'max' for RLIM_INFINITY, 'def' for the current value (default: 32)"},
{{"rlimit_nproc", required_argument, NULL, 0x0206}, "RLIMIT_NPROC, 'max' for RLIM_INFINITY, 'def' for the current value (default: 'def')"},
{{"rlimit_stack", required_argument, NULL, 0x0207}, "RLIMIT_STACK in MB, 'max' for RLIM_INFINITY, 'def' for the current value (default: 'def')"},
{{"persona_addr_compat_layout", no_argument, NULL, 0x0301}, "personality(ADDR_COMPAT_LAYOUT)"},
{{"persona_mmap_page_zero", no_argument, NULL, 0x0302}, "personality(MMAP_PAGE_ZERO)"},
{{"persona_read_implies_exec", no_argument, NULL, 0x0303}, "personality(READ_IMPLIES_EXEC)"},
{{"persona_addr_limit_3gb", no_argument, NULL, 0x0304}, "personality(ADDR_LIMIT_3GB)"},
{{"persona_addr_no_randomize", no_argument, NULL, 0x0305}, "personality(ADDR_NO_RANDOMIZE)"},
{{"disable_clone_newnet", no_argument, NULL, 'N'}, "Don't use CLONE_NEWNET. Enable networking inside the jail"},
{{"disable_clone_newuser", no_argument, NULL, 0x0402}, "Don't use CLONE_NEWUSER. Requires euid==0"},
{{"disable_clone_newns", no_argument, NULL, 0x0403}, "Don't use CLONE_NEWNS"},
{{"disable_clone_newpid", no_argument, NULL, 0x0404}, "Don't use CLONE_NEWPID"},
{{"disable_clone_newipc", no_argument, NULL, 0x0405}, "Don't use CLONE_NEWIPC"},
{{"disable_clone_newuts", no_argument, NULL, 0x0406}, "Don't use CLONE_NEWUTS"},
{{"enable_clone_newcgroup", no_argument, NULL, 0x0407}, "Use CLONE_NEWCGROUP"},
{{"uid_mapping", required_argument, NULL, 'U'}, "Add a custom uid mapping of the form inside_uid:outside_uid:count. Setting this requires newuidmap to be present"},
{{"gid_mapping", required_argument, NULL, 'G'}, "Add a custom gid mapping of the form inside_gid:outside_gid:count. Setting this requires newuidmap to be present"},
{{"bindmount_ro", required_argument, NULL, 'R'}, "List of mountpoints to be mounted --bind (ro) inside the container. Can be specified multiple times. Supports 'source' syntax, or 'source:dest'"},
{{"bindmount", required_argument, NULL, 'B'}, "List of mountpoints to be mounted --bind (rw) inside the container. Can be specified multiple times. Supports 'source' syntax, or 'source:dest'"},
{{"tmpfsmount", required_argument, NULL, 'T'}, "List of mountpoints to be mounted as RW/tmpfs inside the container. Can be specified multiple times. Supports 'dest' syntax"},
{{"tmpfs_size", required_argument, NULL, 0x0602}, "Number of bytes to allocate for tmpfsmounts (default: 4194304)"},
{{"disable_proc", no_argument, NULL, 0x0603}, "Disable mounting /proc in the jail"},
{{"seccomp_policy", required_argument, NULL, 'P'}, "Path to file containing seccomp-bpf policy (see kafel/)"},
{{"seccomp_string", required_argument, NULL, 0x0901}, "String with kafel seccomp-bpf policy (see kafel/)"},
{{"cgroup_mem_max", required_argument, NULL, 0x0801}, "Maximum number of bytes to use in the group (default: '0' - disabled)"},
{{"cgroup_mem_mount", required_argument, NULL, 0x0802}, "Location of memory cgroup FS (default: '/sys/fs/cgroup/memory')"},
{{"cgroup_mem_parent", required_argument, NULL, 0x0803}, "Which pre-existing memory cgroup to use as a parent (default: 'NSJAIL')"},
{{"cgroup_pids_max", required_argument, NULL, 0x0811}, "Maximum number of pids in a cgroup (default: '0' - disabled)"},
{{"cgroup_pids_mount", required_argument, NULL, 0x0812}, "Location of pids cgroup FS (default: '/sys/fs/cgroup/pids')"},
{{"cgroup_pids_parent", required_argument, NULL, 0x0813}, "Which pre-existing pids cgroup to use as a parent (default: 'NSJAIL')"},
{{"iface_no_lo", no_argument, NULL, 0x700}, "Don't bring up the 'lo' interface"},
{{"macvlan_iface", required_argument, NULL, 'I'}, "Interface which will be cloned (MACVLAN) and put inside the subprocess' namespace as 'vs'"},
{{"macvlan_vs_ip", required_argument, NULL, 0x701}, "IP of the 'vs' interface (e.g. \"192.168.0.1\")"},
{{"macvlan_vs_nm", required_argument, NULL, 0x702}, "Netmask of the 'vs' interface (e.g. \"255.255.255.0\")"},
{{"macvlan_vs_gw", required_argument, NULL, 0x703}, "Default GW for the 'vs' interface (e.g. \"192.168.0.1\")"},
};
struct custom_option deprecated_opts[] = {
// Compatibilty flags for MACVLAN.
// TODO(rswiecki): Remove this at some point.
{{"iface", required_argument, NULL, 'I'}, "Interface which will be cloned (MACVLAN) and put inside the subprocess' namespace as 'vs'"},
{{"iface_vs_ip", required_argument, NULL, 0x701}, "IP of the 'vs' interface (e.g. \"192.168.0.1\")"},
{{"iface_vs_nm", required_argument, NULL, 0x702}, "Netmask of the 'vs' interface (e.g. \"255.255.255.0\")"},
{{"iface_vs_gw", required_argument, NULL, 0x703}, "Default GW for the 'vs' interface (e.g. \"192.168.0.1\")"},
};
/* *INDENT-ON* */
static const char *logYesNo(bool yes)
{
return (yes ? "true" : "false");
}
static void cmdlineUsage(const char *pname, struct custom_option *opts)
static void cmdlineOptUsage(struct custom_option *option)
{
if (option->opt.val < 0x80) {
LOG_HELP_BOLD(" --%s%s%c %s", option->opt.name, "|-", option->opt.val,
option->opt.has_arg == required_argument ? "VALUE" : "");
} else {
LOG_HELP_BOLD(" --%s %s", option->opt.name,
option->opt.has_arg == required_argument ? "VALUE" : "");
}
LOG_HELP("\t%s", option->descr);
}
static void cmdlineUsage(const char *pname)
{
LOG_HELP_BOLD("Usage: %s [options] -- path_to_command [args]", pname);
LOG_HELP_BOLD("Options:");
for (int i = 0; opts[i].opt.name; i++) {
if (opts[i].opt.val < 0x80) {
LOG_HELP_BOLD(" --%s%s%c %s", opts[i].opt.name, "|-", opts[i].opt.val,
opts[i].opt.has_arg == required_argument ? "VALUE" : "");
} else {
LOG_HELP_BOLD(" --%s %s", opts[i].opt.name,
opts[i].opt.has_arg == required_argument ? "VALUE" : "");
for (size_t i = 0; i < ARRAYSIZE(custom_opts); i++) {
cmdlineOptUsage(&custom_opts[i]);
}
LOG_HELP_BOLD("\nDeprecated options:");
for (size_t i = 0; i < ARRAYSIZE(deprecated_opts); i++) {
cmdlineOptUsage(&deprecated_opts[i]);
// Find replacement flag.
for (size_t j = 0; j < ARRAYSIZE(custom_opts); j++) {
if (custom_opts[j].opt.val == deprecated_opts[i].opt.val) {
LOG_HELP_BOLD("\tDEPRECATED: Use %s instead.",
custom_opts[j].opt.name);
break;
}
}
LOG_HELP("\t%s", opts[i].descr);
}
LOG_HELP_BOLD("\n Examples: ");
LOG_HELP(" Wait on a port 31337 for connections, and run /bin/sh");
@ -99,20 +202,21 @@ void cmdlineLogParams(struct nsjconf_t *nsjconf)
break;
}
LOG_I
("Jail parameters: hostname:'%s', chroot:'%s', process:'%s', bind:[%s]:%d, "
"max_conns_per_ip:%u, time_limit:%ld, personality:%#lx, daemonize:%s, "
"clone_newnet:%s, clone_newuser:%s, clone_newns:%s, clone_newpid:%s, "
"clone_newipc:%s, clonew_newuts:%s, clone_newcgroup:%s, keep_caps:%s, "
"tmpfs_size:%zu, disable_no_new_privs:%s, pivot_root_only:%s",
nsjconf->hostname, nsjconf->chroot, nsjconf->argv[0], nsjconf->bindhost, nsjconf->port,
nsjconf->max_conns_per_ip, nsjconf->tlimit, nsjconf->personality,
logYesNo(nsjconf->daemonize), logYesNo(nsjconf->clone_newnet),
logYesNo(nsjconf->clone_newuser), logYesNo(nsjconf->clone_newns),
logYesNo(nsjconf->clone_newpid), logYesNo(nsjconf->clone_newipc),
logYesNo(nsjconf->clone_newuts), logYesNo(nsjconf->clone_newcgroup),
logYesNo(nsjconf->keep_caps), nsjconf->tmpfs_size,
logYesNo(nsjconf->disable_no_new_privs), logYesNo(nsjconf->pivot_root_only));
LOG_I("Jail parameters: hostname:'%s', chroot:'%s', process:'%s', "
"bind:[%s]:%d, "
"max_conns_per_ip:%u, time_limit:%ld, personality:%#lx, daemonize:%s, "
"clone_newnet:%s, clone_newuser:%s, clone_newns:%s, clone_newpid:%s, "
"clone_newipc:%s, clonew_newuts:%s, clone_newcgroup:%s, keep_caps:%s, "
"tmpfs_size:%zu, disable_no_new_privs:%s, pivot_root_only:%s",
nsjconf->hostname, nsjconf->chroot, nsjconf->argv[0], nsjconf->bindhost,
nsjconf->port, nsjconf->max_conns_per_ip, nsjconf->tlimit,
nsjconf->personality, logYesNo(nsjconf->daemonize),
logYesNo(nsjconf->clone_newnet), logYesNo(nsjconf->clone_newuser),
logYesNo(nsjconf->clone_newns), logYesNo(nsjconf->clone_newpid),
logYesNo(nsjconf->clone_newipc), logYesNo(nsjconf->clone_newuts),
logYesNo(nsjconf->clone_newcgroup), logYesNo(nsjconf->keep_caps),
nsjconf->tmpfs_size, logYesNo(nsjconf->disable_no_new_privs),
logYesNo(nsjconf->pivot_root_only));
{
struct mounts_t *p;
@ -286,56 +390,56 @@ static bool cmdlineParseGid(struct nsjconf_t *nsjconf, char *str)
bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
{
/* *INDENT-OFF* */
(*nsjconf) = (const struct nsjconf_t) {
.hostname = "NSJAIL",
.cwd = "/",
.chroot = NULL,
.argv = NULL,
.port = 0,
.bindhost = "::",
.daemonize = false,
.tlimit = 0,
.pivot_root_only = false,
.keep_caps = false,
.disable_no_new_privs = false,
.rl_as = 512 * (1024 * 1024),
.rl_core = 0,
.rl_cpu = 600,
.rl_fsize = 1 * (1024 * 1024),
.rl_nofile = 32,
.rl_nproc = cmdlineParseRLimit(RLIMIT_NPROC, "def", 1),
.rl_stack = cmdlineParseRLimit(RLIMIT_STACK, "def", 1),
.personality = 0,
.clone_newnet = true,
.clone_newuser = true,
.clone_newns = true,
.clone_newpid = true,
.clone_newipc = true,
.clone_newuts = true,
.clone_newcgroup = false,
.mode = MODE_STANDALONE_ONCE,
.is_root_rw = false,
.is_silent = false,
.skip_setsid = false,
.max_conns_per_ip = 0,
.tmpfs_size = 4 * (1024 * 1024),
.mount_proc = true,
.cgroup_mem_mount = "/sys/fs/cgroup/memory",
.cgroup_mem_parent = "NSJAIL",
.cgroup_mem_max = (size_t)0,
.cgroup_pids_mount = "/sys/fs/cgroup/pids",
.cgroup_pids_parent = "NSJAIL",
.cgroup_pids_max = (size_t)0,
.iface_no_lo = false,
.iface = NULL,
.iface_vs_ip = "0.0.0.0",
.iface_vs_nm = "255.255.255.0",
.iface_vs_gw = "0.0.0.0",
.kafel_file = NULL,
.kafel_string = NULL,
};
/* *INDENT-OFF* */
/* *INDENT-OFF* */
(*nsjconf) = (const struct nsjconf_t){
.hostname = "NSJAIL",
.cwd = "/",
.chroot = NULL,
.argv = NULL,
.port = 0,
.bindhost = "::",
.daemonize = false,
.tlimit = 0,
.pivot_root_only = false,
.keep_caps = false,
.disable_no_new_privs = false,
.rl_as = 512 * (1024 * 1024),
.rl_core = 0,
.rl_cpu = 600,
.rl_fsize = 1 * (1024 * 1024),
.rl_nofile = 32,
.rl_nproc = cmdlineParseRLimit(RLIMIT_NPROC, "def", 1),
.rl_stack = cmdlineParseRLimit(RLIMIT_STACK, "def", 1),
.personality = 0,
.clone_newnet = true,
.clone_newuser = true,
.clone_newns = true,
.clone_newpid = true,
.clone_newipc = true,
.clone_newuts = true,
.clone_newcgroup = false,
.mode = MODE_STANDALONE_ONCE,
.is_root_rw = false,
.is_silent = false,
.skip_setsid = false,
.max_conns_per_ip = 0,
.tmpfs_size = 4 * (1024 * 1024),
.mount_proc = true,
.cgroup_mem_mount = "/sys/fs/cgroup/memory",
.cgroup_mem_parent = "NSJAIL",
.cgroup_mem_max = (size_t)0,
.cgroup_pids_mount = "/sys/fs/cgroup/pids",
.cgroup_pids_parent = "NSJAIL",
.cgroup_pids_max = (size_t)0,
.iface_no_lo = false,
.iface = NULL,
.iface_vs_ip = "0.0.0.0",
.iface_vs_nm = "255.255.255.0",
.iface_vs_gw = "0.0.0.0",
.kafel_file = NULL,
.kafel_string = NULL,
};
/* *INDENT-ON* */
enum llevel_t log_level = INFO;
TAILQ_INIT(&nsjconf->uids);
@ -361,87 +465,23 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
f->fd = STDERR_FILENO;
TAILQ_INSERT_HEAD(&nsjconf->open_fds, f, pointers);
/* *INDENT-OFF* */
struct custom_option custom_opts[] = {
{{"help", no_argument, NULL, 'h'}, "Help plz.."},
{{"mode", required_argument, NULL, 'M'}, "Execution mode (default: o [MODE_STANDALONE_ONCE]):\n"
"\tl: Wait for connections on a TCP port (specified with --port) [MODE_LISTEN_TCP]\n"
"\to: Immediately launch a single process on the console using clone/execve [MODE_STANDALONE_ONCE]\n"
"\te: Immediately launch a single process on the console using execve [MODE_STANDALONE_EXECVE]\n"
"\tr: Immediately launch a single process on the console, keep doing it forever [MODE_STANDALONE_RERUN]"},
{{"chroot", required_argument, NULL, 'c'}, "Directory containing / of the jail (default: none)"},
{{"rw", no_argument, NULL, 0x601}, "Mount / and /proc as RW (default: RO)"},
{{"user", required_argument, NULL, 'u'}, "Username/uid of processess inside the jail (default: your current uid). You can also use inside_ns_uid:outside_ns_uid convention here. Can be specified multiple times"},
{{"group", required_argument, NULL, 'g'}, "Groupname/gid of processess inside the jail (default: your current gid). You can also use inside_ns_gid:global_ns_gid convention here. Can be specified multiple times"},
{{"hostname", required_argument, NULL, 'H'}, "UTS name (hostname) of the jail (default: 'NSJAIL')"},
{{"cwd", required_argument, NULL, 'D'}, "Directory in the namespace the process will run (default: '/')"},
{{"port", required_argument, NULL, 'p'}, "TCP port to bind to (enables MODE_LISTEN_TCP) (default: 0)"},
{{"bindhost", required_argument, NULL, 0x604}, "IP address port to bind to (only in [MODE_LISTEN_TCP]), '::ffff:127.0.0.1' for locahost (default: '::')"},
{{"max_conns_per_ip", required_argument, NULL, 'i'}, "Maximum number of connections per one IP (only in [MODE_LISTEN_TCP]), (default: 0 (unlimited))"},
{{"log", required_argument, NULL, 'l'}, "Log file (default: /proc/self/fd/2)"},
{{"time_limit", required_argument, NULL, 't'}, "Maximum time that a jail can exist, in seconds (default: 600)"},
{{"daemon", no_argument, NULL, 'd'}, "Daemonize after start"},
{{"verbose", no_argument, NULL, 'v'}, "Verbose output"},
{{"quiet", no_argument, NULL, 'q'}, "Only output warning and more important messages"},
{{"keep_env", no_argument, NULL, 'e'}, "Should all environment variables be passed to the child?"},
{{"env", required_argument, NULL, 'E'}, "Environment variable (can be used multiple times)"},
{{"keep_caps", no_argument, NULL, 0x0501}, "Don't drop capabilities (DANGEROUS)"},
{{"silent", no_argument, NULL, 0x0502}, "Redirect child's fd:0/1/2 to /dev/null"},
{{"skip_setsid", no_argument, NULL, 0x0504}, "Don't call setsid(), allows for terminal signal handling in the sandboxed process"},
{{"pass_fd", required_argument, NULL, 0x0505}, "Don't close this FD before executing child (can be specified multiple times), by default: 0/1/2 are kept open"},
{{"pivot_root_only", no_argument, NULL, 0x0506}, "Only perform pivot_root, no chroot. This will enable nested namespaces"},
{{"disable_no_new_privs", no_argument, NULL, 0x0507}, "Don't set the prctl(NO_NEW_PRIVS, 1) (DANGEROUS)"},
{{"rlimit_as", required_argument, NULL, 0x0201}, "RLIMIT_AS in MB, 'max' for RLIM_INFINITY, 'def' for the current value (default: 512)"},
{{"rlimit_core", required_argument, NULL, 0x0202}, "RLIMIT_CORE in MB, 'max' for RLIM_INFINITY, 'def' for the current value (default: 0)"},
{{"rlimit_cpu", required_argument, NULL, 0x0203}, "RLIMIT_CPU, 'max' for RLIM_INFINITY, 'def' for the current value (default: 600)"},
{{"rlimit_fsize", required_argument, NULL, 0x0204}, "RLIMIT_FSIZE in MB, 'max' for RLIM_INFINITY, 'def' for the current value (default: 1)"},
{{"rlimit_nofile", required_argument, NULL, 0x0205}, "RLIMIT_NOFILE, 'max' for RLIM_INFINITY, 'def' for the current value (default: 32)"},
{{"rlimit_nproc", required_argument, NULL, 0x0206}, "RLIMIT_NPROC, 'max' for RLIM_INFINITY, 'def' for the current value (default: 'def')"},
{{"rlimit_stack", required_argument, NULL, 0x0207}, "RLIMIT_STACK in MB, 'max' for RLIM_INFINITY, 'def' for the current value (default: 'def')"},
{{"persona_addr_compat_layout", no_argument, NULL, 0x0301}, "personality(ADDR_COMPAT_LAYOUT)"},
{{"persona_mmap_page_zero", no_argument, NULL, 0x0302}, "personality(MMAP_PAGE_ZERO)"},
{{"persona_read_implies_exec", no_argument, NULL, 0x0303}, "personality(READ_IMPLIES_EXEC)"},
{{"persona_addr_limit_3gb", no_argument, NULL, 0x0304}, "personality(ADDR_LIMIT_3GB)"},
{{"persona_addr_no_randomize", no_argument, NULL, 0x0305}, "personality(ADDR_NO_RANDOMIZE)"},
{{"disable_clone_newnet", no_argument, NULL, 'N'}, "Don't use CLONE_NEWNET. Enable networking inside the jail"},
{{"disable_clone_newuser", no_argument, NULL, 0x0402}, "Don't use CLONE_NEWUSER. Requires euid==0"},
{{"disable_clone_newns", no_argument, NULL, 0x0403}, "Don't use CLONE_NEWNS"},
{{"disable_clone_newpid", no_argument, NULL, 0x0404}, "Don't use CLONE_NEWPID"},
{{"disable_clone_newipc", no_argument, NULL, 0x0405}, "Don't use CLONE_NEWIPC"},
{{"disable_clone_newuts", no_argument, NULL, 0x0406}, "Don't use CLONE_NEWUTS"},
{{"enable_clone_newcgroup", no_argument, NULL, 0x0407}, "Use CLONE_NEWCGROUP"},
{{"uid_mapping", required_argument, NULL, 'U'}, "Add a custom uid mapping of the form inside_uid:outside_uid:count. Setting this requires newuidmap to be present"},
{{"gid_mapping", required_argument, NULL, 'G'}, "Add a custom gid mapping of the form inside_gid:outside_gid:count. Setting this requires newuidmap to be present"},
{{"bindmount_ro", required_argument, NULL, 'R'}, "List of mountpoints to be mounted --bind (ro) inside the container. Can be specified multiple times. Supports 'source' syntax, or 'source:dest'"},
{{"bindmount", required_argument, NULL, 'B'}, "List of mountpoints to be mounted --bind (rw) inside the container. Can be specified multiple times. Supports 'source' syntax, or 'source:dest'"},
{{"tmpfsmount", required_argument, NULL, 'T'}, "List of mountpoints to be mounted as RW/tmpfs inside the container. Can be specified multiple times. Supports 'dest' syntax"},
{{"tmpfs_size", required_argument, NULL, 0x0602}, "Number of bytes to allocate for tmpfsmounts (default: 4194304)"},
{{"disable_proc", no_argument, NULL, 0x0603}, "Disable mounting /proc in the jail"},
{{"seccomp_policy", required_argument, NULL, 'P'}, "Path to file containing seccomp-bpf policy (see kafel/)"},
{{"seccomp_string", required_argument, NULL, 0x0901}, "String with kafel seccomp-bpf policy (see kafel/)"},
{{"cgroup_mem_max", required_argument, NULL, 0x0801}, "Maximum number of bytes to use in the group (default: '0' - disabled)"},
{{"cgroup_mem_mount", required_argument, NULL, 0x0802}, "Location of memory cgroup FS (default: '/sys/fs/cgroup/memory')"},
{{"cgroup_mem_parent", required_argument, NULL, 0x0803}, "Which pre-existing memory cgroup to use as a parent (default: 'NSJAIL')"},
{{"cgroup_pids_max", required_argument, NULL, 0x0811}, "Maximum number of pids in a cgroup (default: '0' - disabled)"},
{{"cgroup_pids_mount", required_argument, NULL, 0x0812}, "Location of pids cgroup FS (default: '/sys/fs/cgroup/pids')"},
{{"cgroup_pids_parent", required_argument, NULL, 0x0813}, "Which pre-existing pids cgroup to use as a parent (default: 'NSJAIL')"},
{{"iface_no_lo", no_argument, NULL, 0x700}, "Don't bring up the 'lo' interface"},
{{"iface", required_argument, NULL, 'I'}, "Interface which will be cloned (MACVLAN) and put inside the subprocess' namespace as 'vs'"},
{{"iface_vs_ip", required_argument, NULL, 0x701}, "IP of the 'vs' interface (e.g. \"192.168.0.1\")"},
{{"iface_vs_nm", required_argument, NULL, 0x702}, "Netmask of the 'vs' interface (e.g. \"255.255.255.0\")"},
{{"iface_vs_gw", required_argument, NULL, 0x703}, "Default GW for the 'vs' interface (e.g. \"192.168.0.1\")"},
{{0, 0, 0, 0}, NULL},
};
/* *INDENT-ON* */
struct option opts[ARRAYSIZE(custom_opts)];
// Generate options array for getopt_long.
size_t options_length = ARRAYSIZE(custom_opts) + ARRAYSIZE(deprecated_opts) + 1;
struct option opts[options_length];
for (unsigned i = 0; i < ARRAYSIZE(custom_opts); i++) {
opts[i] = custom_opts[i].opt;
}
for (unsigned i = 0; i < ARRAYSIZE(deprecated_opts); i++) {
opts[ARRAYSIZE(custom_opts) + i] = deprecated_opts[i].opt;
}
// Last, NULL option as a terminator.
struct option terminator = { NULL, 0, NULL, 0 };
memcpy(&opts[options_length - 1].name, &terminator, sizeof(terminator));
int opt_index = 0;
for (;;) {
int c = getopt_long(argc, argv, "H:D:c:p:i:u:g:l:t:M:Ndvqeh?E:R:B:T:P:I:U:G:", opts,
int c = getopt_long(argc, argv,
"H:D:c:p:i:u:g:l:t:M:Ndvqeh?E:R:B:T:P:I:U:G:", opts,
&opt_index);
if (c == -1) {
break;
@ -495,7 +535,7 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
nsjconf->tlimit = strtol(optarg, NULL, 0);
break;
case 'h': /* help */
cmdlineUsage(argv[0], custom_opts);
cmdlineUsage(argv[0]);
exit(0);
break;
case 0x0201:
@ -564,14 +604,12 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
case 0x0504:
nsjconf->skip_setsid = true;
break;
case 0x0505:
{
case 0x0505:{
struct fds_t *f;
f = utilMalloc(sizeof(struct fds_t));
f->fd = (int)strtol(optarg, NULL, 0);
TAILQ_INSERT_HEAD(&nsjconf->open_fds, f, pointers);
}
break;
} break;
case 0x0506:
nsjconf->pivot_root_only = true;
break;
@ -589,16 +627,13 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
case 0x0603:
nsjconf->mount_proc = false;
break;
case 'E':
{
case 'E':{
struct charptr_t *p = utilMalloc(sizeof(struct charptr_t));
p->val = optarg;
TAILQ_INSERT_TAIL(&nsjconf->envs, p, pointers);
}
break;
} break;
case 'U':
case 'G':
{
case 'G':{
struct mapping_t *p = utilMalloc(sizeof(struct mapping_t));
p->inside_id = optarg;
char *outside_id = cmdlineSplitStrByColon(optarg);
@ -611,8 +646,7 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
}
}
break;
case 'R':
{
case 'R':{
struct mounts_t *p = utilMalloc(sizeof(struct mounts_t));
p->src = optarg;
p->dst = cmdlineSplitStrByColon(optarg);
@ -620,10 +654,8 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
p->options = "";
p->fs_type = "";
TAILQ_INSERT_TAIL(&nsjconf->mountpts, p, pointers);
}
break;
case 'B':
{
} break;
case 'B':{
struct mounts_t *p = utilMalloc(sizeof(struct mounts_t));
p->src = optarg;
p->dst = cmdlineSplitStrByColon(optarg);
@ -631,10 +663,8 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
p->options = "";
p->fs_type = "";
TAILQ_INSERT_TAIL(&nsjconf->mountpts, p, pointers);
}
break;
case 'T':
{
} break;
case 'T':{
struct mounts_t *p = utilMalloc(sizeof(struct mounts_t));
p->src = NULL;
p->dst = optarg;
@ -642,8 +672,7 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
p->options = cmdlineTmpfsSz;
p->fs_type = "tmpfs";
TAILQ_INSERT_TAIL(&nsjconf->mountpts, p, pointers);
}
break;
} break;
case 'M':
switch (optarg[0]) {
case 'l':
@ -663,7 +692,7 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
LOG_E(" -M o - MODE_STANDALONE_ONCE");
LOG_E(" -M r - MODE_STANDALONE_RERUN");
LOG_E(" -M e - MODE_STANDALONE_EXECVE");
cmdlineUsage(argv[0], custom_opts);
cmdlineUsage(argv[0]);
return false;
break;
}
@ -710,7 +739,7 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
nsjconf->kafel_string = optarg;
break;
default:
cmdlineUsage(argv[0], custom_opts);
cmdlineUsage(argv[0]);
return false;
break;
}
@ -772,7 +801,7 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
nsjconf->argv = &argv[optind];
if (nsjconf->argv[0] == NULL) {
LOG_E("No command provided");
cmdlineUsage(argv[0], custom_opts);
cmdlineUsage(argv[0]);
return false;
}

View File

@ -22,8 +22,8 @@
#ifndef NS_CMDLINE_H
#define NS_CMDLINE_H
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/time.h>
#include "common.h"