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);