#include "rpc/runtime_dir.hpp" #include #include #include #include #include #include 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 (const char* xdg = ::getenv("XDG_RUNTIME_DIR"); xdg != nullptr && xdg[0] != '\0') { base = xdg; } else { base = "/run/user/" + std::to_string(::geteuid()); struct stat st{}; if (::stat(base.c_str(), &st) != 0 || !S_ISDIR(st.st_mode)) { // No XDG_RUNTIME_DIR and no /run/user/: we refuse rather than pick an // insecure fallback. The caller surfaces this as "cannot start". return errc(ENOENT); } } 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 (const char* xdg = ::getenv("XDG_DATA_HOME"); xdg != nullptr && xdg[0] != '\0') { base = xdg; } else if (const char* home = ::getenv("HOME"); home != nullptr && home[0] != '\0') { base = std::string(home) + "/.local/share"; } else { return errc(ENOENT); } 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