cmdline: add option --execute_fd and support for it, in order to use execveat()
This commit is contained in:
parent
5ef11f65a4
commit
9c2f19b972
25
cmdline.c
25
cmdline.c
@ -36,6 +36,8 @@
|
||||
#include <strings.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/personality.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
@ -63,6 +65,7 @@ struct custom_option custom_opts[] = {
|
||||
"\tr: Launch a single process on the console with clone/execve, keep doing it forever [MODE_STANDALONE_RERUN]" },
|
||||
{ { "config", required_argument, NULL, 'C' }, "Configuration file in the config.proto ProtoBuf format (see configs/ directory for examples)" },
|
||||
{ { "exec_file", required_argument, NULL, 'x' }, "File to exec (default: argv[0])" },
|
||||
{ { "execute_fd", no_argument, NULL, 0x0607 }, "Use execveat() to execute a file-descriptor instead of executing the binary path. In such case argv[0]/exec_file denotes a file path before mount namespacing" },
|
||||
{ { "chroot", required_argument, NULL, 'c' }, "Directory containing / of the jail (default: none)" },
|
||||
{ { "rw", no_argument, NULL, 0x601 }, "Mount chroot dir (/) R/W (default: R/O)" },
|
||||
{ { "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:count convention here. Can be specified multiple times" },
|
||||
@ -312,10 +315,12 @@ bool cmdlineParse(int argc, char* argv[], struct nsjconf_t* nsjconf)
|
||||
{
|
||||
(*nsjconf) = (const struct nsjconf_t){
|
||||
.exec_file = NULL,
|
||||
.use_execveat = false,
|
||||
.exec_fd = -1,
|
||||
.argv = NULL,
|
||||
.hostname = "NSJAIL",
|
||||
.cwd = "/",
|
||||
.chroot = NULL,
|
||||
.argv = NULL,
|
||||
.port = 0,
|
||||
.bindhost = "::",
|
||||
.log_fd = STDERR_FILENO,
|
||||
@ -556,7 +561,7 @@ bool cmdlineParse(int argc, char* argv[], struct nsjconf_t* nsjconf)
|
||||
case 0x0508:
|
||||
nsjconf->max_cpus = strtoul(optarg, NULL, 0);
|
||||
break;
|
||||
case 0x509: {
|
||||
case 0x0509: {
|
||||
struct ints_t* f = utilMalloc(sizeof(struct ints_t));
|
||||
f->val = capsNameToVal(optarg);
|
||||
if (f->val == -1) {
|
||||
@ -581,6 +586,9 @@ bool cmdlineParse(int argc, char* argv[], struct nsjconf_t* nsjconf)
|
||||
case 0x0606:
|
||||
nsjconf->is_proc_rw = true;
|
||||
break;
|
||||
case 0x0607:
|
||||
nsjconf->use_execveat = true;
|
||||
break;
|
||||
case 'E': {
|
||||
struct charptr_t* p = utilMalloc(sizeof(struct charptr_t));
|
||||
p->val = optarg;
|
||||
@ -799,5 +807,18 @@ bool cmdlineParse(int argc, char* argv[], struct nsjconf_t* nsjconf)
|
||||
nsjconf->exec_file = nsjconf->argv[0];
|
||||
}
|
||||
|
||||
if (nsjconf->use_execveat) {
|
||||
#if !defined(__NR_execveat)
|
||||
LOG_E("Your nsjail is compiled without support for the execveat() syscall, yet you "
|
||||
"specified --execute_fd flag");
|
||||
return false;
|
||||
#endif /* !defined(__NR_execveat) */
|
||||
if ((nsjconf->exec_fd = open(nsjconf->exec_file, O_RDONLY | O_PATH | O_CLOEXEC))
|
||||
== -1) {
|
||||
PLOG_W("Couldn't open '%s' file", nsjconf->exec_file);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -296,6 +296,7 @@ static bool configParseInternal(struct nsjconf_t* nsjconf, const nsjail::NsJailC
|
||||
argv.push_back(nullptr);
|
||||
nsjconf->exec_file = DUP_IF_SET(njc.exec_bin(), path);
|
||||
nsjconf->argv = argv.data();
|
||||
nsjconf->use_execveat = njc.exec_bin().exec_fd();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -68,6 +68,8 @@ message Exe
|
||||
repeated string arg = 2;
|
||||
/* Override argv[0] */
|
||||
optional string arg0 = 3;
|
||||
/* Should execveat() be used to execute a file-descriptor instead? */
|
||||
optional bool exec_fd = 4 [ default = false ];
|
||||
}
|
||||
message NsJailConfig
|
||||
{
|
||||
|
48
configs/busybox-with-execveat.cfg
Normal file
48
configs/busybox-with-execveat.cfg
Normal file
@ -0,0 +1,48 @@
|
||||
name: "busybox-with-execveat"
|
||||
description: "An example/demo policy which allows to execute /bin/busybox in an empty (only /proc) "
|
||||
description: "mount namespace which doesn't even include busybox itself."
|
||||
|
||||
mode: ONCE
|
||||
hostname: "BUSYBOX"
|
||||
cwd: "/"
|
||||
|
||||
time_limit: 100
|
||||
|
||||
keep_env: false
|
||||
envar: "TERM=linux"
|
||||
envar: "PS1=$ "
|
||||
|
||||
skip_setsid: true
|
||||
|
||||
clone_newcgroup: true
|
||||
|
||||
uidmap {
|
||||
inside_id: "999999"
|
||||
outside_id: ""
|
||||
count: 1
|
||||
}
|
||||
|
||||
gidmap {
|
||||
inside_id: "999999"
|
||||
outside_id: ""
|
||||
count: 1
|
||||
}
|
||||
|
||||
mount_proc: false
|
||||
|
||||
mount {
|
||||
dst: "/proc"
|
||||
fstype: "proc"
|
||||
rw: false
|
||||
}
|
||||
|
||||
seccomp_string: "POLICY example { "
|
||||
seccomp_string: " ERRNO(0) { ptrace } "
|
||||
seccomp_string: "} "
|
||||
seccomp_string: "USE example DEFAULT ALLOW"
|
||||
|
||||
exec_bin {
|
||||
path: "/bin/busybox"
|
||||
arg: "sh"
|
||||
exec_fd: true
|
||||
}
|
6
nsjail.h
6
nsjail.h
@ -105,9 +105,12 @@ enum llevel_t {
|
||||
|
||||
struct nsjconf_t {
|
||||
const char* exec_file;
|
||||
bool use_execveat;
|
||||
int exec_fd;
|
||||
const char** argv;
|
||||
const char* hostname;
|
||||
const char* cwd;
|
||||
const char** argv;
|
||||
const char* chroot;
|
||||
int port;
|
||||
const char* bindhost;
|
||||
int log_fd;
|
||||
@ -135,7 +138,6 @@ struct nsjconf_t {
|
||||
bool clone_newuts;
|
||||
bool clone_newcgroup;
|
||||
enum ns_mode_t mode;
|
||||
const char* chroot;
|
||||
bool is_root_rw;
|
||||
bool is_silent;
|
||||
bool skip_setsid;
|
||||
|
13
subproc.c
13
subproc.c
@ -36,6 +36,7 @@
|
||||
#include <string.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <time.h>
|
||||
@ -170,7 +171,17 @@ static int subprocNewProc(struct nsjconf_t* nsjconf, int fd_in, int fd_out, int
|
||||
if (sandboxApply(nsjconf) == false) {
|
||||
exit(0xff);
|
||||
}
|
||||
execv(nsjconf->exec_file, (char* const*)&nsjconf->argv[0]);
|
||||
|
||||
if (nsjconf->use_execveat) {
|
||||
#if defined(__NR_execveat)
|
||||
syscall(__NR_execveat, (uintptr_t)nsjconf->exec_fd, "",
|
||||
(char* const*)&nsjconf->argv[0], environ, (uintptr_t)AT_EMPTY_PATH);
|
||||
#else /* defined(__NR_execveat) */
|
||||
LOG_F("Your system doesn't support execveat() syscall");
|
||||
#endif /* defined(__NR_execveat) */
|
||||
} else {
|
||||
execv(nsjconf->exec_file, (char* const*)&nsjconf->argv[0]);
|
||||
}
|
||||
|
||||
PLOG_E("execve('%s') failed", nsjconf->exec_file);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user