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 <[email protected]>
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 <memory>
  #include <regex>
-#ifdef __OpenBSD__
-#      include<unistd.h>
-#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<<std::endl;
-                                       exit(1);
-                               }
-                               std::string line;
-                               std::vector<std::string> 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<std::pair<std::string, const char*>> 
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<std::string>()->default_value(""), 
"OpenbSD file with pledge rules")
-                       ("openbsd.unevil_file", value<std::string>()->default_value(""), 
"OpenBSD file with unevil rules")
-                       ("openbsd.unevil_enabled", value<bool>()->default_value(true),    
 "use unevil rues")
-                       ("openbsd.pledge_enabled", value<bool>()->default_value(true),    
 "use pledge rules")
-                       ;
-#endif
-
                m_OptionsDesc
                        .add(general)
                        .add(limits)

Reply via email to