#include "rpc/runtime_dir.hpp" #include #include #include #include #include #include "rpc/platform/runtime_paths.hpp" namespace velox::daemon::rpc { namespace { std::error_code errc(int e) { return std::error_code(e, std::generic_category()); } // Ensure `dir` exists as a directory we own with mode 0700. Creates it if absent. std::error_code ensure_private_dir(const std::string& dir) { if (::mkdir(dir.c_str(), 0700) != 0 && errno != EEXIST) return errc(errno); struct stat st{}; if (::lstat(dir.c_str(), &st) != 0) return errc(errno); if (!S_ISDIR(st.st_mode)) return errc(ENOTDIR); if (st.st_uid != ::geteuid()) return errc(EPERM); // Tighten if a prior run (or umask) left it looser. Group/other bits must be clear: // the socket is 0600 but a traversable parent still lets another user stat it. if ((st.st_mode & 077) != 0 && ::chmod(dir.c_str(), 0700) != 0) return errc(errno); return {}; } } // namespace std::error_code resolve_runtime_dir(RuntimeDir& out) { std::string base; if (auto ec = platform::runtime_base_dir(base)) return ec; if (!base.empty() && base.back() == '/') base.pop_back(); const std::string dir = base + "/velox"; if (auto ec = ensure_private_dir(dir)) return ec; out.path = dir; return {}; } std::error_code resolve_data_dir(std::string& out) { std::string base; if (auto ec = platform::data_base_dir(base)) return ec; if (!base.empty() && base.back() == '/') base.pop_back(); // Create the XDG base components leniently, then the velox dir with a strict check. ::mkdir(base.c_str(), 0700); const std::string dir = base + "/velox"; if (auto ec = ensure_private_dir(dir)) return ec; out = dir; return {}; } } // namespace velox::daemon::rpc