Loading config.yaml +8 −0 Changes for config.yaml: 8 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -75,6 +75,13 @@ BLOGI: AUTH_CLIENTNAME: "blogiclient" AUTH_CLIENTSECRET: "clientsecret" MEDIA_URL: "https://127.0.0.1:8442" # CHROOTDIR: "/srv/blogi/chroot/blog.example.com" # Linux: the worker process calls chroot(2) into this directory before # starting the event loop. All paths in this domain config (DB, template, # plugins …) must be relative to the chroot root. # Requires CAP_SYS_CHROOT / root. Leave empty to disable. # Windows: used as the working directory for the worker process and the # process is attached to a Job Object (KILL_ON_JOB_CLOSE). - NAME: "blog.another.org" DB_DRIVER: "sqlite" DB_CONNECTION: "/var/lib/blogi/blog-another.db" Loading @@ -87,3 +94,4 @@ BLOGI: AUTH_CLIENTNAME: "anotherclient" AUTH_CLIENTSECRET: "anothersecret" MEDIA_URL: "https://media.another.org:8442" # CHROOTDIR: "/srv/blogi/chroot/blog.another.org" src/blogi.cpp +54 −1 Changes for src/blogi.cpp: 54 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -3789,12 +3789,28 @@ int main(int argc, char *argv[]) // Pre-fork supervisor: bind socket once, fork one worker per domain. HttpConDPreFork preFork; // Collect per-domain chroot directories before forking so that // the child can enter its jail before the event loop starts. std::vector<std::string> chrootDirs(domainCount); for (size_t d = 0; d < domainCount; ++d) chrootDirs[d] = blogi::Blogi::Cfg->getDomainConfig(d).chrootDir; std::vector<pid_t> pids(domainCount, -1); for (size_t d = 0; d < domainCount; ++d) { pid_t pid = fork(); if (pid == 0) { if (!chrootDirs[d].empty()) { if (::chroot(chrootDirs[d].c_str()) != 0 || ::chdir("/") != 0) { std::cerr << "[domain " << d << "] chroot('" << chrootDirs[d] << "') failed: " << strerror(errno) << std::endl; return 1; } } blogi::Blogi::Cfg->filterDomains(d); blogi::Blogi blg(blogi::Blogi::HttpServer->getServerSockets(), false); blg.runEventloop(); Loading Loading @@ -3822,6 +3838,16 @@ int main(int argc, char *argv[]) pid_t newpid = fork(); if (newpid == 0) { if (!chrootDirs[d].empty()) { if (::chroot(chrootDirs[d].c_str()) != 0 || ::chdir("/") != 0) { std::cerr << "[domain " << d << "] chroot('" << chrootDirs[d] << "') failed: " << strerror(errno) << std::endl; return 1; } } blogi::Blogi::Cfg->filterDomains(d); blogi::Blogi blg(blogi::Blogi::HttpServer->getServerSockets(), false); blg.runEventloop(); Loading Loading @@ -4258,9 +4284,36 @@ int _tmain(int argc, TCHAR *argv[]) std::vector<wchar_t> cmdBuf(cmdLine.begin(), cmdLine.end()); cmdBuf.push_back(L'\0'); // Use chrootDir as working directory for filesystem isolation. LPCWSTR lpDirectory = NULL; std::wstring wChrootDir; const std::string &chrootDir = blogi::Blogi::Cfg->getDomainConfig(d).chrootDir; if (!chrootDir.empty()) { wChrootDir.assign(chrootDir.begin(), chrootDir.end()); lpDirectory = wChrootDir.c_str(); } if (!CreateProcessW(NULL, cmdBuf.data(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) FALSE, 0, NULL, lpDirectory, &si, &pi)) return INVALID_HANDLE_VALUE; // Assign to a Job Object so the worker is killed when the // supervisor exits (KILL_ON_JOB_CLOSE). HANDLE hJob = CreateJobObjectW(NULL, NULL); if (hJob != NULL) { JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = {}; jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; SetInformationJobObject(hJob, JobObjectExtendedLimitInformation, &jeli, sizeof(jeli)); AssignProcessToJobObject(hJob, pi.hProcess); CloseHandle(hJob); } CloseHandle(pi.hThread); return pi.hProcess; }; Loading src/conf.cpp +1 −0 Changes for src/conf.cpp: 1 added line, 0 removed lines. Original line number Diff line number Diff line Loading @@ -122,6 +122,7 @@ blogi::Config::Config(const std::string &path) : confplus::Config(path), _Config try { dc.startPage = getValue(getKey((base + "/STARTPAGE").c_str()), 0); } catch(...) {} try { dc.mediaDBUrl = getValue(getKey((base + "/MEDIA_URL").c_str()), 0); } catch(...) {} try { dc.tmpDir = getValue(getKey((base + "/TMPDIR").c_str()), 0); } catch(...) { dc.tmpDir = "/tmp/blogi"; } try { dc.chrootDir = getValue(getKey((base + "/CHROOTDIR").c_str()), 0); } catch(...) {} try { auto *plgKey = getKey((base + "/PLUGINDIR").c_str()); Loading src/conf.h +1 −0 Changes for src/conf.h: 1 added line, 0 removed lines. Original line number Diff line number Diff line Loading @@ -68,6 +68,7 @@ namespace blogi { std::vector<std::string> plgDirs; std::string mediaDBUrl; std::string tmpDir; std::string chrootDir; const std::string buildurl(const std::string &url) const; }; Loading Loading
config.yaml +8 −0 Changes for config.yaml: 8 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -75,6 +75,13 @@ BLOGI: AUTH_CLIENTNAME: "blogiclient" AUTH_CLIENTSECRET: "clientsecret" MEDIA_URL: "https://127.0.0.1:8442" # CHROOTDIR: "/srv/blogi/chroot/blog.example.com" # Linux: the worker process calls chroot(2) into this directory before # starting the event loop. All paths in this domain config (DB, template, # plugins …) must be relative to the chroot root. # Requires CAP_SYS_CHROOT / root. Leave empty to disable. # Windows: used as the working directory for the worker process and the # process is attached to a Job Object (KILL_ON_JOB_CLOSE). - NAME: "blog.another.org" DB_DRIVER: "sqlite" DB_CONNECTION: "/var/lib/blogi/blog-another.db" Loading @@ -87,3 +94,4 @@ BLOGI: AUTH_CLIENTNAME: "anotherclient" AUTH_CLIENTSECRET: "anothersecret" MEDIA_URL: "https://media.another.org:8442" # CHROOTDIR: "/srv/blogi/chroot/blog.another.org"
src/blogi.cpp +54 −1 Changes for src/blogi.cpp: 54 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -3789,12 +3789,28 @@ int main(int argc, char *argv[]) // Pre-fork supervisor: bind socket once, fork one worker per domain. HttpConDPreFork preFork; // Collect per-domain chroot directories before forking so that // the child can enter its jail before the event loop starts. std::vector<std::string> chrootDirs(domainCount); for (size_t d = 0; d < domainCount; ++d) chrootDirs[d] = blogi::Blogi::Cfg->getDomainConfig(d).chrootDir; std::vector<pid_t> pids(domainCount, -1); for (size_t d = 0; d < domainCount; ++d) { pid_t pid = fork(); if (pid == 0) { if (!chrootDirs[d].empty()) { if (::chroot(chrootDirs[d].c_str()) != 0 || ::chdir("/") != 0) { std::cerr << "[domain " << d << "] chroot('" << chrootDirs[d] << "') failed: " << strerror(errno) << std::endl; return 1; } } blogi::Blogi::Cfg->filterDomains(d); blogi::Blogi blg(blogi::Blogi::HttpServer->getServerSockets(), false); blg.runEventloop(); Loading Loading @@ -3822,6 +3838,16 @@ int main(int argc, char *argv[]) pid_t newpid = fork(); if (newpid == 0) { if (!chrootDirs[d].empty()) { if (::chroot(chrootDirs[d].c_str()) != 0 || ::chdir("/") != 0) { std::cerr << "[domain " << d << "] chroot('" << chrootDirs[d] << "') failed: " << strerror(errno) << std::endl; return 1; } } blogi::Blogi::Cfg->filterDomains(d); blogi::Blogi blg(blogi::Blogi::HttpServer->getServerSockets(), false); blg.runEventloop(); Loading Loading @@ -4258,9 +4284,36 @@ int _tmain(int argc, TCHAR *argv[]) std::vector<wchar_t> cmdBuf(cmdLine.begin(), cmdLine.end()); cmdBuf.push_back(L'\0'); // Use chrootDir as working directory for filesystem isolation. LPCWSTR lpDirectory = NULL; std::wstring wChrootDir; const std::string &chrootDir = blogi::Blogi::Cfg->getDomainConfig(d).chrootDir; if (!chrootDir.empty()) { wChrootDir.assign(chrootDir.begin(), chrootDir.end()); lpDirectory = wChrootDir.c_str(); } if (!CreateProcessW(NULL, cmdBuf.data(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) FALSE, 0, NULL, lpDirectory, &si, &pi)) return INVALID_HANDLE_VALUE; // Assign to a Job Object so the worker is killed when the // supervisor exits (KILL_ON_JOB_CLOSE). HANDLE hJob = CreateJobObjectW(NULL, NULL); if (hJob != NULL) { JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = {}; jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; SetInformationJobObject(hJob, JobObjectExtendedLimitInformation, &jeli, sizeof(jeli)); AssignProcessToJobObject(hJob, pi.hProcess); CloseHandle(hJob); } CloseHandle(pi.hThread); return pi.hProcess; }; Loading
src/conf.cpp +1 −0 Changes for src/conf.cpp: 1 added line, 0 removed lines. Original line number Diff line number Diff line Loading @@ -122,6 +122,7 @@ blogi::Config::Config(const std::string &path) : confplus::Config(path), _Config try { dc.startPage = getValue(getKey((base + "/STARTPAGE").c_str()), 0); } catch(...) {} try { dc.mediaDBUrl = getValue(getKey((base + "/MEDIA_URL").c_str()), 0); } catch(...) {} try { dc.tmpDir = getValue(getKey((base + "/TMPDIR").c_str()), 0); } catch(...) { dc.tmpDir = "/tmp/blogi"; } try { dc.chrootDir = getValue(getKey((base + "/CHROOTDIR").c_str()), 0); } catch(...) {} try { auto *plgKey = getKey((base + "/PLUGINDIR").c_str()); Loading
src/conf.h +1 −0 Changes for src/conf.h: 1 added line, 0 removed lines. Original line number Diff line number Diff line Loading @@ -68,6 +68,7 @@ namespace blogi { std::vector<std::string> plgDirs; std::string mediaDBUrl; std::string tmpDir; std::string chrootDir; const std::string buildurl(const std::string &url) const; }; Loading