2015-05-15 05:44:48 +08:00
|
|
|
/*
|
|
|
|
|
|
|
|
nsjail
|
|
|
|
-----------------------------------------
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
*/
|
2016-03-02 00:03:11 +08:00
|
|
|
|
2015-05-15 05:44:48 +08:00
|
|
|
#include "nsjail.h"
|
|
|
|
|
2020-02-13 19:24:28 +08:00
|
|
|
#include <fcntl.h>
|
|
|
|
#include <poll.h>
|
2015-05-15 05:44:48 +08:00
|
|
|
#include <signal.h>
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <stdio.h>
|
2017-09-14 04:03:21 +08:00
|
|
|
#include <stdlib.h>
|
2015-05-15 05:44:48 +08:00
|
|
|
#include <string.h>
|
2018-05-25 07:04:29 +08:00
|
|
|
#include <sys/ioctl.h>
|
2015-05-15 05:44:48 +08:00
|
|
|
#include <sys/time.h>
|
2018-05-25 07:04:29 +08:00
|
|
|
#include <termios.h>
|
2015-05-15 05:44:48 +08:00
|
|
|
#include <unistd.h>
|
|
|
|
|
2020-02-13 19:24:28 +08:00
|
|
|
#include <algorithm>
|
2022-08-26 20:40:46 +08:00
|
|
|
#include <atomic>
|
2020-02-13 19:24:28 +08:00
|
|
|
#include <cerrno>
|
2018-05-28 08:04:03 +08:00
|
|
|
#include <memory>
|
2020-02-13 19:24:28 +08:00
|
|
|
#include <vector>
|
2018-05-28 08:04:03 +08:00
|
|
|
|
2022-11-23 05:15:01 +08:00
|
|
|
#include "cgroup2.h"
|
2015-05-15 05:44:48 +08:00
|
|
|
#include "cmdline.h"
|
2018-02-11 00:49:15 +08:00
|
|
|
#include "logs.h"
|
2018-02-10 12:25:55 +08:00
|
|
|
#include "macros.h"
|
2015-05-15 05:44:48 +08:00
|
|
|
#include "net.h"
|
2018-02-12 10:11:58 +08:00
|
|
|
#include "sandbox.h"
|
2015-05-15 05:44:48 +08:00
|
|
|
#include "subproc.h"
|
2017-06-20 06:16:38 +08:00
|
|
|
#include "util.h"
|
2015-05-15 05:44:48 +08:00
|
|
|
|
2018-05-25 08:15:47 +08:00
|
|
|
namespace nsjail {
|
2015-05-15 05:44:48 +08:00
|
|
|
|
2022-08-26 20:40:46 +08:00
|
|
|
static __thread std::atomic<int> sigFatal(0);
|
|
|
|
static __thread std::atomic<bool> showProc(false);
|
2018-05-25 08:15:47 +08:00
|
|
|
|
|
|
|
static void sigHandler(int sig) {
|
2020-02-13 19:24:28 +08:00
|
|
|
if (sig == SIGALRM || sig == SIGCHLD || sig == SIGPIPE) {
|
2015-05-15 05:44:48 +08:00
|
|
|
return;
|
|
|
|
}
|
2017-10-19 21:25:20 +08:00
|
|
|
if (sig == SIGUSR1 || sig == SIGQUIT) {
|
2018-05-25 08:15:47 +08:00
|
|
|
showProc = true;
|
2015-05-15 05:44:48 +08:00
|
|
|
return;
|
|
|
|
}
|
2018-05-25 08:15:47 +08:00
|
|
|
sigFatal = sig;
|
2015-05-15 05:44:48 +08:00
|
|
|
}
|
|
|
|
|
2018-05-25 08:15:47 +08:00
|
|
|
static bool setSigHandler(int sig) {
|
2018-02-11 04:19:47 +08:00
|
|
|
LOG_D("Setting sighandler for signal %s (%d)", util::sigName(sig).c_str(), sig);
|
2015-05-15 05:44:48 +08:00
|
|
|
|
|
|
|
sigset_t smask;
|
|
|
|
sigemptyset(&smask);
|
2018-02-08 22:24:17 +08:00
|
|
|
|
|
|
|
struct sigaction sa;
|
2018-05-25 08:15:47 +08:00
|
|
|
sa.sa_handler = sigHandler;
|
2018-02-08 22:24:17 +08:00
|
|
|
sa.sa_mask = smask;
|
|
|
|
sa.sa_flags = 0;
|
|
|
|
sa.sa_restorer = NULL;
|
2018-02-15 08:33:33 +08:00
|
|
|
|
|
|
|
if (sig == SIGTTIN || sig == SIGTTOU) {
|
|
|
|
sa.sa_handler = SIG_IGN;
|
2020-02-13 19:24:28 +08:00
|
|
|
}
|
2015-05-15 05:44:48 +08:00
|
|
|
if (sigaction(sig, &sa, NULL) == -1) {
|
|
|
|
PLOG_E("sigaction(%d)", sig);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-05-25 08:15:47 +08:00
|
|
|
static bool setSigHandlers(void) {
|
2018-05-22 20:27:18 +08:00
|
|
|
for (const auto& i : nssigs) {
|
2018-05-25 08:15:47 +08:00
|
|
|
if (!setSigHandler(i)) {
|
2017-10-18 18:33:24 +08:00
|
|
|
return false;
|
|
|
|
}
|
2015-05-15 05:44:48 +08:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-05-25 08:15:47 +08:00
|
|
|
static bool setTimer(nsjconf_t* nsjconf) {
|
2015-08-15 22:02:38 +08:00
|
|
|
if (nsjconf->mode == MODE_STANDALONE_EXECVE) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-05-15 05:44:48 +08:00
|
|
|
struct itimerval it = {
|
2018-02-08 22:24:17 +08:00
|
|
|
.it_interval =
|
2017-10-26 06:26:02 +08:00
|
|
|
{
|
2017-10-16 21:31:14 +08:00
|
|
|
.tv_sec = 1,
|
|
|
|
.tv_usec = 0,
|
|
|
|
},
|
2018-02-08 22:24:17 +08:00
|
|
|
.it_value =
|
2017-10-26 06:26:02 +08:00
|
|
|
{
|
2017-10-16 21:31:14 +08:00
|
|
|
.tv_sec = 1,
|
|
|
|
.tv_usec = 0,
|
|
|
|
},
|
2015-05-15 05:44:48 +08:00
|
|
|
};
|
|
|
|
if (setitimer(ITIMER_REAL, &it, NULL) == -1) {
|
|
|
|
PLOG_E("setitimer(ITIMER_REAL)");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-02-13 19:24:28 +08:00
|
|
|
static bool pipeTraffic(nsjconf_t* nsjconf, int listenfd) {
|
|
|
|
std::vector<struct pollfd> fds;
|
2020-02-17 22:55:08 +08:00
|
|
|
fds.reserve(nsjconf->pipes.size() * 3 + 1);
|
2020-02-13 19:24:28 +08:00
|
|
|
for (const auto& p : nsjconf->pipes) {
|
|
|
|
fds.push_back({
|
2020-02-17 22:55:08 +08:00
|
|
|
.fd = p.sock_fd,
|
|
|
|
.events = POLLIN | POLLOUT,
|
2020-02-13 19:24:28 +08:00
|
|
|
.revents = 0,
|
|
|
|
});
|
|
|
|
fds.push_back({
|
2020-02-17 22:55:08 +08:00
|
|
|
.fd = p.pipe_in,
|
2020-02-13 19:24:28 +08:00
|
|
|
.events = POLLOUT,
|
|
|
|
.revents = 0,
|
|
|
|
});
|
2020-02-17 22:55:08 +08:00
|
|
|
fds.push_back({
|
|
|
|
.fd = p.pipe_out,
|
|
|
|
.events = POLLIN,
|
|
|
|
.revents = 0,
|
|
|
|
});
|
2020-02-13 19:24:28 +08:00
|
|
|
}
|
|
|
|
fds.push_back({
|
|
|
|
.fd = listenfd,
|
|
|
|
.events = POLLIN,
|
|
|
|
.revents = 0,
|
|
|
|
});
|
|
|
|
LOG_D("Waiting for fd activity");
|
|
|
|
while (poll(fds.data(), fds.size(), -1) > 0) {
|
2020-02-17 21:16:40 +08:00
|
|
|
if (sigFatal > 0 || showProc) {
|
|
|
|
return false;
|
|
|
|
}
|
2020-02-13 19:24:28 +08:00
|
|
|
if (fds.back().revents != 0) {
|
|
|
|
LOG_D("New connection ready");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool cleanup = false;
|
2020-02-17 22:55:08 +08:00
|
|
|
for (size_t i = 0; i < fds.size() - 1; ++i) {
|
|
|
|
if (fds[i].revents & POLLIN) {
|
|
|
|
fds[i].events &= ~POLLIN;
|
|
|
|
}
|
|
|
|
if (fds[i].revents & POLLOUT) {
|
|
|
|
fds[i].events &= ~POLLOUT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (size_t i = 0; i < fds.size() - 3; i += 3) {
|
|
|
|
const size_t pipe_no = i / 3;
|
|
|
|
int in, out;
|
|
|
|
const char* direction;
|
|
|
|
bool closed = false;
|
|
|
|
std::tuple<int, int, const char*> direction_map[] = {
|
2020-08-26 22:09:55 +08:00
|
|
|
std::make_tuple(i, i + 1, "in"),
|
|
|
|
std::make_tuple(i + 2, i, "out"),
|
2020-07-29 21:18:10 +08:00
|
|
|
};
|
2020-02-17 22:55:08 +08:00
|
|
|
for (const auto& entry : direction_map) {
|
|
|
|
std::tie(in, out, direction) = entry;
|
|
|
|
bool in_ready = (fds[in].events & POLLIN) == 0 ||
|
|
|
|
(fds[in].revents & POLLIN) == POLLIN;
|
|
|
|
bool out_ready = (fds[out].events & POLLOUT) == 0 ||
|
|
|
|
(fds[out].revents & POLLOUT) == POLLOUT;
|
|
|
|
if (in_ready && out_ready) {
|
2020-03-27 17:19:40 +08:00
|
|
|
LOG_D("#%zu piping data %s", pipe_no, direction);
|
2020-02-17 22:55:08 +08:00
|
|
|
ssize_t rv = splice(fds[in].fd, nullptr, fds[out].fd,
|
|
|
|
nullptr, 4096, SPLICE_F_NONBLOCK);
|
|
|
|
if (rv == -1 && errno != EAGAIN) {
|
2020-03-27 17:19:40 +08:00
|
|
|
PLOG_E("splice fd pair #%zu {%d, %d}\n", pipe_no,
|
2020-02-17 22:55:08 +08:00
|
|
|
fds[in].fd, fds[out].fd);
|
|
|
|
}
|
|
|
|
if (rv == 0) {
|
|
|
|
closed = true;
|
|
|
|
}
|
|
|
|
fds[in].events |= POLLIN;
|
|
|
|
fds[out].events |= POLLOUT;
|
2020-02-13 19:24:28 +08:00
|
|
|
}
|
2020-02-17 22:55:08 +08:00
|
|
|
if ((fds[in].revents & (POLLERR | POLLHUP)) != 0 ||
|
|
|
|
(fds[out].revents & (POLLERR | POLLHUP)) != 0) {
|
|
|
|
closed = true;
|
2020-02-17 21:16:40 +08:00
|
|
|
}
|
2020-02-13 19:24:28 +08:00
|
|
|
}
|
2020-02-17 22:55:08 +08:00
|
|
|
if (closed) {
|
2020-03-27 17:19:40 +08:00
|
|
|
LOG_D("#%zu connection closed", pipe_no);
|
2020-02-13 19:24:28 +08:00
|
|
|
cleanup = true;
|
2020-02-17 22:55:08 +08:00
|
|
|
close(nsjconf->pipes[pipe_no].sock_fd);
|
|
|
|
close(nsjconf->pipes[pipe_no].pipe_in);
|
|
|
|
close(nsjconf->pipes[pipe_no].pipe_out);
|
2020-08-31 04:02:08 +08:00
|
|
|
if (nsjconf->pipes[pipe_no].pid > 0) {
|
|
|
|
kill(nsjconf->pipes[pipe_no].pid, SIGKILL);
|
|
|
|
}
|
2020-02-17 22:55:08 +08:00
|
|
|
nsjconf->pipes[pipe_no] = {};
|
2020-02-13 19:24:28 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (cleanup) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2020-02-17 22:55:08 +08:00
|
|
|
nsjconf->pipes.erase(std::remove(nsjconf->pipes.begin(), nsjconf->pipes.end(), pipemap_t{}),
|
2020-02-13 19:24:28 +08:00
|
|
|
nsjconf->pipes.end());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-05-26 07:24:58 +08:00
|
|
|
static int listenMode(nsjconf_t* nsjconf) {
|
2018-02-11 06:46:15 +08:00
|
|
|
int listenfd = net::getRecvSocket(nsjconf->bindhost.c_str(), nsjconf->port);
|
2015-05-15 05:44:48 +08:00
|
|
|
if (listenfd == -1) {
|
2018-05-28 07:40:02 +08:00
|
|
|
return EXIT_FAILURE;
|
2015-05-15 05:44:48 +08:00
|
|
|
}
|
|
|
|
for (;;) {
|
2018-05-25 08:15:47 +08:00
|
|
|
if (sigFatal > 0) {
|
2022-06-11 18:08:50 +08:00
|
|
|
subproc::killAndReapAll(
|
2022-08-26 20:40:46 +08:00
|
|
|
nsjconf, nsjconf->forward_signals ? sigFatal.load() : SIGKILL);
|
2018-05-25 08:15:47 +08:00
|
|
|
logs::logStop(sigFatal);
|
2016-07-29 21:38:22 +08:00
|
|
|
close(listenfd);
|
2018-05-28 07:40:02 +08:00
|
|
|
return EXIT_SUCCESS;
|
2015-05-15 05:44:48 +08:00
|
|
|
}
|
2018-05-25 08:15:47 +08:00
|
|
|
if (showProc) {
|
|
|
|
showProc = false;
|
2018-02-10 00:03:02 +08:00
|
|
|
subproc::displayProc(nsjconf);
|
2015-05-15 05:44:48 +08:00
|
|
|
}
|
2020-02-13 19:24:28 +08:00
|
|
|
if (pipeTraffic(nsjconf, listenfd)) {
|
|
|
|
int connfd = net::acceptConn(listenfd);
|
|
|
|
if (connfd >= 0) {
|
|
|
|
int in[2];
|
|
|
|
int out[2];
|
|
|
|
if (pipe(in) != 0 || pipe(out) != 0) {
|
|
|
|
PLOG_E("pipe");
|
|
|
|
continue;
|
|
|
|
}
|
2020-08-31 05:22:22 +08:00
|
|
|
|
2020-08-31 04:02:08 +08:00
|
|
|
pid_t pid =
|
|
|
|
subproc::runChild(nsjconf, connfd, in[0], out[1], out[1]);
|
2020-08-31 05:22:22 +08:00
|
|
|
|
2020-02-13 19:24:28 +08:00
|
|
|
close(in[0]);
|
|
|
|
close(out[1]);
|
2020-08-31 05:22:22 +08:00
|
|
|
|
|
|
|
if (pid <= 0) {
|
|
|
|
close(in[1]);
|
|
|
|
close(out[0]);
|
|
|
|
close(connfd);
|
|
|
|
} else {
|
|
|
|
nsjconf->pipes.push_back({
|
|
|
|
.sock_fd = connfd,
|
|
|
|
.pipe_in = in[1],
|
|
|
|
.pipe_out = out[0],
|
|
|
|
.pid = pid,
|
|
|
|
});
|
|
|
|
}
|
2020-02-13 19:24:28 +08:00
|
|
|
}
|
2015-05-15 05:44:48 +08:00
|
|
|
}
|
2018-02-10 00:03:02 +08:00
|
|
|
subproc::reapProc(nsjconf);
|
2015-05-15 05:44:48 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-25 08:15:47 +08:00
|
|
|
static int standaloneMode(nsjconf_t* nsjconf) {
|
2015-05-15 05:44:48 +08:00
|
|
|
for (;;) {
|
2020-08-31 04:02:08 +08:00
|
|
|
if (subproc::runChild(nsjconf, /* netfd= */ -1, STDIN_FILENO, STDOUT_FILENO,
|
|
|
|
STDERR_FILENO) == -1) {
|
2018-07-24 06:23:44 +08:00
|
|
|
LOG_E("Couldn't launch the child process");
|
|
|
|
return 0xff;
|
|
|
|
}
|
|
|
|
for (;;) {
|
|
|
|
int child_status = subproc::reapProc(nsjconf);
|
|
|
|
if (subproc::countProc(nsjconf) == 0) {
|
|
|
|
if (nsjconf->mode == MODE_STANDALONE_ONCE) {
|
|
|
|
return child_status;
|
|
|
|
}
|
|
|
|
break;
|
2015-05-15 05:44:48 +08:00
|
|
|
}
|
2018-07-24 06:23:44 +08:00
|
|
|
if (showProc) {
|
|
|
|
showProc = false;
|
|
|
|
subproc::displayProc(nsjconf);
|
2018-07-23 23:13:17 +08:00
|
|
|
}
|
2018-07-24 06:23:44 +08:00
|
|
|
if (sigFatal > 0) {
|
2022-06-11 18:08:50 +08:00
|
|
|
subproc::killAndReapAll(
|
2022-08-26 20:40:46 +08:00
|
|
|
nsjconf, nsjconf->forward_signals ? sigFatal.load() : SIGKILL);
|
2018-07-24 06:23:44 +08:00
|
|
|
logs::logStop(sigFatal);
|
|
|
|
return (128 + sigFatal);
|
|
|
|
}
|
|
|
|
pause();
|
2015-05-15 05:44:48 +08:00
|
|
|
}
|
|
|
|
}
|
2015-07-08 00:33:10 +08:00
|
|
|
// not reached
|
2015-05-15 05:44:48 +08:00
|
|
|
}
|
|
|
|
|
2018-05-25 08:15:47 +08:00
|
|
|
std::unique_ptr<struct termios> getTC(int fd) {
|
2018-05-25 07:04:29 +08:00
|
|
|
std::unique_ptr<struct termios> trm(new struct termios);
|
|
|
|
|
|
|
|
if (ioctl(fd, TCGETS, trm.get()) == -1) {
|
|
|
|
PLOG_D("ioctl(fd=%d, TCGETS) failed", fd);
|
|
|
|
return nullptr;
|
|
|
|
}
|
2018-05-25 08:15:47 +08:00
|
|
|
LOG_D("Saved the current state of the TTY");
|
2018-05-25 07:04:29 +08:00
|
|
|
return trm;
|
|
|
|
}
|
|
|
|
|
2018-05-25 08:15:47 +08:00
|
|
|
void setTC(int fd, const struct termios* trm) {
|
2018-05-25 07:04:29 +08:00
|
|
|
if (!trm) {
|
|
|
|
return;
|
|
|
|
}
|
2018-05-25 08:05:12 +08:00
|
|
|
if (ioctl(fd, TCSETS, trm) == -1) {
|
2018-05-25 07:04:29 +08:00
|
|
|
PLOG_W("ioctl(fd=%d, TCSETS) failed", fd);
|
2018-05-25 08:15:47 +08:00
|
|
|
return;
|
2018-05-25 07:04:29 +08:00
|
|
|
}
|
2019-03-10 22:00:45 +08:00
|
|
|
if (tcflush(fd, TCIFLUSH) == -1) {
|
|
|
|
PLOG_W("tcflush(fd=%d, TCIFLUSH) failed", fd);
|
|
|
|
return;
|
|
|
|
}
|
2018-05-25 07:04:29 +08:00
|
|
|
}
|
|
|
|
|
2018-05-25 08:15:47 +08:00
|
|
|
} // namespace nsjail
|
|
|
|
|
2017-10-26 06:26:02 +08:00
|
|
|
int main(int argc, char* argv[]) {
|
2018-02-10 22:50:12 +08:00
|
|
|
std::unique_ptr<nsjconf_t> nsjconf = cmdline::parseArgs(argc, argv);
|
2018-05-25 08:15:47 +08:00
|
|
|
std::unique_ptr<struct termios> trm = nsjail::getTC(STDIN_FILENO);
|
2018-05-25 08:05:12 +08:00
|
|
|
|
2018-02-09 22:44:29 +08:00
|
|
|
if (!nsjconf) {
|
2017-09-25 18:00:57 +08:00
|
|
|
LOG_F("Couldn't parse cmdline options");
|
2015-05-15 05:44:48 +08:00
|
|
|
}
|
2020-04-21 17:25:06 +08:00
|
|
|
if (nsjconf->daemonize && (daemon(/* nochdir= */ 1, /* noclose= */ 0) == -1)) {
|
2015-05-15 05:44:48 +08:00
|
|
|
PLOG_F("daemon");
|
|
|
|
}
|
2018-02-09 22:44:29 +08:00
|
|
|
cmdline::logParams(nsjconf.get());
|
2018-05-25 08:15:47 +08:00
|
|
|
if (!nsjail::setSigHandlers()) {
|
|
|
|
LOG_F("nsjail::setSigHandlers() failed");
|
2015-05-15 05:44:48 +08:00
|
|
|
}
|
2018-05-25 08:15:47 +08:00
|
|
|
if (!nsjail::setTimer(nsjconf.get())) {
|
|
|
|
LOG_F("nsjail::setTimer() failed");
|
2015-05-15 05:44:48 +08:00
|
|
|
}
|
2022-11-10 12:43:44 +08:00
|
|
|
|
|
|
|
if (nsjconf->detect_cgroupv2) {
|
|
|
|
cgroup2::detectCgroupv2(nsjconf.get());
|
|
|
|
LOG_I("Detected cgroups version: %d", nsjconf->use_cgroupv2 ? 2 : 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nsjconf->use_cgroupv2) {
|
|
|
|
if (!cgroup2::setup(nsjconf.get())) {
|
|
|
|
LOG_E("Couldn't setup parent cgroup (cgroupv2)");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-12 10:11:58 +08:00
|
|
|
if (!sandbox::preparePolicy(nsjconf.get())) {
|
|
|
|
LOG_F("Couldn't prepare sandboxing policy");
|
|
|
|
}
|
2015-05-15 05:44:48 +08:00
|
|
|
|
2018-02-13 00:31:45 +08:00
|
|
|
int ret = 0;
|
2018-02-09 22:44:29 +08:00
|
|
|
if (nsjconf->mode == MODE_LISTEN_TCP) {
|
2018-05-26 07:24:58 +08:00
|
|
|
ret = nsjail::listenMode(nsjconf.get());
|
2015-05-15 05:44:48 +08:00
|
|
|
} else {
|
2018-05-25 08:15:47 +08:00
|
|
|
ret = nsjail::standaloneMode(nsjconf.get());
|
2015-05-15 05:44:48 +08:00
|
|
|
}
|
2018-02-17 10:14:54 +08:00
|
|
|
|
2018-02-13 00:31:45 +08:00
|
|
|
sandbox::closePolicy(nsjconf.get());
|
2018-05-25 08:05:12 +08:00
|
|
|
/* Try to restore the underlying console's params in case some program has changed it */
|
2019-10-04 06:33:29 +08:00
|
|
|
if (!nsjconf->daemonize) {
|
|
|
|
nsjail::setTC(STDIN_FILENO, trm.get());
|
|
|
|
}
|
2018-05-25 07:04:29 +08:00
|
|
|
|
2018-05-28 08:04:03 +08:00
|
|
|
LOG_D("Returning with %d", ret);
|
2018-02-13 00:09:45 +08:00
|
|
|
return ret;
|
2015-05-15 05:44:48 +08:00
|
|
|
}
|