BIN = nsjail
LIBS = kafel/libkafel.a
-SRCS_C = nsjail.c caps.c cmdline.c contain.c log.c cgroup.c mount.c net.c pid.c sandbox.c subproc.c user.c util.c uts.c cpu.c
-SRCS_CXX = config.cc
+SRCS_C = caps.c cmdline.c contain.c log.c cgroup.c mount.c net.c pid.c sandbox.c subproc.c user.c util.c uts.c cpu.c
+SRCS_CXX = nsjail.cc config.cc
SRCS_PROTO = config.proto
SRCS_PB_CXX = $(SRCS_PROTO:.proto=.pb.cc)
SRCS_PB_H = $(SRCS_PROTO:.proto=.pb.h)
.PHONY: all clean depend indent
.c.o: %.c
- $(CC) $(CFLAGS) $< -o $@
+ $(CXX) -xc $(CFLAGS) $< -o $@
.cc.o: %.cc
$(CXX) $(CXXFLAGS) $< -o $@
#include "nsjail.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
uint64_t cmdlineParseRLimit(int res, const char* optarg, unsigned long mul);
void cmdlineLogParams(struct nsjconf_t* nsjconf);
bool cmdlineParse(int argc, char* argv[], struct nsjconf_t* nsjconf);
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
#endif /* _CMDLINE_H */
#define PLOG_E(...) logLog(ERROR, __func__, __LINE__, true, __VA_ARGS__);
#define PLOG_F(...) logLog(FATAL, __func__, __LINE__, true, __VA_ARGS__);
+#ifdef __cplusplus
+extern "C" {
+#endif
+
bool logInitLogFile(struct nsjconf_t* nsjconf);
void logLog(enum llevel_t ll, const char* fn, int ln, bool perr, const char* fmt, ...)
__attribute__((format(printf, 5, 6)));
void logStop(int sig);
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
#endif /* NS_LOG_H */
#include "nsjail.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
bool netLimitConns(struct nsjconf_t* nsjconf, int connsock);
int netGetRecvSocket(const char* bindhost, int port);
int netAcceptConn(int listenfd);
bool netInitNsFromParent(struct nsjconf_t* nsjconf, int pid);
bool netInitNsFromChild(struct nsjconf_t* nsjconf);
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
#endif /* _NET_H */
+++ /dev/null
-/*
-
- 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.
-
-*/
-
-#include "nsjail.h"
-
-#include <signal.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/time.h>
-#include <unistd.h>
-
-#include "cmdline.h"
-#include "common.h"
-#include "log.h"
-#include "net.h"
-#include "subproc.h"
-#include "util.h"
-
-static __thread int nsjailSigFatal = 0;
-static __thread bool nsjailShowProc = false;
-
-static void nsjailSig(int sig) {
- if (sig == SIGALRM) {
- return;
- }
- if (sig == SIGCHLD) {
- return;
- }
- if (sig == SIGUSR1 || sig == SIGQUIT) {
- nsjailShowProc = true;
- return;
- }
- nsjailSigFatal = sig;
-}
-
-static bool nsjailSetSigHandler(int sig) {
- LOG_D("Setting sighandler for signal %s (%d)", utilSigName(sig), sig);
-
- sigset_t smask;
- sigemptyset(&smask);
- struct sigaction sa = {
- .sa_handler = nsjailSig,
- .sa_mask = smask,
- .sa_flags = 0,
- .sa_restorer = NULL,
- };
- if (sigaction(sig, &sa, NULL) == -1) {
- PLOG_E("sigaction(%d)", sig);
- return false;
- }
- return true;
-}
-
-static bool nsjailSetSigHandlers(void) {
- for (size_t i = 0; i < ARRAYSIZE(nssigs); i++) {
- if (!nsjailSetSigHandler(nssigs[i])) {
- return false;
- }
- }
- return true;
-}
-
-static bool nsjailSetTimer(struct nsjconf_t* nsjconf) {
- if (nsjconf->mode == MODE_STANDALONE_EXECVE) {
- return true;
- }
-
- struct itimerval it = {
- .it_value =
- {
- .tv_sec = 1,
- .tv_usec = 0,
- },
- .it_interval =
- {
- .tv_sec = 1,
- .tv_usec = 0,
- },
- };
- if (setitimer(ITIMER_REAL, &it, NULL) == -1) {
- PLOG_E("setitimer(ITIMER_REAL)");
- return false;
- }
- return true;
-}
-
-static void nsjailListenMode(struct nsjconf_t* nsjconf) {
- int listenfd = netGetRecvSocket(nsjconf->bindhost, nsjconf->port);
- if (listenfd == -1) {
- return;
- }
- for (;;) {
- if (nsjailSigFatal > 0) {
- subprocKillAll(nsjconf);
- logStop(nsjailSigFatal);
- close(listenfd);
- return;
- }
- if (nsjailShowProc) {
- nsjailShowProc = false;
- subprocDisplay(nsjconf);
- }
- int connfd = netAcceptConn(listenfd);
- if (connfd >= 0) {
- subprocRunChild(nsjconf, connfd, connfd, connfd);
- close(connfd);
- }
- subprocReap(nsjconf);
- }
-}
-
-static int nsjailStandaloneMode(struct nsjconf_t* nsjconf) {
- subprocRunChild(nsjconf, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO);
- for (;;) {
- int child_status = subprocReap(nsjconf);
-
- if (subprocCount(nsjconf) == 0) {
- if (nsjconf->mode == MODE_STANDALONE_ONCE) {
- return child_status;
- }
- subprocRunChild(nsjconf, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO);
- continue;
- }
- if (nsjailShowProc) {
- nsjailShowProc = false;
- subprocDisplay(nsjconf);
- }
- if (nsjailSigFatal > 0) {
- subprocKillAll(nsjconf);
- logStop(nsjailSigFatal);
- return -1;
- }
-
- pause();
- }
- // not reached
-}
-
-int main(int argc, char* argv[]) {
- struct nsjconf_t nsjconf;
- if (!cmdlineParse(argc, argv, &nsjconf)) {
- LOG_F("Couldn't parse cmdline options");
- }
- if (nsjconf.clone_newuser == false && geteuid() != 0) {
- LOG_W("--disable_clone_newuser might require root() privs");
- }
- if (nsjconf.daemonize && (daemon(0, 0) == -1)) {
- PLOG_F("daemon");
- }
- cmdlineLogParams(&nsjconf);
- if (nsjailSetSigHandlers() == false) {
- LOG_F("nsjailSetSigHandlers() failed");
- }
- if (nsjailSetTimer(&nsjconf) == false) {
- LOG_F("nsjailSetTimer() failed");
- }
-
- if (nsjconf.mode == MODE_LISTEN_TCP) {
- nsjailListenMode(&nsjconf);
- } else {
- return nsjailStandaloneMode(&nsjconf);
- }
- return 0;
-}
--- /dev/null
+/*
+
+ 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.
+
+*/
+
+#include "nsjail.h"
+
+#include <signal.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+#include "cmdline.h"
+#include "common.h"
+#include "log.h"
+#include "net.h"
+#include "subproc.h"
+#include "util.h"
+
+static __thread int nsjailSigFatal = 0;
+static __thread bool nsjailShowProc = false;
+
+static void nsjailSig(int sig) {
+ if (sig == SIGALRM) {
+ return;
+ }
+ if (sig == SIGCHLD) {
+ return;
+ }
+ if (sig == SIGUSR1 || sig == SIGQUIT) {
+ nsjailShowProc = true;
+ return;
+ }
+ nsjailSigFatal = sig;
+}
+
+static bool nsjailSetSigHandler(int sig) {
+ LOG_D("Setting sighandler for signal %s (%d)", utilSigName(sig), sig);
+
+ sigset_t smask;
+ sigemptyset(&smask);
+
+ struct sigaction sa;
+ sa.sa_handler = nsjailSig;
+ sa.sa_mask = smask;
+ sa.sa_flags = 0;
+ sa.sa_restorer = NULL;
+ if (sigaction(sig, &sa, NULL) == -1) {
+ PLOG_E("sigaction(%d)", sig);
+ return false;
+ }
+ return true;
+}
+
+static bool nsjailSetSigHandlers(void) {
+ for (size_t i = 0; i < ARRAYSIZE(nssigs); i++) {
+ if (!nsjailSetSigHandler(nssigs[i])) {
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool nsjailSetTimer(struct nsjconf_t* nsjconf) {
+ if (nsjconf->mode == MODE_STANDALONE_EXECVE) {
+ return true;
+ }
+
+ struct itimerval it = {
+ .it_interval =
+ {
+ .tv_sec = 1,
+ .tv_usec = 0,
+ },
+ .it_value =
+ {
+ .tv_sec = 1,
+ .tv_usec = 0,
+ },
+ };
+ if (setitimer(ITIMER_REAL, &it, NULL) == -1) {
+ PLOG_E("setitimer(ITIMER_REAL)");
+ return false;
+ }
+ return true;
+}
+
+static void nsjailListenMode(struct nsjconf_t* nsjconf) {
+ int listenfd = netGetRecvSocket(nsjconf->bindhost, nsjconf->port);
+ if (listenfd == -1) {
+ return;
+ }
+ for (;;) {
+ if (nsjailSigFatal > 0) {
+ subprocKillAll(nsjconf);
+ logStop(nsjailSigFatal);
+ close(listenfd);
+ return;
+ }
+ if (nsjailShowProc) {
+ nsjailShowProc = false;
+ subprocDisplay(nsjconf);
+ }
+ int connfd = netAcceptConn(listenfd);
+ if (connfd >= 0) {
+ subprocRunChild(nsjconf, connfd, connfd, connfd);
+ close(connfd);
+ }
+ subprocReap(nsjconf);
+ }
+}
+
+static int nsjailStandaloneMode(struct nsjconf_t* nsjconf) {
+ subprocRunChild(nsjconf, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO);
+ for (;;) {
+ int child_status = subprocReap(nsjconf);
+
+ if (subprocCount(nsjconf) == 0) {
+ if (nsjconf->mode == MODE_STANDALONE_ONCE) {
+ return child_status;
+ }
+ subprocRunChild(nsjconf, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO);
+ continue;
+ }
+ if (nsjailShowProc) {
+ nsjailShowProc = false;
+ subprocDisplay(nsjconf);
+ }
+ if (nsjailSigFatal > 0) {
+ subprocKillAll(nsjconf);
+ logStop(nsjailSigFatal);
+ return -1;
+ }
+
+ pause();
+ }
+ // not reached
+}
+
+int main(int argc, char* argv[]) {
+ struct nsjconf_t nsjconf;
+ if (!cmdlineParse(argc, argv, &nsjconf)) {
+ LOG_F("Couldn't parse cmdline options");
+ }
+ if (nsjconf.clone_newuser == false && geteuid() != 0) {
+ LOG_W("--disable_clone_newuser might require root() privs");
+ }
+ if (nsjconf.daemonize && (daemon(0, 0) == -1)) {
+ PLOG_F("daemon");
+ }
+ cmdlineLogParams(&nsjconf);
+ if (nsjailSetSigHandlers() == false) {
+ LOG_F("nsjailSetSigHandlers() failed");
+ }
+ if (nsjailSetTimer(&nsjconf) == false) {
+ LOG_F("nsjailSetTimer() failed");
+ }
+
+ if (nsjconf.mode == MODE_LISTEN_TCP) {
+ nsjailListenMode(&nsjconf);
+ } else {
+ return nsjailStandaloneMode(&nsjconf);
+ }
+ return 0;
+}
}))
#endif /* !defined(TEMP_FAILURE_RETRY) */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
static const int nssigs[] = {
SIGINT,
SIGQUIT,
caps;
};
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
#endif /* _NSJAIL_H */
#include "nsjail.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void subprocRunChild(struct nsjconf_t* nsjconf, int fd_in, int fd_out, int fd_err);
int subprocCount(struct nsjconf_t* nsjconf);
void subprocDisplay(struct nsjconf_t* nsjconf);
/* Returns the exit code of the first failing subprocess, or 0 if none fail */
int subprocReap(struct nsjconf_t* nsjconf);
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
#endif /* NS_PROC_H */
#include "nsjail.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void* utilMalloc(size_t sz);
void* utilCalloc(size_t sz);
char* utilStrDup(const char* str);
const char* utilSigName(int signo);
const char* utilTimeToStr(time_t t);
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
#endif /* NS_UTIL_H */