Merge pull request #197 from pks-t/pks-forward-signals

Optionally forward fatal signals
This commit is contained in:
robertswiecki 2022-06-11 12:08:21 +02:00 committed by GitHub
commit d88be25986
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 19 additions and 5 deletions

View File

@ -534,6 +534,8 @@ Options:
Mode of the 'vs' interface. Can be either 'private', 'vepa', 'bridge' or 'passthru' (default: 'private') Mode of the 'vs' interface. Can be either 'private', 'vepa', 'bridge' or 'passthru' (default: 'private')
--disable_tsc --disable_tsc
Disable rdtsc and rdtscp instructions. WARNING: To make it effective, you also need to forbid `prctl(PR_SET_TSC, PR_TSC_ENABLE, ...)` in seccomp rules! (x86 and x86_64 only). Dynamic binaries produced by GCC seem to rely on RDTSC, but static ones should work. Disable rdtsc and rdtscp instructions. WARNING: To make it effective, you also need to forbid `prctl(PR_SET_TSC, PR_TSC_ENABLE, ...)` in seccomp rules! (x86 and x86_64 only). Dynamic binaries produced by GCC seem to rely on RDTSC, but static ones should work.
--forward_signals
Forward fatal signals to the child process instead of always using SIKGILL.
Examples: Examples:
Wait on a port 31337 for connections, and run /bin/sh Wait on a port 31337 for connections, and run /bin/sh

View File

