sandbox.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. #include "xs.h"
  2. #include "snac.h"
  3. #ifdef __linux__
  4. #ifndef WITHOUT_SANDBOX
  5. #include <linux/version.h>
  6. #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 13, 0)
  7. #define WITHOUT_SANDBOX
  8. #endif
  9. #endif
  10. #endif /* __linux__ */
  11. #ifdef WITHOUT_SANDBOX
  12. void sbox_enter(const char *basedir)
  13. {
  14. /* nothing to do */
  15. (void)basedir;
  16. srv_debug(0, xs_fmt("Linux sandboxing disabled or unsupported"));
  17. }
  18. #else /* WITHOUT_SANDBOX */
  19. #include <unistd.h>
  20. #if defined (__linux__)
  21. #define LL_PRINTERR(fmt, ...) srv_debug(0, xs_fmt(fmt, __VA_ARGS__))
  22. #include "landloc.h"
  23. static
  24. LL_BEGIN(sbox_enter_linux_, const char* basedir, const char *address, int smail) {
  25. const unsigned long long
  26. rd = LANDLOCK_ACCESS_FS_READ_DIR,
  27. rf = LANDLOCK_ACCESS_FS_READ_FILE,
  28. w = LANDLOCK_ACCESS_FS_WRITE_FILE |
  29. LANDLOCK_ACCESS_FS_TRUNCATE_COMPAT,
  30. c = LANDLOCK_ACCESS_FS_MAKE_DIR |
  31. LANDLOCK_ACCESS_FS_MAKE_REG |
  32. LANDLOCK_ACCESS_FS_TRUNCATE_COMPAT |
  33. LANDLOCK_ACCESS_FS_MAKE_SYM |
  34. LANDLOCK_ACCESS_FS_REMOVE_DIR |
  35. LANDLOCK_ACCESS_FS_REMOVE_FILE |
  36. LANDLOCK_ACCESS_FS_REFER_COMPAT,
  37. s = LANDLOCK_ACCESS_FS_MAKE_SOCK,
  38. x = LANDLOCK_ACCESS_FS_EXECUTE;
  39. LL_PATH(basedir, rf|rd|w|c);
  40. LL_PATH("/tmp", rf|rd|w|c);
  41. #ifndef WITHOUT_SHM
  42. LL_PATH("/dev/shm", rf|w|c );
  43. #endif
  44. LL_PATH("/etc/resolv.conf", rf );
  45. LL_PATH("/etc/hosts", rf );
  46. LL_PATH("/etc/ssl", rf );
  47. LL_PATH("/usr/share/zoneinfo", rf );
  48. if (mtime("/etc/pki") > 0)
  49. LL_PATH("/etc/pki", rf );
  50. if (*address == '/') {
  51. /* the directory holding the socket must be allowed */
  52. xs *l = xs_split(address, "/");
  53. l = xs_list_del(l, -1);
  54. xs *sdir = xs_join(l, "/");
  55. LL_PATH(sdir, s);
  56. }
  57. if (smail)
  58. LL_PATH("/usr/sbin/sendmail", x);
  59. if (*address != '/') {
  60. unsigned short listen_port = xs_number_get(xs_dict_get(srv_config, "port"));
  61. LL_PORT(listen_port, LANDLOCK_ACCESS_NET_BIND_TCP_COMPAT);
  62. }
  63. LL_PORT(80, LANDLOCK_ACCESS_NET_CONNECT_TCP_COMPAT);
  64. LL_PORT(443, LANDLOCK_ACCESS_NET_CONNECT_TCP_COMPAT);
  65. } LL_END
  66. #endif
  67. void sbox_enter(const char *basedir)
  68. {
  69. const char *address = xs_dict_get(srv_config, "address");
  70. int smail = !xs_is_true(xs_dict_get(srv_config, "disable_email_notifications"));
  71. #if defined (__OpenBSD__)
  72. if (xs_is_true(xs_dict_get(srv_config, "disable_openbsd_security"))) {
  73. srv_log(xs_dup("disable_openbsd_security is deprecated. Use disable_sandbox instead."));
  74. return;
  75. }
  76. if (xs_is_true(xs_dict_get(srv_config, "disable_sandbox"))) {
  77. srv_debug(0, xs_dup("Sandbox disabled by admin"));
  78. return;
  79. }
  80. srv_debug(1, xs_fmt("Calling unveil()"));
  81. unveil(basedir, "rwc");
  82. unveil("/tmp", "rwc");
  83. unveil("/etc/resolv.conf", "r");
  84. unveil("/etc/hosts", "r");
  85. unveil("/etc/ssl/openssl.cnf", "r");
  86. unveil("/etc/ssl/cert.pem", "r");
  87. unveil("/usr/share/zoneinfo", "r");
  88. if (smail)
  89. unveil("/usr/sbin/sendmail", "x");
  90. if (*address == '/')
  91. unveil(address, "rwc");
  92. unveil(NULL, NULL);
  93. srv_debug(1, xs_fmt("Calling pledge()"));
  94. xs *p = xs_str_new("stdio rpath wpath cpath flock inet proc dns fattr");
  95. if (smail)
  96. p = xs_str_cat(p, " exec");
  97. if (*address == '/')
  98. p = xs_str_cat(p, " unix");
  99. pledge(p, NULL);
  100. #elif defined (__linux__)
  101. if (xs_is_true(xs_dict_get_def(srv_config, "disable_sandbox", xs_stock(XSTYPE_TRUE)))) {
  102. srv_debug(0, xs_dup("Sandbox disabled by admin"));
  103. return;
  104. }
  105. if (sbox_enter_linux_(basedir, address, smail) == 0)
  106. srv_log(xs_dup("landlocked"));
  107. else
  108. srv_log(xs_dup("landlocking failed"));
  109. #endif
  110. }
  111. #endif /* WITHOUT_SANDBOX */