Regular mode uses "stdio rpath inet dns proc"; "proc" to fork a child (no exec) unless '--debug nofork' or '--debug nodetach' is set.
--inetd uses "stdio rpath". --pp requires "proc exec" to run, e.g. cpp(1) on the config file which which gets reloaded on SIGHUP: started with --pp means "proc exec" stay. "wpath cpath" are for log and/or pid files and dropped after setup. "getpw id" are for intitial privilege drop and dropped after setup. Works nicely for me with a config like our example. Tested with inetd.conf(5) [::1]:2628 stream tcp6 nowait root /usr/local/sbin/dictd dictd -i Pledges could perhaps start tighter and avoid later dropping, but too many nested `if (option-used)' levels make the code harder to follow, imho. Feedback? Objection? OK? Index: Makefile =================================================================== RCS file: /cvs/ports/net/dictd/Makefile,v diff -u -p -r1.19 Makefile --- Makefile 29 Oct 2023 09:10:49 -0000 1.19 +++ Makefile 29 Oct 2023 09:12:30 -0000 @@ -7,7 +7,7 @@ DISTNAME= dictd-$V PKGNAME-main= dictd-client-$V PKGNAME-server= dictd-server-$V REVISION-main= 1 -REVISION-server=1 +REVISION-server=2 CATEGORIES= net education @@ -17,6 +17,8 @@ MAINTAINER= Klemens Nanni <k...@openbsd.or # GPL v2 PERMIT_PACKAGE= Yes + +# uses pledge() WANTLIB= c maa z SITES= ${SITE_SOURCEFORGE:=dict/} Index: patches/patch-dictd_c =================================================================== RCS file: /cvs/ports/net/dictd/patches/patch-dictd_c,v diff -u -p -r1.1 patch-dictd_c --- patches/patch-dictd_c 27 Oct 2023 18:51:10 -0000 1.1 +++ patches/patch-dictd_c 29 Oct 2023 11:04:17 -0000 @@ -1,9 +1,18 @@ -use dedicated _dictd user/group +- use dedicated _dictd user/group +- use pledge(2) Index: dictd.c --- dictd.c.orig +++ dictd.c -@@ -1269,9 +1272,9 @@ static void release_root_privileges( void ) +@@ -37,6 +37,7 @@ + #include <ctype.h> + #include <sys/stat.h> + #include <fcntl.h> ++#include <unistd.h> /* pledge */ + + #define MAXPROCTITLE 2048 /* Maximum amount of proc title we'll use. */ + #undef MIN +@@ -1269,9 +1270,9 @@ static void release_root_privileges( void ) if (geteuid() == 0) { struct passwd *pwd; @@ -15,3 +24,67 @@ Index: dictd.c setuid(pwd->pw_uid); } else if ((pwd = getpwnam("nobody"))) { setgid(pwd->pw_gid); +@@ -1664,6 +1665,17 @@ int main (int argc, char **argv, char **envp) + default: help(); exit(0); break; + } + ++#ifdef __OpenBSD__ ++ /* no need for "inet dns" when talking to inetd(8) over stdin/out */ ++ if (inetd) { ++ if (pledge("stdio rpath wpath cpath getpw proc exec id", NULL) == -1) ++ err_fatal_errno(__func__, "pledge"); ++ } else { ++ if (pledge("stdio rpath wpath cpath inet dns getpw proc exec id", NULL) == -1) ++ err_fatal_errno(__func__, "pledge"); ++ } ++#endif ++ + if (inetd) + detach = 0; + +@@ -1714,6 +1726,34 @@ int main (int argc, char **argv, char **envp) + pid_file_write (); + } + ++#ifdef __OpenBSD__ ++ /* ++ * drop "wpath cpath" after pid and/or log file setup ++ * drop "getpw id" after privilege drop ++ */ ++ if (inetd) { ++ /* drop "exec" unless --pp was used */ ++ if (preprocessor != NULL) { ++ if (pledge("stdio rpath proc exec", NULL) == -1) ++ err_fatal_errno(__func__, "pledge"); ++ } else { ++ if (pledge("stdio rpath", NULL) == -1) ++ err_fatal_errno(__func__, "pledge"); ++ } ++ } else if (preprocessor != NULL || !dbg_test(DBG_NOFORK)) { ++ if (preprocessor != NULL) { ++ if (pledge("stdio rpath inet dns proc exec", NULL) == -1) ++ err_fatal_errno(__func__, "pledge"); ++ } else { ++ if (pledge("stdio rpath inet dns proc", NULL) == -1) ++ err_fatal_errno(__func__, "pledge"); ++ } ++ } else { ++ if (pledge("stdio rpath inet dns", NULL) == -1) ++ err_fatal_errno(__func__, "pledge"); ++ } ++#endif ++ + time(&startTime); + log_info(":I: %d starting %s %24.24s\n", + getpid(), dict_get_banner(0), ctime(&startTime)); +@@ -1807,6 +1847,10 @@ int main (int argc, char **argv, char **envp) + } else { + if (_dict_forks - _dict_reaps < _dict_daemon_limit_childs) { + if (!start_daemon()) { /* child */ ++#ifdef __OpenBSD__ ++ if (pledge("stdio rpath inet dns", NULL) == -1) ++ err_fatal_errno (__func__, "pledge"); ++#endif + int databases_loaded = (DictConfig != NULL); + + alarm(0);