1 #include "../../system.h"
7 #include "../../device.h"
8 #include "../../logger.h"
9 #include "../../names.h"
10 #include "../../net.h"
11 #include "../../sandbox.h"
12 #include "../../script.h"
13 #include "../../xalloc.h"
14 #include "../../proxy.h"
16 static sandbox_level_t current_level = SANDBOX_NONE;
17 static bool can_use_new_paths = true;
18 static bool entered = false;
20 static bool chrooted(void) {
21 return !(confbase && *confbase);
24 static void create_conf_subdir(const char *name, mode_t mode) {
26 snprintf(path, sizeof(path), "%s/%s", confbase, name);
30 static void open_conf_subdir(const char *name, const char *privs) {
32 snprintf(path, sizeof(path), "%s/%s", confbase, name);
33 allow_path(path, privs);
36 static void open_common_paths(bool can_exec) {
37 // Dummy device uses a fake path, skip it
38 const char *dev = strcasecmp(device, DEVICE_DUMMY) ? device : NULL;
40 // These calls must be done before the first unveil() for two reasons:
41 // 1. the first unveil() blocks access to all other paths.
42 // 2. unveil() remembers the exact directory and won't allow access if it's (re)created.
43 create_conf_subdir("cache", 0777);
44 create_conf_subdir("hosts", 0777);
45 create_conf_subdir("invitations", 0700);
47 const unveil_path_t paths[] = {
49 {"/dev/urandom", "r"},
50 {confbase, can_exec ? "rx" : "r"},
54 {unixsocketname, "rwc"},
59 open_conf_subdir("cache", "rwc");
60 open_conf_subdir("hosts", can_exec ? "rwxc" : "rwc");
61 open_conf_subdir("invitations", "rwc");
64 static void open_exec_paths(void) {
65 // proxyhost was checked previously. If we're here, proxyhost
66 // contains the path to the executable, and nothing else.
67 const char *proxy_exec = proxytype == PROXY_EXEC ? proxyhost : NULL;
69 const unveil_path_t bin_paths[] = {
74 {"/usr/local/bin", "rx"},
75 {"/usr/local/sbin", "rx"},
76 {scriptinterpreter, "rx"},
80 allow_paths(bin_paths);
83 static bool sandbox_privs(bool can_exec) {
84 // no mcast since multicasting should be set up by now
86 "stdio" // General I/O, both disk and network
87 " rpath" // Read files and directories
88 " wpath" // Write files and directories
89 " cpath" // Create new ones
90 " dns" // Resolve domain names
91 " inet" // Make network connections
92 " unix"; // Control socket connections from tinc CLI
95 // fork() and execve() for scripts and exec proxies
96 const char *exec = " proc exec";
97 size_t n = strlcat(promises, exec, sizeof(promises));
98 assert(n < sizeof(promises));
101 return restrict_privs(promises, can_exec ? PROMISES_ALL : PROMISES_NONE);
104 static void sandbox_paths(bool can_exec) {
106 logger(DEBUG_ALWAYS, LOG_DEBUG, "chroot is used. Disabling path sandbox.");
110 open_common_paths(can_exec);
111 can_use_new_paths = false;
114 if(proxytype == PROXY_EXEC && !access(proxyhost, X_OK)) {
115 logger(DEBUG_ALWAYS, LOG_WARNING, "Looks like a shell expression was used for exec proxy. Using weak path sandbox.");
116 allow_path("/", "rx");
123 static bool sandbox_can_after_enter(sandbox_action_t action) {
125 case START_PROCESSES:
126 return current_level < SANDBOX_HIGH;
129 return can_use_new_paths;
136 bool sandbox_can(sandbox_action_t action, sandbox_time_t when) {
137 if(when == AFTER_SANDBOX || entered) {
138 return sandbox_can_after_enter(action);
144 void sandbox_set_level(sandbox_level_t level) {
146 current_level = level;
149 bool sandbox_enter() {
153 if(current_level == SANDBOX_NONE) {
154 logger(DEBUG_ALWAYS, LOG_DEBUG, "Sandbox is disabled");
158 bool can_exec = sandbox_can_after_enter(START_PROCESSES);
160 sandbox_paths(can_exec);
162 if(sandbox_privs(can_exec)) {
163 logger(DEBUG_ALWAYS, LOG_DEBUG, "Entered sandbox at level %d", current_level);
167 logger(DEBUG_ALWAYS, LOG_ERR, "Could not enter sandbox. Set a lower level or disable it in tinc.conf");
168 current_level = SANDBOX_NONE;