Hi folks,

This is purely OpenBSD-specific; had a brief look at SecComp and
promptly ran away.

Included are pledge(2) diffs for dwm, dmenu, st and slock. I've been
testing these for a week now (both stress-tests and normal usage), and I
have no ill effects to report.

- st has been tortured with cat'ing from /dev/random, ssh'ing into some
  odd boxes, running all sorts of silly ncurses apps, etc. I'm writing
  this email by ssh'ing via mosh to a Linux box running emacs in tmux,
  and everything looks good.

- slock has been thoroughly keyboard-mashed. The question stands,
  whether it's a good idea for a potentially non-exploitable bug in
  slock to be able to kill it and unlock the screen. Perhaps only worth
  enabling in "debug mode"?

- dmenu survived cat'ing some serious /dev/random.

- dwm hasn't been tested super-thoroughly, since I keep this one machine
  free from most random crap; however all of the above apps + dillo,
  firefox, xconsole, and some others didn't seem to cause any problems.

My approach was to first try dropping as much privileges as possible
before initialisation, and then some more right before entering the main
loop. I believe even more privileges could be dropped, e.g. in dwm, if
it used a separate process for handling keyboard launching.

Tested on 5.9-stable, amd64.

If there's interest, I could work on pledging other suckless tools as
well (sbase? ii? quark? sup? suggestions?).

Thanks!
K.

diff --git a/dwm.c b/dwm.c
index ff7e096..aab76b2 100644
--- a/dwm.c
+++ b/dwm.c
@@ -2132,13 +2132,28 @@ main(int argc, char *argv[])
 		die("dwm-"VERSION "\n");
 	else if (argc != 1)
 		die("usage: dwm [-v]\n");
+#if defined(__OpenBSD__)
+	if (pledge("stdio rpath dns unix prot_exec proc exec", NULL) < 0) {
+		die("pledge\n");
+	}
+#endif
 	if (!setlocale(LC_CTYPE, "") || !XSupportsLocale())
 		fputs("warning: no locale support\n", stderr);
 	if (!(dpy = XOpenDisplay(NULL)))
 		die("dwm: cannot open display\n");
+#if defined(__OpenBSD__)
+	if (pledge("stdio rpath prot_exec proc exec", NULL) < 0) {
+		die("pledge\n");
+	}
+#endif
 	checkotherwm();
 	setup();
 	scan();
+#if defined(__OpenBSD__)
+	if (pledge("stdio proc exec", NULL) < 0) {
+		die("pledge\n");
+	}
+#endif
 	run();
 	cleanup();
 	XCloseDisplay(dpy);
diff --git a/dmenu.c b/dmenu.c
index e0c2f80..47a69a7 100644
--- a/dmenu.c
+++ b/dmenu.c
@@ -6,6 +6,7 @@
 #include <string.h>
 #include <strings.h>
 #include <time.h>
+#include <unistd.h>  /* pledge(2) */
 
 #include <X11/Xlib.h>
 #include <X11/Xatom.h>
@@ -496,6 +497,12 @@ run(void)
 {
 	XEvent ev;
 
+#if defined(__OpenBSD__)
+	if (pledge("stdio", NULL) < 0) {
+		die("pledge\n");
+	}
+#endif
+
 	while (!XNextEvent(dpy, &ev)) {
 		if (XFilterEvent(&ev, win))
 			continue;
@@ -654,6 +661,12 @@ main(int argc, char *argv[])
 		else
 			usage();
 
+#if defined(__OpenBSD__)
+	if (pledge("stdio rpath dns unix", NULL) < 0) {
+		die("pledge\n");
+	}
+#endif
+
 	if (!setlocale(LC_CTYPE, "") || !XSupportsLocale())
 		fputs("warning: no locale support\n", stderr);
 	if (!(dpy = XOpenDisplay(NULL)))
@@ -668,6 +681,12 @@ main(int argc, char *argv[])
 		die("no fonts could be loaded.\n");
 	drw_setscheme(drw, &scheme[SchemeNorm]);
 
+#if defined(__OpenBSD__)
+	if (pledge("stdio rpath", NULL) < 0) {
+		die("pledge\n");
+	}
+#endif
+
 	if (fast) {
 		grabkeyboard();
 		readstdin();
diff --git a/st.c b/st.c
index 27536d2..eb5b6b0 100644
--- a/st.c
+++ b/st.c
@@ -4224,6 +4224,12 @@ run(void)
 	struct timespec drawtimeout, *tv = NULL, now, last, lastblink;
 	long deltatime;
 
+#if defined(__OpenBSD__)
+	if (pledge("stdio rpath wpath tty proc getpw exec", NULL) < 0) {
+		die("pledge\n");
+	}
+#endif
+
 	/* Waiting for window mapping */
 	do {
 		XNextEvent(xw.dpy, &ev);
@@ -4247,6 +4253,12 @@ run(void)
 	clock_gettime(CLOCK_MONOTONIC, &last);
 	lastblink = last;
 
+#if defined(__OpenBSD__)
+	if (pledge("stdio rpath tty proc", NULL) < 0) {
+		die("pledge\n");
+	}
+#endif
+
 	for (xev = actionfps;;) {
 		FD_ZERO(&rfd);
 		FD_SET(cmdfd, &rfd);
diff --git a/slock.c b/slock.c
index c9cdee2..7f17ed3 100644
--- a/slock.c
+++ b/slock.c
@@ -299,6 +299,12 @@ main(int argc, char **argv) {
 	dontkillme();
 #endif
 
+#if defined(__OpenBSD__)
+	if (pledge("stdio dns unix rpath prot_exec getpw proc exec", NULL) < 0) {
+		die("pledge\n");
+	}
+#endif
+
 	if (!getpwuid(getuid()))
 		die("no passwd entry for you\n");
 
@@ -334,6 +340,12 @@ main(int argc, char **argv) {
 		die("execvp %s failed: %s\n", argv[1], strerror(errno));
 	}
 
+#if defined(__OpenBSD__)
+	if (pledge("stdio rpath getpw proc exec", NULL) < 0) {
+		die("pledge\n");
+	}
+#endif
+
 	/* Everything is now blank. Now wait for the correct password. */
 #ifdef HAVE_BSD_AUTH
 	readpw(dpy);

Reply via email to