1
0

sandbox.c 4.8 KB

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