From: David Uhden Collado Subject: Re: [UPDATE] net/i2pd: update to 2.61.0 To: ports@openbsd.org, openbsd@systemfailure.net, lucas@sexy.is, stu@spacehopper.org, andrew@kloet.net Date: Wed, 22 Jul 2026 17:46:00 +0000 Andrew Kloet wrote: > On Wed Jul 22, 2026 at 10:57 AM EDT, Stuart Henderson wrote: >> the revised pledge still feels like shoehorning it into a program >> which has not been designed to actually work with it. big clue >> is having file access and network access in the same process. >> (sure, there's worse in ports, and it's not a total blocker, but >> it does make me wonder how well tested it's been, because clearly >> there hasn't been too much careful thought about how to use this >> prior to it being committed uptream..) > > I've replaced upstream's pledge/unveil with what I had been drafting but > never finished a few months ago. Looking for feedback before I submit it > to upstream. Unfortunately i2pd doesn't have a test suite as far as I > can tell so I find it difficult to make sure all bases have been covered > across pledge/unveil. I ran it for a few minutes and saw no EPERM. > > Doesn't resolve the issue of simul net/file access but I think this > design actually has some thought put into it :p > > Andrew Should we wait for the next release, or should we update the port now? I think the changes are reason enough to update now, especially since we don't know if the main branch will accept your changes. > > > commit f2d7f170ad404eec631c71cda706ad79e252af2c > Author: Andrew Kloet > Date: Wed Jul 22 08:40:12 2026 -0400 > > daemon: redo pledge/unveil > > diff --git a/daemon/Daemon.cpp b/daemon/Daemon.cpp > index ecb73965..022b59f2 100644 > --- a/daemon/Daemon.cpp > +++ b/daemon/Daemon.cpp > @@ -10,10 +10,6 @@ > #include > #include > > -#ifdef __OpenBSD__ > -# include > -#endif > - > #include "Daemon.h" > > #include "Config.h" > @@ -107,84 +103,6 @@ namespace util > i2p::config::ParseConfig(config); > i2p::config::Finalize(); > > -#ifdef __OpenBSD__ > - auto init_pledge =]() { > - std::string pledge_file; i2p::config::GetOption("openbsd.pledge_file", pledge_file); > - if (pledge_file ="") > - { > - LogPrint(eLogDebug, "Use default pledge values"); > - // TODO: remove that not need > - pledge("stdio rpath wpath cpath inet dns unix recvfd sendfd proc error mcast chown flock",nullptr); > - } else { > - std::ifstream f(pledge_file); > - if(!f) { > - std::cerr << "Can't open pledge file " << pledge_file< - exit(1); > - } > - std::string line; > - std::vector rules; > - while(std::getline(f, line)){ > - rules.push_back(line); > - } > - if(f.bad()) { > - std::cerr << "IO error with pledge file" << std::endl; > - } > - std::ostringstream out; > - for(auto r : rules) > - out << r << " "; > - pledge(out.str().c_str(), nullptr); > - } > - > - > - }; > - auto init_unevil =]() { > - unveil("/usr/lib", "r"); > - unveil("/usr/local/lib", "r"); > - unveil("/usr/libexec/ld.so", "r"); > - unveil("/dev/urandom", "r"); > - unveil("/tmp", "rw"); > - unveil("/etc/i2pd", "r"); // ваще не нужно вроде на весь прям каталог > - > - #define UNVEIL_DIR(dir) unveil(dir.c_str(), "rwc") > - > - std::string unevil_file; i2p::config::GetOption("openbsd.unevil_file",unevil_file); > - UNVEIL_DIR(unevil_file); > - std::string tunnelsdir, certsdir, logfile, datadir, reseed_file, openbsd_pledge_file; > - i2p::config::GetOption("tunnelsdir", tunnelsdir); > - UNVEIL_DIR(tunnelsdir); > - i2p::config::GetOption("certsdir", certsdir); > - UNVEIL_DIR(certsdir); > - i2p::config::GetOption("datadir", datadir); > - UNVEIL_DIR(datadir); > - i2p::config::GetOption("reseed.file", reseed_file); > - unveil(reseed_file.c_str(), "r"); > - i2p::config::GetOption("openbsd.pledge_file", openbsd_pledge_file); > - unveil(openbsd_pledge_file.c_str(), "r"); > - std::string tunconf ;i2p::config::GetOption("tunconf", tunconf); unveil(tunconf.c_str(), "r"); > - std::string conf ;i2p::config::GetOption("tunconf", conf); unveil(conf.c_str(), "r"); > - std::string pidfile ;i2p::config::GetOption("pidfile", pidfile); unveil(pidfile.c_str(), "rwc"); > - i2p::config::GetOption("logfile", logfile); unveil(logfile.c_str(), "rwc"); > - if(unevil_file !=") > - { > - std::ifstream f(unevil_file); > - if (!f) { > - std::cerr << "Can't open unevil file" << std::endl; > - exit(1); > - } > - std::string line; > - while(std::getline(f, line)){ > - UNVEIL_DIR(line); > - } > - } > - #undef UNVEIL_DIR > - unveil(NULL, NULL); > - }; > - bool openbsd_unevil_enabled; i2p::config::GetOption("openbsd.unevil_enabled", openbsd_unevil_enabled); > - bool openbsd_pledge_enabled; i2p::config::GetOption("openbsd.pledge_enabled", openbsd_pledge_enabled); > - if(openbsd_unevil_enabled) init_unevil(); > - if(openbsd_pledge_enabled) init_pledge(); > -#endif > - > i2p::config::GetOption("daemon", isDaemon); > > std::string certsdir; i2p::config::GetOption("certsdir", certsdir); > diff --git a/daemon/UnixDaemon.cpp b/daemon/UnixDaemon.cpp > index 43c3c9de..e74bb57b 100644 > --- a/daemon/UnixDaemon.cpp > +++ b/daemon/UnixDaemon.cpp > @@ -210,6 +210,44 @@ namespace i2p > sigaction(SIGCONT, &sa, 0); > } > > +#ifdef __OpenBSD__ > + std::string dataDir =2p::fs::GetDataDir(); > + if (!dataDir.empty()) > + if (unveil(dataDir.c_str(), "rwc") =-1) > + LogPrint(eLogError, "Daemon: Unveil failed for dataDir (", dataDir, "): ", std::strerror(errno)); > + > + auto unveilConfigOption =](const std::string& key, const char* mask) { > + std::string path; > + if (i2p::config::GetOption(key, path) && !path.empty()) > + if (unveil(path.c_str(), mask) =-1) > + LogPrint(eLogError, "Daemon: Unveil failed for ", key, " (", path, "): ", std::strerror(errno)); > + }; > + > + const std::vector> unveilRules = > + {"conf", "r"}, > + {"certsdir", "r"}, > + {"tunconf", "r"}, > + {"tunnelsdir", "r"}, > + {"pidfile", "rwc"}, > + {"logfile", "rwc"}, > + {"reseed.file", "r"}, > + {"reseed.zipfile", "r"} > + }; > + > + for (const auto& rule : unveilRules) > + unveilConfigOption(rule.first, rule.second); > + > + if (unveil(NULL, NULL) =-1) { > + LogPrint(eLogError, "Daemon: unveil lock failed: ", std::strerror(errno)); > + exit(1); > + } > + > + if (pledge("stdio inet dns flock rpath wpath cpath proc", NULL) =-1) { > + LogPrint(eLogError, "Daemon: pledge failed: ", std::strerror(errno)); > + exit(1); > + } > +#endif > + > return Daemon_Singleton::start(); > } > > diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp > index fe406b13..ea137597 100644 > --- a/libi2pd/Config.cpp > +++ b/libi2pd/Config.cpp > @@ -396,16 +396,6 @@ namespace config { > ; > #endif > > -#ifdef __OpenBSD__ > - options_description openbsd_specific("OpenBSD specific options"); > - openbsd_specific.add_options() > - ("openbsd.pledge_file", value()->default_value(""), "OpenbSD file with pledge rules") > - ("openbsd.unevil_file", value()->default_value(""), "OpenBSD file with unevil rules") > - ("openbsd.unevil_enabled", value()->default_value(true), "use unevil rues") > - ("openbsd.pledge_enabled", value()->default_value(true), "use pledge rules") > - ; > -#endif > - > m_OptionsDesc > .add(general) > .add(limits)