sandbox.c (4680B)
1 #include "xs.h" 2 3 #include "snac.h" 4 5 #if defined(__OpenBSD__) 6 7 void sbox_enter(const char *basedir) 8 { 9 const char *address = xs_dict_get(srv_config, "address"); 10 11 if (xs_is_true(xs_dict_get(srv_config, "disable_openbsd_security"))) { 12 srv_log(xs_dup("OpenBSD security disabled by admin")); 13 return; 14 } 15 16 int smail; 17 const char *url = xs_dict_get(srv_config, "smtp_url"); 18 19 if (xs_is_string(url) && *url) 20 smail = 0; 21 else 22 smail = !xs_is_true(xs_dict_get(srv_config, "disable_email_notifications")); 23 24 srv_debug(1, xs_fmt("Calling unveil()")); 25 unveil(basedir, "rwc"); 26 unveil("/tmp", "rwc"); 27 unveil("/etc/resolv.conf", "r"); 28 unveil("/etc/hosts", "r"); 29 unveil("/etc/ssl/openssl.cnf", "r"); 30 unveil("/etc/ssl/cert.pem", "r"); 31 unveil("/usr/share/zoneinfo", "r"); 32 33 if (*address == '/') 34 unveil(address, "rwc"); 35 36 if (smail) 37 unveil("/usr/sbin/sendmail", "x"); 38 39 unveil(NULL, NULL); 40 41 srv_debug(1, xs_fmt("Calling pledge()")); 42 43 xs *p = xs_str_new("stdio rpath wpath cpath flock inet proc dns fattr"); 44 45 if (*address == '/') 46 p = xs_str_cat(p, " unix"); 47 48 if (smail) 49 p = xs_str_cat(p, " exec"); 50 51 pledge(p, NULL); 52 } 53 54 #elif defined(__linux__) 55 56 #if defined(WITH_LINUX_SANDBOX) 57 58 #include <unistd.h> 59 60 #define LL_PRINTERR(fmt, ...) srv_debug(0, xs_fmt(fmt, __VA_ARGS__)) 61 #include "landloc.h" 62 63 static 64 LL_BEGIN(sbox_enter_linux_, const char* basedir, const char *address, int smtp_port) { 65 66 const unsigned long long 67 rd = LANDLOCK_ACCESS_FS_READ_DIR, 68 rf = LANDLOCK_ACCESS_FS_READ_FILE, 69 w = LANDLOCK_ACCESS_FS_WRITE_FILE | 70 LANDLOCK_ACCESS_FS_TRUNCATE_COMPAT, 71 c = LANDLOCK_ACCESS_FS_MAKE_DIR | 72 LANDLOCK_ACCESS_FS_MAKE_REG | 73 LANDLOCK_ACCESS_FS_TRUNCATE_COMPAT | 74 LANDLOCK_ACCESS_FS_MAKE_SYM | 75 LANDLOCK_ACCESS_FS_REMOVE_DIR | 76 LANDLOCK_ACCESS_FS_REMOVE_FILE | 77 LANDLOCK_ACCESS_FS_REFER_COMPAT, 78 s = LANDLOCK_ACCESS_FS_MAKE_SOCK, 79 x = LANDLOCK_ACCESS_FS_EXECUTE; 80 char *resolved_path = NULL; 81 82 LL_PATH(basedir, rf|rd|w|c); 83 LL_PATH("/tmp", rf|rd|w|c); 84 #ifndef WITHOUT_SHM 85 LL_PATH("/dev/shm", rf|w|c ); 86 #endif 87 LL_PATH("/dev/urandom", rf ); 88 LL_PATH("/etc/resolv.conf", rf ); 89 LL_PATH("/etc/hosts", rf ); 90 LL_PATH("/etc/ssl", rf|rd ); 91 if ((resolved_path = realpath("/etc/ssl/cert.pem", NULL))) { 92 /* some distros like cert.pem to be a symlink */ 93 LL_PATH(resolved_path, rf ); 94 free(resolved_path); 95 } 96 LL_PATH("/usr/share/zoneinfo", rf ); 97 98 if (mtime("/etc/pki") > 0) 99 LL_PATH("/etc/pki", rf ); 100 101 if (*address == '/') { 102 /* the directory holding the socket must be allowed */ 103 xs *l = xs_split(address, "/"); 104 l = xs_list_del(l, -1); 105 xs *sdir = xs_join(l, "/"); 106 107 LL_PATH(sdir, s); 108 } 109 110 if (*address != '/') { 111 unsigned short listen_port = xs_number_get(xs_dict_get(srv_config, "port")); 112 LL_PORT(listen_port, LANDLOCK_ACCESS_NET_BIND_TCP_COMPAT); 113 } 114 115 LL_PORT(80, LANDLOCK_ACCESS_NET_CONNECT_TCP_COMPAT); 116 LL_PORT(443, LANDLOCK_ACCESS_NET_CONNECT_TCP_COMPAT); 117 if (smtp_port > 0) 118 LL_PORT((unsigned short)smtp_port, LANDLOCK_ACCESS_NET_CONNECT_TCP_COMPAT); 119 120 } LL_END 121 122 void sbox_enter(const char *basedir) 123 { 124 const char *errstr; 125 const char *address = xs_dict_get(srv_config, "address"); 126 const char *smtp_url = xs_dict_get(srv_config, "smtp_url"); 127 int smtp_port = -1; 128 129 if (xs_is_true(xs_dict_get(srv_config, "disable_sandbox"))) { 130 srv_debug(1, xs_dup("Linux sandbox disabled by admin")); 131 return; 132 } 133 134 if (xs_is_string(smtp_url) && *smtp_url != '\0') { 135 smtp_port = parse_port(smtp_url, &errstr); 136 if (errstr) 137 srv_debug(0, xs_fmt("Couldn't determine port from '%s': %s", smtp_url, errstr)); 138 } 139 140 if (sbox_enter_linux_(basedir, address, smtp_port) == 0) 141 srv_debug(1, xs_dup("Linux sandbox enabled")); 142 else 143 srv_debug(0, xs_dup("Linux sandbox failed")); 144 } 145 146 #else /* defined(WITH_LINUX_SANDBOX) */ 147 148 void sbox_enter(const char *basedir) 149 { 150 (void)basedir; 151 152 srv_debug(1, xs_fmt("Linux sandbox not compiled in")); 153 } 154 155 #endif 156 157 #else 158 159 /* other OSs: dummy sbox_enter() */ 160 161 void sbox_enter(const char *basedir) 162 { 163 (void)basedir; 164 } 165 166 167 #endif /* __OpenBSD__ */