alexkarle.com

Source for alexkarle.com
git clone git://git.alexkarle.com/alexkarle.com.git
Log | Files | Refs | README | LICENSE

commit df84249f3751747a0e36c0620c2c608dc76cfb8d (patch)
parent a37db38a47c02ad652a2043e90d3e8994175260f
Author: Alex Karle <alex@alexkarle.com>
Date:   Sun, 25 Apr 2021 23:59:00 -0400

kiosk: Demo super secure pledge (stdio + rpath only)

This is mostly a "spike" for fun, but it's worth keeping in the git
history if I want to go back to it.

The idea here is that kiosk will be a login shell open to anonymous,
untrusted, users. As such, I want to be SUPER sure I don't give anyone
shell access to my machine. In this iteration of kiosk, it restricts its
view to just the kiosk/ directory (and /dev/tty for prompting), and then
immediately drops privelages to just standard io and read-only access to
those limited paths. This means that even if there were a bad use of
memory or something like that, the attacker can never spawn a new
process, talk over the internet, or do anything else nefarious to hurt
the system.

The cost? Well, not having the pager ability is kind-of a pain,
especially for longer blog posts... As such, I'll likely just revert
this patch in a commit or two (maybe I'll try writing my own pager.
hmm).

Diffstat:
Msrc/kiosk.c | 21++++++++++++---------
1 file changed, 12 insertions(+), 9 deletions(-)

diff --git a/src/kiosk.c b/src/kiosk.c @@ -5,6 +5,7 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <fcntl.h> int list(void) { DIR *dirp = opendir(MANDIR); @@ -46,10 +47,16 @@ void mandoc(int choice) { int i = 0; while ((dp = readdir(dirp)) != NULL) { if (dp->d_name[0] != '.' && ++i == choice) { - char *cmd_base = "less"; - char cmd[sizeof(cmd_base) + PATH_MAX + 2]; - sprintf(cmd, "%s %s/%s", cmd_base, MANDIR, dp->d_name); - system(cmd); + char path[PATH_MAX]; + sprintf(path, "%s/%s", MANDIR, dp->d_name); + FILE *fd = fopen(path, "r"); + if (fd == NULL) + err(1, "open"); + char c; + while ((c = getc(fd)) != EOF) { + putc(c, stdout); + } + fclose(fd); break; } } @@ -98,14 +105,10 @@ int main(void) { /* All unveils for this proc only (not for less) */ if (unveil(MANDIR, "r") == -1) err(1, "unveil"); - if (unveil("/usr/bin/less", "rx") == -1) - err(1, "unveil"); if (unveil("/dev/tty", "r") == -1) err(1, "unveil"); - if (unveil("/bin/sh", "rx") == -1) /* for system(3) */ - err(1, "unveil"); /* no more unveil's past here! requires pledge*/ - if (pledge("stdio rpath proc exec", NULL) == -1) + if (pledge("stdio rpath", NULL) == -1) err(1, "pledge"); #endif int n = list();