2015-05-15 05:44:48 +08:00
/*
nsjail - cmdline parsing
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Copyright 2014 Google Inc . All Rights Reserved .
Licensed under the Apache License , Version 2.0 ( the " License " ) ;
you may not use this file except in compliance with the License .
You may obtain a copy of the License at
http : //www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing , software
distributed under the License is distributed on an " AS IS " BASIS ,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
See the License for the specific language governing permissions and
limitations under the License .
*/
# include "cmdline.h"
# include <ctype.h>
# include <errno.h>
# include <getopt.h>
# include <grp.h>
# include <limits.h>
# include <pwd.h>
# include <stdbool.h>
# include <stdlib.h>
# include <stdio.h>
2015-10-17 22:48:30 +08:00
# include <string.h>
2015-05-15 05:44:48 +08:00
# include <strings.h>
# include <sys/personality.h>
2015-10-17 22:48:30 +08:00
# include <sys/mount.h>
2015-05-15 05:44:48 +08:00
# include <sys/time.h>
# include <unistd.h>
# include "common.h"
# include "log.h"
2016-01-17 11:14:09 +08:00
# include "util.h"
2015-05-15 05:44:48 +08:00
struct custom_option {
struct option opt ;
const char * descr ;
} ;
static const char * logYesNo ( bool yes )
{
return ( yes ? " true " : " false " ) ;
}
static void cmdlineHelp ( const char * pname , struct custom_option * opts )
{
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 ( isprint ( opts [ i ] . opt . val ) ) {
2015-08-16 02:10:07 +08:00
LOG_HELP_BOLD ( " --%s%s%c %s " , opts [ i ] . opt . name , " |- " , opts [ i ] . opt . val ,
opts [ i ] . opt . has_arg = = required_argument ? " [val] " : " " ) ;
2015-05-15 05:44:48 +08:00
} else {
LOG_HELP_BOLD ( " --%s %s " , opts [ i ] . opt . name ,
opts [ i ] . opt . has_arg = = required_argument ? " [val] " : " " ) ;
}
LOG_HELP ( " \t %s " , opts [ i ] . descr ) ;
}
}
void cmdlineLogParams ( struct nsjconf_t * nsjconf )
{
switch ( nsjconf - > mode ) {
case MODE_LISTEN_TCP :
LOG_I ( " Mode: LISTEN_TCP " ) ;
break ;
case MODE_STANDALONE_ONCE :
LOG_I ( " Mode: STANDALONE_ONCE " ) ;
break ;
2015-08-15 22:02:38 +08:00
case MODE_STANDALONE_EXECVE :
LOG_I ( " Mode: STANDALONE_EXECVE " ) ;
break ;
2015-05-15 05:44:48 +08:00
case MODE_STANDALONE_RERUN :
LOG_I ( " Mode: STANDALONE_RERUN " ) ;
break ;
default :
LOG_F ( " Mode: UNKNOWN " ) ;
break ;
}
LOG_I
( " Jail parameters: hostname:'%s', chroot:'%s', process:'%s', port:%d, "
2016-01-23 14:05:24 +08:00
" max_conns_per_ip:%u, uid:(ns:%u, global:%u), gid:(ns:%u, global:%u), time_limit:%ld, personality:%#lx, daemonize:%s, "
2015-05-15 05:44:48 +08:00
" clone_newnet:%s, clone_newuser:%s, clone_newns:%s, clone_newpid:%s, "
2015-07-08 04:17:44 +08:00
" clone_newipc:%s, clonew_newuts:%s, apply_sandbox:%s, keep_caps:%s, "
2015-07-08 06:54:59 +08:00
" tmpfs_size:%zu " ,
2015-05-15 05:44:48 +08:00
nsjconf - > hostname , nsjconf - > chroot , nsjconf - > argv [ 0 ] , nsjconf - > port ,
2016-01-23 14:05:24 +08:00
nsjconf - > max_conns_per_ip , nsjconf - > inside_uid , nsjconf - > outside_uid ,
nsjconf - > inside_gid , nsjconf - > outside_gid , nsjconf - > tlimit , nsjconf - > personality ,
logYesNo ( nsjconf - > daemonize ) , logYesNo ( nsjconf - > clone_newnet ) ,
2015-05-15 05:44:48 +08:00
logYesNo ( nsjconf - > clone_newuser ) , logYesNo ( nsjconf - > clone_newns ) ,
logYesNo ( nsjconf - > clone_newpid ) , logYesNo ( nsjconf - > clone_newipc ) ,
2015-07-08 04:17:44 +08:00
logYesNo ( nsjconf - > clone_newuts ) , logYesNo ( nsjconf - > apply_sandbox ) ,
logYesNo ( nsjconf - > keep_caps ) , nsjconf - > tmpfs_size ) ;
2015-06-18 09:00:39 +08:00
2015-10-17 22:48:30 +08:00
struct mounts_t * p ;
2016-01-09 23:09:05 +08:00
TAILQ_FOREACH ( p , & nsjconf - > mountpts , pointers ) {
2015-10-18 01:14:57 +08:00
LOG_I ( " Mount point: src:'%s' dst:'%s' type:'%s' flags:0x%tx options:'%s' " ,
2015-10-17 22:48:30 +08:00
p - > src , p - > dst , p - > fs_type , p - > flags , p - > options ) ;
2015-05-15 05:44:48 +08:00
}
}
static void cmdlineUsage ( const char * pname , struct custom_option * opts )
{
cmdlineHelp ( pname , opts ) ;
exit ( 0 ) ;
}
static bool cmdlineIsANumber ( const char * s )
{
for ( int i = 0 ; s [ i ] ; s + + ) {
if ( ! isdigit ( s [ i ] ) & & s [ i ] ! = ' x ' ) {
return false ;
}
}
return true ;
}
rlim_t cmdlineParseRLimit ( int res , const char * optarg , unsigned long mul )
{
2015-10-14 01:06:49 +08:00
struct rlimit64 cur ;
if ( prlimit64 ( 0 , res , NULL , & cur ) = = - 1 ) {
2015-05-15 05:44:48 +08:00
PLOG_F ( " getrlimit(%d) " , res ) ;
}
if ( strcasecmp ( optarg , " max " ) = = 0 ) {
return cur . rlim_max ;
}
if ( strcasecmp ( optarg , " def " ) = = 0 ) {
return cur . rlim_cur ;
}
if ( cmdlineIsANumber ( optarg ) = = false ) {
2015-08-16 02:10:07 +08:00
LOG_F ( " RLIMIT %d needs a numeric or 'max'/'def' value ('%s' provided) " , res ,
optarg ) ;
2015-05-15 05:44:48 +08:00
}
2015-10-19 02:47:44 +08:00
rlim64_t val = strtoull ( optarg , NULL , 0 ) * mul ;
2015-10-14 01:06:49 +08:00
if ( val = = ULLONG_MAX & & errno ! = 0 ) {
2015-05-15 05:44:48 +08:00
PLOG_F ( " strtoul('%s', 0) " , optarg ) ;
}
return val ;
}
2015-10-17 22:48:30 +08:00
/* findSpecDestination mutates spec (source:dest) to have a null byte instead
* of ' : ' in between source and dest , then returns a pointer to the dest
* string . */
2016-01-23 14:05:24 +08:00
static char * cmdlineSplitStrByColon ( char * spec )
2015-10-17 22:48:30 +08:00
{
char * dest = spec ;
while ( * dest ! = ' : ' & & * dest ! = ' \0 ' ) {
dest + + ;
}
switch ( * dest ) {
case ' : ' :
* dest = ' \0 ' ;
return dest + 1 ;
case ' \0 ' :
return spec ;
default :
// not reached
return spec ;
}
}
2016-01-23 14:05:24 +08:00
static bool cmdlineParseUid ( struct nsjconf_t * nsjconf , char * str )
{
if ( str = = NULL ) {
return true ;
}
char * second = cmdlineSplitStrByColon ( str ) ;
struct passwd * pw = getpwnam ( str ) ;
if ( pw ! = NULL ) {
nsjconf - > inside_uid = pw - > pw_uid ;
} else if ( cmdlineIsANumber ( str ) ) {
nsjconf - > inside_uid = ( uid_t ) strtoull ( str , NULL , 0 ) ;
} else {
LOG_E ( " No such user '%s' " , str ) ;
return false ;
}
if ( str = = second ) {
return true ;
}
pw = getpwnam ( second ) ;
if ( pw ! = NULL ) {
nsjconf - > outside_uid = pw - > pw_uid ;
} else if ( cmdlineIsANumber ( second ) ) {
nsjconf - > outside_uid = ( uid_t ) strtoull ( second , NULL , 0 ) ;
} else {
LOG_E ( " No such user '%s' " , second ) ;
return false ;
}
return true ;
}
static bool cmdlineParseGid ( struct nsjconf_t * nsjconf , char * str )
{
if ( str = = NULL ) {
return true ;
}
char * second = cmdlineSplitStrByColon ( str ) ;
struct group * gr = getgrnam ( str ) ;
if ( gr ! = NULL ) {
nsjconf - > inside_gid = gr - > gr_gid ;
} else if ( cmdlineIsANumber ( str ) ) {
nsjconf - > inside_gid = ( gid_t ) strtoull ( str , NULL , 0 ) ;
} else {
LOG_E ( " No such group '%s' " , str ) ;
return false ;
}
if ( str = = second ) {
return true ;
}
gr = getgrnam ( second ) ;
if ( gr ! = NULL ) {
nsjconf - > outside_gid = gr - > gr_gid ;
} else if ( cmdlineIsANumber ( second ) ) {
nsjconf - > outside_gid = ( gid_t ) strtoull ( second , NULL , 0 ) ;
} else {
LOG_E ( " No such group '%s' " , second ) ;
return false ;
}
return true ;
}
2015-05-15 05:44:48 +08:00
bool cmdlineParse ( int argc , char * argv [ ] , struct nsjconf_t * nsjconf )
{
2015-06-17 22:52:51 +08:00
/* *INDENT-OFF* */
( * nsjconf ) = ( struct nsjconf_t ) {
. hostname = " NSJAIL " ,
2015-11-07 20:01:44 +08:00
. cwd = " / " ,
2016-01-26 05:27:06 +08:00
. chroot = " / " ,
2015-06-17 22:52:51 +08:00
. argv = NULL ,
. port = 31337 ,
. daemonize = false ,
. tlimit = 0 ,
. apply_sandbox = true ,
. verbose = false ,
. keep_caps = 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 ,
. mode = MODE_LISTEN_TCP ,
. is_root_rw = false ,
. is_silent = false ,
2016-01-26 01:09:32 +08:00
. skip_setsid = false ,
2015-06-17 22:52:51 +08:00
. iface = NULL ,
2016-01-23 14:05:24 +08:00
. inside_uid = getuid ( ) ,
. inside_gid = getgid ( ) ,
. outside_uid = getuid ( ) ,
. outside_gid = getgid ( ) ,
2015-06-17 22:52:51 +08:00
. max_conns_per_ip = 0 ,
2015-07-08 06:54:59 +08:00
. tmpfs_size = 4 * ( 1024 * 1024 ) ,
2015-08-15 22:02:38 +08:00
. mount_proc = true ,
2015-06-17 22:52:51 +08:00
} ;
/* *INDENT-OFF* */
2016-01-27 00:42:10 +08:00
TAILQ_INIT ( & nsjconf - > envs ) ;
2016-01-09 23:09:05 +08:00
TAILQ_INIT ( & nsjconf - > pids ) ;
TAILQ_INIT ( & nsjconf - > mountpts ) ;
2015-06-18 09:00:39 +08:00
2016-01-23 14:05:24 +08:00
char * user = NULL ;
char * group = NULL ;
2015-05-15 05:44:48 +08:00
const char * logfile = NULL ;
2015-10-17 22:48:30 +08:00
static char cmdlineTmpfsSz [ PATH_MAX ] = " size=4194304 " ;
2015-05-15 05:44:48 +08:00
/* *INDENT-OFF* */
struct custom_option custom_opts [ ] = {
{ { " help " , no_argument , NULL , ' h ' } , " Help plz.. " } ,
{ { " mode " , required_argument , NULL , ' M ' } , " Execution mode (default: l [MODE_LISTEN_TCP]): \n "
" \t l: Listen to connections on a TCP port (specified with --port) [MODE_LISTEN_TCP] \n "
2015-08-15 22:02:38 +08:00
" \t o: Immediately launch a single process on a console using clone/execve [MODE_STANDALONE_ONCE] \n "
" \t e: Immediately launch a single process on a console using execve [MODE_STANDALONE_EXECVE] \n "
2015-05-15 05:44:48 +08:00
" \t r: Immediately launch a single process on a console, keep doing it forever [MODE_STANDALONE_RERUN] " } ,
2016-01-14 22:26:18 +08:00
{ { " cmd " , no_argument , NULL , 0x500 } , " Equivalent of -Mo (MODE_STANDALONE_ONCE), run command on a local console, once " } ,
2016-01-26 05:27:06 +08:00
{ { " chroot " , required_argument , NULL , ' c ' } , " Directory containing / of the jail (default: \" / \" ) " } ,
2016-01-14 22:44:29 +08:00
{ { " rw " , no_argument , NULL , 0x0601 } , " Mount / as RW (default: RO) " } ,
2015-05-15 05:44:48 +08:00
{ { " user " , required_argument , NULL , ' u ' } , " Username/uid of processess inside the jail (default: 'nobody') " } ,
{ { " group " , required_argument , NULL , ' g ' } , " Groupname/gid of processess inside the jail (default: 'nogroup') " } ,
{ { " hostname " , required_argument , NULL , ' H ' } , " UTS name (hostname) of the jail (default: 'NSJAIL') " } ,
2015-11-07 20:01:44 +08:00
{ { " cwd " , required_argument , NULL , ' D ' } , " Directory in the namespace the process will run (default: '/') " } ,
2015-05-15 05:44:48 +08:00
{ { " port " , required_argument , NULL , ' p ' } , " TCP port to bind to (only in [MODE_LISTEN_TCP]) (default: 31337) " } ,
{ { " max_conns_per_ip " , required_argument , NULL , ' i ' } , " Maximum number of connections per one IP (default: 0 (unlimited)) " } ,
2015-08-15 22:05:57 +08:00
{ { " log " , required_argument , NULL , ' l ' } , " Log file (default: /proc/self/fd/2) " } ,
2015-05-15 05:44:48 +08:00
{ { " 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? (default: false) " } ,
{ { " verbose " , no_argument , NULL , ' v ' } , " Verbose output (default: false) " } ,
{ { " keep_env " , no_argument , NULL , ' e ' } , " Should all environment variables be passed to the child? (default: false) " } ,
2016-01-27 00:42:10 +08:00
{ { " env " , required_argument , NULL , ' E ' } , " Environment variable (can be used multiple times) " } ,
2015-08-15 22:02:38 +08:00
{ { " keep_caps " , no_argument , NULL , 0x0501 } , " Don't drop capabilities (DANGEROUS) (default: false) " } ,
{ { " silent " , no_argument , NULL , 0x0502 } , " Redirect child's fd:0/1/2 to /dev/null (default: false) " } ,
{ { " disable_sandbox " , no_argument , NULL , 0x0503 } , " Don't enable the seccomp-bpf sandboxing (default: false) " } ,
2016-01-26 01:09:32 +08:00
{ { " skip_setsid " , no_argument , NULL , 0x0504 } , " Don't call setsid(), allows for terminal signal handling in the sandboxed process (default: false) " } ,
2015-05-15 05:44:48 +08:00
{ { " 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) (default: false) " } ,
{ { " persona_mmap_page_zero " , no_argument , NULL , 0x0302 } , " personality(MMAP_PAGE_ZERO) (default: false) " } ,
{ { " persona_read_implies_exec " , no_argument , NULL , 0x0303 } , " personality(READ_IMPLIES_EXEC) (default: false) " } ,
{ { " persona_addr_limit_3gb " , no_argument , NULL , 0x0304 } , " personality(ADDR_LIMIT_3GB) (default: false) " } ,
{ { " persona_addr_no_randomize " , no_argument , NULL , 0x0305 } , " personality(ADDR_NO_RANDOMIZE) (default: false) " } ,
{ { " disable_clone_newnet " , no_argument , NULL , ' N ' } , " Enable networking inside the jail (default: false) " } ,
{ { " disable_clone_newuser " , no_argument , NULL , 0x0402 } , " Don't use CLONE_NEWUSER (default: false) " } ,
{ { " disable_clone_newns " , no_argument , NULL , 0x0403 } , " Don't use CLONE_NEWNS (default: false) " } ,
{ { " disable_clone_newpid " , no_argument , NULL , 0x0404 } , " Don't use CLONE_NEWPID (default: false) " } ,
{ { " disable_clone_newipc " , no_argument , NULL , 0x0405 } , " Don't use CLONE_NEWIPC (default: false) " } ,
{ { " disable_clone_newuts " , no_argument , NULL , 0x0406 } , " Don't use CLONE_NEWUTS (default: false) " } ,
2015-08-12 10:27:57 +08:00
{ { " 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'. (default: none) " } ,
2015-07-08 01:15:37 +08:00
{ { " 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'. (default: none) " } ,
{ { " 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. (default: none) " } ,
2015-05-28 09:37:08 +08:00
{ { " iface " , required_argument , NULL , ' I ' } , " Interface which will be cloned (MACVTAP) and put inside the subprocess' namespace " } ,
2015-08-15 22:02:38 +08:00
{ { " tmpfs_size " , required_argument , NULL , 0x0602 } , " Number of bytes to allocate for tmpfsmounts (default: 4194304) " } ,
{ { " disable_proc " , no_argument , NULL , 0x0603 } , " Disable mounting /proc (default: false) " } ,
2015-05-15 05:44:48 +08:00
{ { 0 , 0 , 0 , 0 } , NULL } ,
} ;
/* *INDENT-ON* */
struct option opts [ ARRAYSIZE ( custom_opts ) ] ;
for ( unsigned i = 0 ; i < ARRAYSIZE ( custom_opts ) ; i + + ) {
opts [ i ] = custom_opts [ i ] . opt ;
}
int opt_index = 0 ;
for ( ; ; ) {
2016-01-27 00:42:10 +08:00
int c = getopt_long ( argc , argv , " H:D:c:p:i:u:g:l:t:M:Ndveh?E:R:B:T:I: " , opts ,
& opt_index ) ;
2015-05-15 05:44:48 +08:00
if ( c = = - 1 ) {
break ;
}
switch ( c ) {
case ' H ' :
nsjconf - > hostname = optarg ;
break ;
2015-11-07 20:01:44 +08:00
case ' D ' :
nsjconf - > cwd = optarg ;
break ;
2015-05-15 05:44:48 +08:00
case ' c ' :
nsjconf - > chroot = optarg ;
break ;
case ' p ' :
nsjconf - > port = strtoul ( optarg , NULL , 0 ) ;
break ;
case ' i ' :
nsjconf - > max_conns_per_ip = strtoul ( optarg , NULL , 0 ) ;
break ;
case ' u ' :
user = optarg ;
break ;
case ' g ' :
group = optarg ;
break ;
case ' l ' :
logfile = optarg ;
break ;
case ' d ' :
nsjconf - > daemonize = true ;
break ;
case ' v ' :
nsjconf - > verbose = true ;
break ;
case ' e ' :
nsjconf - > keep_env = true ;
break ;
case ' t ' :
nsjconf - > tlimit = strtol ( optarg , NULL , 0 ) ;
break ;
case ' h ' : /* help */
case ' ? ' : /* help */
cmdlineUsage ( argv [ 0 ] , custom_opts ) ;
break ;
case 0x0201 :
nsjconf - > rl_as = cmdlineParseRLimit ( RLIMIT_AS , optarg , ( 1024 * 1024 ) ) ;
break ;
case 0x0202 :
nsjconf - > rl_core = cmdlineParseRLimit ( RLIMIT_CORE , optarg , ( 1024 * 1024 ) ) ;
break ;
case 0x0203 :
nsjconf - > rl_cpu = cmdlineParseRLimit ( RLIMIT_CPU , optarg , 1 ) ;
break ;
case 0x0204 :
nsjconf - > rl_fsize = cmdlineParseRLimit ( RLIMIT_FSIZE , optarg , ( 1024 * 1024 ) ) ;
break ;
case 0x0205 :
nsjconf - > rl_nofile = cmdlineParseRLimit ( RLIMIT_NOFILE , optarg , 1 ) ;
break ;
case 0x0206 :
nsjconf - > rl_nproc = cmdlineParseRLimit ( RLIMIT_NPROC , optarg , 1 ) ;
break ;
case 0x0207 :
nsjconf - > rl_stack = cmdlineParseRLimit ( RLIMIT_STACK , optarg , ( 1024 * 1024 ) ) ;
break ;
case 0x0301 :
nsjconf - > personality | = ADDR_COMPAT_LAYOUT ;
break ;
case 0x0302 :
nsjconf - > personality | = MMAP_PAGE_ZERO ;
break ;
case 0x0303 :
nsjconf - > personality | = READ_IMPLIES_EXEC ;
break ;
case 0x0304 :
nsjconf - > personality | = ADDR_LIMIT_3GB ;
break ;
case 0x0305 :
nsjconf - > personality | = ADDR_NO_RANDOMIZE ;
break ;
case ' N ' :
nsjconf - > clone_newnet = false ;
break ;
case 0x0402 :
nsjconf - > clone_newuser = false ;
break ;
case 0x0403 :
nsjconf - > clone_newns = false ;
break ;
case 0x0404 :
nsjconf - > clone_newpid = false ;
break ;
case 0x0405 :
nsjconf - > clone_newipc = false ;
break ;
case 0x0406 :
nsjconf - > clone_newuts = false ;
break ;
2016-01-14 22:26:18 +08:00
case 0x0500 :
nsjconf - > mode = MODE_STANDALONE_ONCE ;
break ;
2015-05-15 05:44:48 +08:00
case 0x0501 :
2015-08-15 22:02:38 +08:00
nsjconf - > keep_caps = true ;
2015-05-15 05:44:48 +08:00
break ;
case 0x0502 :
2015-08-15 22:02:38 +08:00
nsjconf - > is_silent = true ;
2015-05-15 05:44:48 +08:00
break ;
case 0x0503 :
2015-08-15 22:02:38 +08:00
nsjconf - > apply_sandbox = false ;
break ;
2016-01-26 01:09:32 +08:00
case 0x0504 :
nsjconf - > skip_setsid = true ;
break ;
2015-08-15 22:02:38 +08:00
case 0x0601 :
2015-05-15 05:44:48 +08:00
nsjconf - > is_root_rw = true ;
break ;
2015-08-15 22:02:38 +08:00
case 0x0602 :
nsjconf - > tmpfs_size = strtoull ( optarg , NULL , 0 ) ;
2015-10-17 22:48:30 +08:00
snprintf ( cmdlineTmpfsSz , sizeof ( cmdlineTmpfsSz ) , " size=%zu " ,
nsjconf - > tmpfs_size ) ;
2015-08-15 22:02:38 +08:00
break ;
case 0x0603 :
nsjconf - > mount_proc = false ;
2015-05-15 05:44:48 +08:00
break ;
2016-01-27 00:42:10 +08:00
case ' E ' :
{
struct charptr_t * p = util_malloc ( sizeof ( struct charptr_t ) ) ;
p - > val = optarg ;
TAILQ_INSERT_TAIL ( & nsjconf - > envs , p , pointers ) ;
}
break ;
2015-08-12 10:27:57 +08:00
case ' R ' :
2015-07-08 01:15:37 +08:00
{
2016-01-17 11:14:09 +08:00
struct mounts_t * p = util_malloc ( sizeof ( struct mounts_t ) ) ;
2015-10-17 22:48:30 +08:00
p - > src = optarg ;
2016-01-23 14:05:24 +08:00
p - > dst = cmdlineSplitStrByColon ( optarg ) ;
2015-10-17 22:48:30 +08:00
p - > flags = MS_BIND | MS_REC | MS_PRIVATE | MS_RDONLY ;
p - > options = NULL ;
p - > fs_type = NULL ;
2016-01-09 23:09:05 +08:00
TAILQ_INSERT_TAIL ( & nsjconf - > mountpts , p , pointers ) ;
2015-07-08 01:15:37 +08:00
}
break ;
2015-05-15 05:44:48 +08:00
case ' B ' :
2015-06-18 09:00:39 +08:00
{
2016-01-17 11:14:09 +08:00
struct mounts_t * p = util_malloc ( sizeof ( struct mounts_t ) ) ;
2015-10-17 22:48:30 +08:00
p - > src = optarg ;
2016-01-23 14:05:24 +08:00
p - > dst = cmdlineSplitStrByColon ( optarg ) ;
2015-10-17 22:48:30 +08:00
p - > flags = MS_BIND | MS_REC | MS_PRIVATE ;
p - > options = NULL ;
p - > fs_type = NULL ;
2016-01-09 23:09:05 +08:00
TAILQ_INSERT_TAIL ( & nsjconf - > mountpts , p , pointers ) ;
2015-05-15 05:44:48 +08:00
}
break ;
case ' T ' :
2015-06-18 09:00:39 +08:00
{
2016-01-17 11:14:09 +08:00
struct mounts_t * p = util_malloc ( sizeof ( struct mounts_t ) ) ;
2015-10-17 22:48:30 +08:00
p - > src = " none " ;
p - > dst = optarg ;
p - > flags = 0 ;
p - > options = cmdlineTmpfsSz ;
p - > fs_type = " tmpfs " ;
2016-01-09 23:09:05 +08:00
TAILQ_INSERT_TAIL ( & nsjconf - > mountpts , p , pointers ) ;
2015-05-15 05:44:48 +08:00
}
break ;
case ' M ' :
switch ( optarg [ 0 ] ) {
case ' l ' :
nsjconf - > mode = MODE_LISTEN_TCP ;
break ;
case ' o ' :
nsjconf - > mode = MODE_STANDALONE_ONCE ;
break ;
2015-08-15 22:02:38 +08:00
case ' e ' :
nsjconf - > mode = MODE_STANDALONE_EXECVE ;
break ;
2015-05-15 05:44:48 +08:00
case ' r ' :
nsjconf - > mode = MODE_STANDALONE_RERUN ;
break ;
default :
LOG_E ( " Modes supported: -M l - MODE_LISTEN_TCP (default) " ) ;
LOG_E ( " -M o - MODE_STANDALONE_ONCE " ) ;
LOG_E ( " -M r - MODE_STANDALONE_RERUN " ) ;
2016-01-17 11:14:09 +08:00
LOG_E ( " -M e - MODE_STANDALONE_EXECVE " ) ;
2015-05-15 05:44:48 +08:00
cmdlineUsage ( argv [ 0 ] , custom_opts ) ;
return false ;
break ;
}
break ;
2015-05-28 09:37:08 +08:00
case ' I ' :
nsjconf - > iface = optarg ;
break ;
2015-05-15 05:44:48 +08:00
default :
cmdlineUsage ( argv [ 0 ] , custom_opts ) ;
return false ;
break ;
}
}
2015-10-17 22:48:30 +08:00
if ( nsjconf - > mount_proc = = true ) {
2016-01-17 11:14:09 +08:00
struct mounts_t * p = util_malloc ( sizeof ( struct mounts_t ) ) ;
2015-10-17 22:48:30 +08:00
p - > src = " none " ;
p - > dst = " /proc " ;
p - > flags = 0 ;
p - > options = NULL ;
p - > fs_type = " proc " ;
2016-01-09 23:09:05 +08:00
TAILQ_INSERT_HEAD ( & nsjconf - > mountpts , p , pointers ) ;
2015-10-17 22:48:30 +08:00
}
2016-01-26 05:27:06 +08:00
{
2016-01-17 11:14:09 +08:00
struct mounts_t * p = util_malloc ( sizeof ( struct mounts_t ) ) ;
2015-10-17 22:48:30 +08:00
p - > src = nsjconf - > chroot ;
p - > dst = " / " ;
p - > flags = MS_BIND | MS_REC | MS_PRIVATE ;
p - > options = NULL ;
p - > fs_type = NULL ;
if ( nsjconf - > is_root_rw = = false ) {
p - > flags | = MS_RDONLY ;
}
2016-01-09 23:09:05 +08:00
TAILQ_INSERT_HEAD ( & nsjconf - > mountpts , p , pointers ) ;
2015-10-17 22:48:30 +08:00
}
2015-05-15 05:44:48 +08:00
if ( logInitLogFile ( nsjconf , logfile , nsjconf - > verbose ) = = false ) {
return false ;
}
2016-01-23 14:05:24 +08:00
if ( cmdlineParseUid ( nsjconf , user ) = = false ) {
2015-05-15 05:44:48 +08:00
return false ;
}
2016-01-23 14:05:24 +08:00
if ( cmdlineParseGid ( nsjconf , group ) = = false ) {
2015-05-15 05:44:48 +08:00
return false ;
}
2016-01-23 14:05:24 +08:00
nsjconf - > argv = & argv [ optind ] ;
if ( nsjconf - > argv [ 0 ] = = NULL ) {
LOG_E ( " No command provided " ) ;
cmdlineUsage ( argv [ 0 ] , custom_opts ) ;
2015-05-15 05:44:48 +08:00
return false ;
}
return true ;
}