diff options
author | Alexander Kobel | 2018-11-07 00:16:50 +0100 |
---|---|---|
committer | Alexander Kobel | 2018-11-07 00:16:50 +0100 |
commit | 6368dfe8d45a62bebbfb08a40032a95fba9768bd (patch) | |
tree | af96ac57e570fdbdd3c2e945a34999f1278a117d | |
download | aur-6368dfe8d45a62bebbfb08a40032a95fba9768bd.tar.gz |
xscreensaver OOM protection and systemd user service
-rw-r--r-- | .SRCINFO | 16 | ||||
-rw-r--r-- | LICENSE | 14 | ||||
-rw-r--r-- | PKGBUILD | 23 | ||||
-rw-r--r-- | oom_score_adj.c | 61 | ||||
-rw-r--r-- | xscreensaver-oom-protect.c | 114 | ||||
-rw-r--r-- | xscreensaver.service | 16 |
6 files changed, 244 insertions, 0 deletions
diff --git a/.SRCINFO b/.SRCINFO new file mode 100644 index 000000000000..d88b8c753559 --- /dev/null +++ b/.SRCINFO @@ -0,0 +1,16 @@ +pkgbase = xscreensaver-oom-protect + pkgdesc = Protect xscreensaver from the out-of-memory killer + pkgver = 1.0.0 + pkgrel = 1 + arch = x86_64 + license = custom:WTFPL + depends = xscreensaver + source = xscreensaver-oom-protect.c + source = LICENSE + source = xscreensaver.service + md5sums = 43175fd1d4dc75bf02311b1cc6de467e + md5sums = 8365d07beeb5f39d87e846dca3ae7b64 + md5sums = bb945c067ae57367ddc6f041fd33dfa4 + +pkgname = xscreensaver-oom-protect + diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000000..ee7d6a54e914 --- /dev/null +++ b/LICENSE @@ -0,0 +1,14 @@ + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
+ Version 2, December 2004
+
+ Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
+
+ Everyone is permitted to copy and distribute verbatim or modified
+ copies of this license document, and changing it is allowed as long
+ as the name is changed.
+
+ DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. You just DO WHAT THE FUCK YOU WANT TO.
+
diff --git a/PKGBUILD b/PKGBUILD new file mode 100644 index 000000000000..a588be22285b --- /dev/null +++ b/PKGBUILD @@ -0,0 +1,23 @@ +# Maintainer: Alexander Kobel <a-kobel@a-kobel.de> + +pkgname=xscreensaver-oom-protect +pkgver=1.0.0 +pkgrel=1 +pkgdesc="Protect xscreensaver from the out-of-memory killer" +arch=('x86_64') +license=('custom:WTFPL') +depends=('xscreensaver') +source=(${pkgname}.c + LICENSE + xscreensaver.service) +md5sums=('43175fd1d4dc75bf02311b1cc6de467e' + '8365d07beeb5f39d87e846dca3ae7b64' + 'bb945c067ae57367ddc6f041fd33dfa4') + +package() { + cd ${srcdir} + ${CC:-gcc} ${CFLAGS} ${LDFLAGS} -o ${pkgname} ${pkgname}.c + install -D -m4755 -t ${pkgdir}/usr/bin ${pkgname} + install -D -m644 -t ${pkgdir}/usr/lib/systemd/user xscreensaver.service + install -D -m644 -t ${pkgdir}/usr/share/licenses/${pkgname} LICENSE +} diff --git a/oom_score_adj.c b/oom_score_adj.c new file mode 100644 index 000000000000..3fc91dd06a5d --- /dev/null +++ b/oom_score_adj.c @@ -0,0 +1,61 @@ +/* OOM killer adjustment, meant to protect running processes via a small + * setuid-ed "wrapper". */ + +/* (c) 2018 Alexander Kobel <a-kobel@a-kobel.de> */ +/* Published under the WTFPL; see LICENSE. */ + +#include <errno.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <linux/oom.h> + +int usage (char **argv) { + fprintf (stderr, + "Adjust the out-of-memory killer score for a process; " + "see man proc(5).\n" + "\n" + "Usage:\t%s <pid> <oom_score_adj>\n" + "\n" + " <pid>\n" + "\tprocess id\n" + " <oom_score_adj>\n" + "\tinteger between %d and %d inclusive.\n" + "\t(oom_score_adj = %d disables oom killing for this process)\n", + argv[0], OOM_SCORE_ADJ_MIN, OOM_SCORE_ADJ_MAX, OOM_SCORE_ADJ_MIN); + return EINVAL; +} + +int main (int argc, char **argv) { + char *endptr; + long pid; + long oom_score_adj; + char fn[PATH_MAX]; + int n; + FILE *f; + + if (argc != 3) + return usage (argv); + + pid = strtol (argv[1], &endptr, 10); + if (errno == ERANGE || *endptr != 0 || pid < 1) + return usage (argv); + + oom_score_adj = strtol (argv[2], &endptr, 10); + if (errno == ERANGE || *endptr != 0 + || oom_score_adj < OOM_SCORE_ADJ_MIN + || oom_score_adj > OOM_SCORE_ADJ_MAX) + return usage (argv); + + n = snprintf (fn, PATH_MAX, "/proc/%ld/oom_score_adj", pid); + if (n < 0 && n > PATH_MAX) + return ENAMETOOLONG; + f = fopen (fn, "w"); + if (f == NULL) + return EPERM; + fprintf (f, "%ld", oom_score_adj); + fclose (f); + + return 0; +} diff --git a/xscreensaver-oom-protect.c b/xscreensaver-oom-protect.c new file mode 100644 index 000000000000..389b09012288 --- /dev/null +++ b/xscreensaver-oom-protect.c @@ -0,0 +1,114 @@ +/* protect xscreensaver from the OOM killer via a small + * setuid-ed "wrapper". + * + * An attempt to patch the security hole described in + * https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=562884 + * without globally disabling the magic SysRq functionality + * and/or OOM killer, without patching xscreensaver directly. + * + * Hardcoded to check whether the given pid actually is a process for + * /usr/bin/xscreensaver to avoid malicious users protecting arbitrary + * other processes. + * + * If you think you want to consider other screensavers, read + * https://www.jwz.org/xscreensaver/faq.html + * - in particular, #20 and #28 - + * https://www.jwz.org/xscreensaver/faq.html#no-ctl-alt-bs + * https://www.jwz.org/xscreensaver/faq.html#gnome-screensaver + * and + * https://www.jwz.org/xscreensaver/toolkits.html + * and think again. */ + +/* (c) 2018 Alexander Kobel <a-kobel@a-kobel.de> */ +/* Published under the WTFPL; see LICENSE. */ + +#include <errno.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <linux/oom.h> + +int usage (char **argv) { + fprintf (stderr, + "Protect process <pid> from the OOM killer by setting its " + "oom_score_adj to %d.\n" + "(TL;DR: try to avoid that an attacker types Alt+SysRq+F " + "repeatedly and ends up\n" + "with your logged-in session without the xscreensaver lock.)\n" + "Will fail with error code %d if the process does not run " + "/usr/bin/xscreensaver.\n" + "For more information and background, see\n" + "\tman xscreensaver(1) \"Magic Backdoor Keystrokes\"\n" + "\tman proc(5)\n" + "\thttps://bugs.debian.org/cgi-bin/bugreport.cgi?bug=562884\n" + "\n" + "(c) 2018 Alexander Kobel <a-kobel@a-kobel.de>\n" + "\n" + "Usage:\t%s <pid>\n" + "\n" + " <pid>\n" + "\tprocess id of a /usr/bin/xscreensaver instance\n" + "\n" + "Example:\n" + "\tfor pid in $(pgrep xscreensaver); do\n" + "\t\t%s $pid\n" + "\tdone\n" + "\n" + "Preferably called from a supervisor like systemd.\n" + "\n" + "WARNING: The OOM adjustment is not locked, and may be changed or " + "reset again.\n" + "As far as the author is aware, the necessary permissions are those " + "of the\n" + "xscreensaver process itself; and with the same permissions, the " + "OOM score\n" + "adjustment can be lowered again. Thus, for additional security " + "against\n" + "*non-malicious* resets, call the equivalent of\n" + "\techo %d > /proc/<pid>/oom_score_adj\n" + "on each activation of the screensaver (which should be possible " + "as non-root).\n" + "All bets are off against an attacker that already aquired the " + "rights of the\n" + "owner of the original xscreensaver process (and, most probably, " + "there's no need\n" + "to work around that).\n", + OOM_SCORE_ADJ_MIN, EINVAL, argv[0], argv[0], OOM_SCORE_ADJ_MIN); + return EINVAL; +} + +int main (int argc, char **argv) { + char *endptr; + long pid; + char fn[PATH_MAX]; + char xscreensaver_exe[PATH_MAX]; + int n; + FILE *f; + + if (argc != 2) + return usage (argv); + + pid = strtol (argv[1], &endptr, 10); + if (errno == ERANGE || *endptr != 0 || pid < 1) + return usage (argv); + + n = snprintf (fn, PATH_MAX, "/proc/%ld/exe", pid); + if (n < 0 && n > PATH_MAX) + return ENAMETOOLONG; + if (realpath (fn, xscreensaver_exe) == NULL) + return errno; + if (strcmp (xscreensaver_exe, "/usr/bin/xscreensaver") != 0) + return EINVAL; + + n = snprintf (fn, PATH_MAX, "/proc/%ld/oom_score_adj", pid); + if (n < 0 && n > PATH_MAX) + return ENAMETOOLONG; + f = fopen (fn, "w"); + if (f == NULL) + return EPERM; + fprintf (f, "%d", OOM_SCORE_ADJ_MIN); + fclose (f); + + return 0; +} diff --git a/xscreensaver.service b/xscreensaver.service new file mode 100644 index 000000000000..c85317a8e9e5 --- /dev/null +++ b/xscreensaver.service @@ -0,0 +1,16 @@ +[Unit] +Description=xscreensaver with OOM killer protection +Documentation=man:xscreensaver man:xscreensaver-command man:xscreensaver-demo + +[Service] +Type=simple +ExecStartPre=/usr/bin/xscreensaver-command -exit +ExecStart=/usr/bin/xscreensaver -nosplash -no-capture-stderr +ExecStartPost=/usr/bin/xscreensaver-oom-protect $MAINPID +ExecReload=/usr/bin/xscreensaver-command -restart +ExecStop=/usr/bin/xscreensaver-command -exit +Restart=always + +[Install] +WantedBy=default.target +Alias=screensaver.service |