@ -167,6 +167,7 @@ struct custom_option custom_opts[] = {
{ { "macvlan_vs_ma", required_argument, NULL, 0x705 }, "MAC-address of the 'vs' interface (e.g. \"ba:ad:ba:be:45:00\")" }, { { "macvlan_vs_ma", required_argument, NULL, 0x705 }, "MAC-address of the 'vs' interface (e.g. \"ba:ad:ba:be:45:00\")" },
{ { "macvlan_vs_mo", required_argument, NULL, 0x706 }, "Mode of the 'vs' interface. Can be either 'private', 'vepa', 'bridge' or 'passthru' (default: 'private')" }, { { "macvlan_vs_mo", required_argument, NULL, 0x706 }, "Mode of the 'vs' interface. Can be either 'private', 'vepa', 'bridge' or 'passthru' (default: 'private')" },
{ { "disable_tsc", no_argument, NULL, 0x707 }, "Disable rdtsc and rdtscp instructions. WARNING: To make it effective, you also need to forbid `prctl(PR_SET_TSC, PR_TSC_ENABLE, ...)` in seccomp rules! (x86 and x86_64 only). Dynamic binaries produced by GCC seem to rely on RDTSC, but static ones should work." }, { { "disable_tsc", no_argument, NULL, 0x707 }, "Disable rdtsc and rdtscp instructions. WARNING: To make it effective, you also need to forbid `prctl(PR_SET_TSC, PR_TSC_ENABLE, ...)` in seccomp rules! (x86 and x86_64 only). Dynamic binaries produced by GCC seem to rely on RDTSC, but static ones should work." },
{ { "forward_signals", no_argument, NULL, 0x708 }, "Forward fatal signals to the child process instead of always using SIKGILL." },
}; };
// clang-format on // clang-format on
@ -480,6 +481,7 @@ std::unique_ptr<nsjconf_t> parseArgs(int argc, char* argv[]) {
nsjconf->iface_vs_ma = ""; nsjconf->iface_vs_ma = "";
nsjconf->iface_vs_mo = "private"; nsjconf->iface_vs_mo = "private";
nsjconf->disable_tsc = false; nsjconf->disable_tsc = false;
nsjconf->forward_signals = false;
nsjconf->orig_uid = getuid(); nsjconf->orig_uid = getuid();
nsjconf->orig_euid = geteuid(); nsjconf->orig_euid = geteuid();
nsjconf->num_cpus = sysconf(_SC_NPROCESSORS_ONLN); nsjconf->num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
@ -861,6 +863,9 @@ std::unique_ptr<nsjconf_t> parseArgs(int argc, char* argv[]) {
case 0x707: case 0x707:
nsjconf->disable_tsc = true; nsjconf->disable_tsc = true;
break; break;
case 0x708:
nsjconf->forward_signals = true;
break;
case 0x801: case 0x801:
nsjconf->cgroup_mem_max = (size_t)strtoull(optarg, NULL, 0); nsjconf->cgroup_mem_max = (size_t)strtoull(optarg, NULL, 0);
break; break;

View File

@ -282,6 +282,8 @@ static bool configParseInternal(nsjconf_t* nsjconf, const nsjail::NsJailConfig&
nsjconf->disable_tsc = njc.disable_tsc(); nsjconf->disable_tsc = njc.disable_tsc();
nsjconf->forward_signals = njc.forward_signals();
if (njc.has_exec_bin()) { if (njc.has_exec_bin()) {
if (njc.exec_bin().has_path()) { if (njc.exec_bin().has_path()) {
nsjconf->exec_file = njc.exec_bin().path(); nsjconf->exec_file = njc.exec_bin().path();

View File

@ -268,4 +268,8 @@ message NsJailConfig {
optional Exe exec_bin = 90; optional Exe exec_bin = 90;
optional bool disable_tsc = 93 [default = false]; optional bool disable_tsc = 93 [default = false];
/* Set this to true to forward fatal signals to the child process instead
* of always using SIGKILL. */
optional bool forward_signals = 94 [default = false];
} }

View File

@ -222,7 +222,7 @@ static int listenMode(nsjconf_t* nsjconf) {
} }
for (;;) { for (;;) {
if (sigFatal > 0) { if (sigFatal > 0) {
subproc::killAndReapAll(nsjconf); subproc::killAndReapAll(nsjconf, nsjconf->forward_signals ? sigFatal : SIGKILL);
logs::logStop(sigFatal); logs::logStop(sigFatal);
close(listenfd); close(listenfd);
return EXIT_SUCCESS; return EXIT_SUCCESS;
@ -285,7 +285,7 @@ static int standaloneMode(nsjconf_t* nsjconf) {
subproc::displayProc(nsjconf); subproc::displayProc(nsjconf);
} }
if (sigFatal > 0) { if (sigFatal > 0) {
subproc::killAndReapAll(nsjconf); subproc::killAndReapAll(nsjconf, nsjconf->forward_signals ? sigFatal : SIGKILL);
logs::logStop(sigFatal); logs::logStop(sigFatal);
return (128 + sigFatal); return (128 + sigFatal);
} }

View File

@ -146,6 +146,7 @@ struct nsjconf_t {
std::string iface_vs_ma; std::string iface_vs_ma;
std::string iface_vs_mo; std::string iface_vs_mo;
bool disable_tsc; bool disable_tsc;
bool forward_signals;
std::string cgroup_mem_mount; std::string cgroup_mem_mount;
std::string cgroup_mem_parent; std::string cgroup_mem_parent;
size_t cgroup_mem_max; size_t cgroup_mem_max;

View File

@ -389,10 +389,10 @@ int reapProc(nsjconf_t* nsjconf) {
return rv; return rv;
} }
void killAndReapAll(nsjconf_t* nsjconf) { void killAndReapAll(nsjconf_t* nsjconf, int signal) {
while (!nsjconf->pids.empty()) { while (!nsjconf->pids.empty()) {
pid_t pid = nsjconf->pids.begin()->first; pid_t pid = nsjconf->pids.begin()->first;
if (kill(pid, SIGKILL) == 0) { if (kill(pid, signal) == 0) {
reapProc(nsjconf, pid, true); reapProc(nsjconf, pid, true);
} else { } else {
removeProc(nsjconf, pid); removeProc(nsjconf, pid);

View File

@ -37,7 +37,7 @@ namespace subproc {
pid_t runChild(nsjconf_t* nsjconf, int listen_fd, int fd_in, int fd_out, int fd_err); pid_t runChild(nsjconf_t* nsjconf, int listen_fd, int fd_in, int fd_out, int fd_err);
int countProc(nsjconf_t* nsjconf); int countProc(nsjconf_t* nsjconf);
void displayProc(nsjconf_t* nsjconf); void displayProc(nsjconf_t* nsjconf);
void killAndReapAll(nsjconf_t* nsjconf); void killAndReapAll(nsjconf_t* nsjconf, int signal);
/* Returns the exit code of the first failing subprocess, or 0 if none fail */ /* Returns the exit code of the first failing subprocess, or 0 if none fail */
int reapProc(nsjconf_t* nsjconf); int reapProc(nsjconf_t* nsjconf);
int systemExe(const std::vector<std::string>& args, char** env); int systemExe(const std::vector<std::string>& args, char** env);