Added use_switchroot option
This commit is contained in:
parent
2e9fd0e2e4
commit
dab1713ac9
@ -76,6 +76,7 @@ struct custom_option custom_opts[] = {
|
|||||||
{ { "exec_file", required_argument, NULL, 'x' }, "File to exec (default: argv[0])" },
|
{ { "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" },
|
{ { "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)" },
|
{ { "chroot", required_argument, NULL, 'c' }, "Directory containing / of the jail (default: none)" },
|
||||||
|
{ { "use_switchroot", no_argument, NULL, 0x600 }, "When creating a mount namespace, use switch_root rather then the default pivot_root (usefull when using rootfs, on which the kernel disallows pivot_root)" },
|
||||||
{ { "rw", no_argument, NULL, 0x601 }, "Mount chroot dir (/) R/W (default: R/O)" },
|
{ { "rw", no_argument, NULL, 0x601 }, "Mount chroot dir (/) R/W (default: R/O)" },
|
||||||
{ { "user", required_argument, NULL, 'u' }, "Username/uid of processes 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" },
|
{ { "user", required_argument, NULL, 'u' }, "Username/uid of processes 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" },
|
||||||
{ { "group", required_argument, NULL, 'g' }, "Groupname/gid of processes inside the jail (default: your current gid). You can also use inside_ns_gid:global_ns_gid:count convention here. Can be specified multiple times" },
|
{ { "group", required_argument, NULL, 'g' }, "Groupname/gid of processes inside the jail (default: your current gid). You can also use inside_ns_gid:global_ns_gid:count convention here. Can be specified multiple times" },
|
||||||
@ -431,6 +432,7 @@ std::unique_ptr<nsjconf_t> parseArgs(int argc, char* argv[]) {
|
|||||||
nsjconf->clone_newnet = true;
|
nsjconf->clone_newnet = true;
|
||||||
nsjconf->clone_newuser = true;
|
nsjconf->clone_newuser = true;
|
||||||
nsjconf->clone_newns = true;
|
nsjconf->clone_newns = true;
|
||||||
|
nsjconf->use_switchroot = false;
|
||||||
nsjconf->clone_newpid = true;
|
nsjconf->clone_newpid = true;
|
||||||
nsjconf->clone_newipc = true;
|
nsjconf->clone_newipc = true;
|
||||||
nsjconf->clone_newuts = true;
|
nsjconf->clone_newuts = true;
|
||||||
@ -648,6 +650,9 @@ std::unique_ptr<nsjconf_t> parseArgs(int argc, char* argv[]) {
|
|||||||
}
|
}
|
||||||
nsjconf->caps.push_back(cap);
|
nsjconf->caps.push_back(cap);
|
||||||
} break;
|
} break;
|
||||||
|
case 0x0600:
|
||||||
|
nsjconf->use_switchroot = true;
|
||||||
|
break;
|
||||||
case 0x0601:
|
case 0x0601:
|
||||||
nsjconf->is_root_rw = true;
|
nsjconf->is_root_rw = true;
|
||||||
break;
|
break;
|
||||||
|
@ -184,6 +184,8 @@ static bool configParseInternal(nsjconf_t* nsjconf, const nsjail::NsJailConfig&
|
|||||||
nsjconf->clone_newuts = njc.clone_newuts();
|
nsjconf->clone_newuts = njc.clone_newuts();
|
||||||
nsjconf->clone_newcgroup = njc.clone_newcgroup();
|
nsjconf->clone_newcgroup = njc.clone_newcgroup();
|
||||||
nsjconf->clone_newtime = njc.clone_newtime();
|
nsjconf->clone_newtime = njc.clone_newtime();
|
||||||
|
|
||||||
|
nsjconf->use_switchroot = njc.use_switchroot();
|
||||||
|
|
||||||
for (ssize_t i = 0; i < njc.uidmap_size(); i++) {
|
for (ssize_t i = 0; i < njc.uidmap_size(); i++) {
|
||||||
if (!user::parseId(nsjconf, njc.uidmap(i).inside_id(), njc.uidmap(i).outside_id(),
|
if (!user::parseId(nsjconf, njc.uidmap(i).inside_id(), njc.uidmap(i).outside_id(),
|
||||||
|
@ -86,6 +86,9 @@ message NsJailConfig {
|
|||||||
/* Initial current working directory for the binary */
|
/* Initial current working directory for the binary */
|
||||||
optional string cwd = 9 [default = "/"];
|
optional string cwd = 9 [default = "/"];
|
||||||
|
|
||||||
|
/* Defines whether to use switch_root or pivot_root */
|
||||||
|
optional bool use_switchroot = 88 [default = false];
|
||||||
|
|
||||||
/* TCP port to listen to. Valid with mode=LISTEN only */
|
/* TCP port to listen to. Valid with mode=LISTEN only */
|
||||||
optional uint32 port = 10 [default = 0];
|
optional uint32 port = 10 [default = 0];
|
||||||
/* Host to bind to for mode=LISTEN. Must be in IPv6 format */
|
/* Host to bind to for mode=LISTEN. Must be in IPv6 format */
|
||||||
|
75
mnt.cc
75
mnt.cc
@ -398,30 +398,61 @@ static bool initCloneNs(nsjconf_t* nsjconf) {
|
|||||||
PLOG_E("umount2('%s', MNT_DETACH)", tmpdir->c_str());
|
PLOG_E("umount2('%s', MNT_DETACH)", tmpdir->c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
* This requires some explanation: It's actually possible to pivot_root('/', '/').
|
if (false == nsjconf->use_switchroot) {
|
||||||
* After this operation has been completed, the old root is mounted over the new
|
/*
|
||||||
* root, and it's OK to simply umount('/') now, and to have new_root as '/'. This
|
* This requires some explanation: It's actually possible to pivot_root('/', '/').
|
||||||
* allows us not care about providing any special directory for old_root, which is
|
* After this operation has been completed, the old root is mounted over the new
|
||||||
* sometimes not easy, given that e.g. /tmp might not always be present inside
|
* root, and it's OK to simply umount('/') now, and to have new_root as '/'. This
|
||||||
* new_root
|
* allows us not care about providing any special directory for old_root, which is
|
||||||
*/
|
* sometimes not easy, given that e.g. /tmp might not always be present inside
|
||||||
if (util::syscall(
|
* new_root
|
||||||
__NR_pivot_root, (uintptr_t)destdir->c_str(), (uintptr_t)destdir->c_str()) == -1) {
|
*/
|
||||||
PLOG_E("pivot_root('%s', '%s')", destdir->c_str(), destdir->c_str());
|
if (util::syscall(
|
||||||
return false;
|
__NR_pivot_root, (uintptr_t)destdir->c_str(), (uintptr_t)destdir->c_str()) == -1) {
|
||||||
}
|
PLOG_E("pivot_root('%s', '%s')", destdir->c_str(), destdir->c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (umount2("/", MNT_DETACH) == -1) {
|
if (umount2("/", MNT_DETACH) == -1) {
|
||||||
PLOG_E("umount2('/', MNT_DETACH)");
|
PLOG_E("umount2('/', MNT_DETACH)");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* pivot_root would normally un-mount the old root, however in certain cases this
|
||||||
|
* operation is forbidden. There are systems (mainly embedded) that keep their root
|
||||||
|
* file system in RAM, when initially loaded by the kernel (e.g. initramfs),
|
||||||
|
* and there is no other file system that is mounted on top of it.In such systems,
|
||||||
|
* there is option to pivot_root!
|
||||||
|
* For more information, see kernel.org/doc/Documentation/filesystems/ramfs-rootfs-initramfs.txt.
|
||||||
|
* switch_root alternative:
|
||||||
|
* Innstead of un-mounting the old rootfs, it is over mounted by moving the new root to it.
|
||||||
|
* This way, we prevent the process from hacking its way back into the old root.
|
||||||
|
*/
|
||||||
|
if (chdir(destdir->c_str()) == -1) {
|
||||||
|
PLOG_E("chdir('%s')", destdir->c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
for (const auto& p : nsjconf->mountpts) {
|
/* mount moving the new root on top of '/'. This operation is atomic and doesn't involve
|
||||||
if (!remountPt(p) && p.is_mandatory) {
|
un-mounting '/' at any stage */
|
||||||
return false;
|
if (mount(".", "/", NULL, MS_MOVE, NULL) == -1) {
|
||||||
}
|
PLOG_E("mount('/', %s, NULL, MS_MOVE, NULL)", destdir->c_str());
|
||||||
}
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chroot(".") == -1) {
|
||||||
|
PLOG_E("chroot('%s')", destdir->c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& p : nsjconf->mountpts) {
|
||||||
|
if (!remountPt(p) && p.is_mandatory) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
1
nsjail.h
1
nsjail.h
@ -120,6 +120,7 @@ struct nsjconf_t {
|
|||||||
bool clone_newnet;
|
bool clone_newnet;
|
||||||
bool clone_newuser;
|
bool clone_newuser;
|
||||||
bool clone_newns;
|
bool clone_newns;
|
||||||
|
bool use_switchroot;
|
||||||
bool clone_newpid;
|
bool clone_newpid;
|
||||||
bool clone_newipc;
|
bool clone_newipc;
|
||||||
bool clone_newuts;
|
bool clone_newuts;
|
||||||
|
Loading…
Reference in New Issue
Block a user