summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'sys-apps/man-db/files/man-db-2.8.0-seccomp_suid.patch')
-rw-r--r--sys-apps/man-db/files/man-db-2.8.0-seccomp_suid.patch126
1 files changed, 126 insertions, 0 deletions
diff --git a/sys-apps/man-db/files/man-db-2.8.0-seccomp_suid.patch b/sys-apps/man-db/files/man-db-2.8.0-seccomp_suid.patch
new file mode 100644
index 000000000000..f513ee8cca67
--- /dev/null
+++ b/sys-apps/man-db/files/man-db-2.8.0-seccomp_suid.patch
@@ -0,0 +1,126 @@
+From 10027a400d6a05f463f3981e1191a2f35d0cc02b Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@debian.org>
+Date: Wed, 7 Feb 2018 13:44:30 +0000
+Subject: [PATCH] Fix manconv under seccomp when man is setuid
+
+We must drop privileges before loading the sandbox.
+
+Reported by Lars Wendler.
+
+* src/manconv_client.c (manconv_pre_exec): New function.
+(manconv_stdin): Move setuid hack to ...
+(add_manconv): ... here, now implemented using a custom pre-exec hook.
+We no longer have a fall-through if dropping privileges fails, since
+that's now harder to do and wasn't really necessary in the first place.
+---
+ src/manconv_client.c | 80 +++++++++++++++++++++++++++++-----------------------
+ 1 file changed, 45 insertions(+), 35 deletions(-)
+
+diff --git a/src/manconv_client.c b/src/manconv_client.c
+index d6e010b0..41ce4790 100644
+--- a/src/manconv_client.c
++++ b/src/manconv_client.c
+@@ -56,41 +56,6 @@ static void manconv_stdin (void *data)
+ struct manconv_codes *codes = data;
+ pipeline *p;
+
+-#ifdef MAN_OWNER
+- /* iconv_open may not work correctly in setuid processes; in GNU
+- * libc, gconv modules may be linked against other gconv modules and
+- * rely on RPATH $ORIGIN to load those modules from the correct
+- * path, but $ORIGIN is disabled in setuid processes. It is
+- * impossible to reset libc's idea of setuidness without creating a
+- * whole new process image. Therefore, if the calling process is
+- * setuid, we must drop privileges and execute manconv.
+- *
+- * If dropping privileges fails, fall through to the in-process
+- * code, as in some situations it may actually manage to work.
+- */
+- if (running_setuid () && !idpriv_drop ()) {
+- char **from_code;
+- char *sources = NULL;
+- pipecmd *cmd;
+-
+- for (from_code = codes->from; *from_code; ++from_code) {
+- sources = appendstr (sources, *from_code, NULL);
+- if (*(from_code + 1))
+- sources = appendstr (sources, ":", NULL);
+- }
+-
+- cmd = pipecmd_new_args (MANCONV, "-f", sources,
+- "-t", codes->to, NULL);
+- free (sources);
+-
+- if (quiet >= 2)
+- pipecmd_arg (cmd, "-q");
+-
+- pipecmd_exec (cmd);
+- /* never returns */
+- }
+-#endif /* MAN_OWNER */
+-
+ p = decompress_fdopen (dup (STDIN_FILENO));
+ pipeline_start (p);
+ manconv (p, codes->from, codes->to);
+@@ -98,6 +63,17 @@ static void manconv_stdin (void *data)
+ pipeline_free (p);
+ }
+
++#ifdef MAN_OWNER
++static void manconv_pre_exec (void *data)
++{
++ /* We must drop privileges before loading the sandbox, since our
++ * seccomp filter doesn't allow setresuid and friends.
++ */
++ drop_privs (NULL);
++ sandbox_load (data);
++}
++#endif /* MAN_OWNER */
++
+ static void free_manconv_codes (void *data)
+ {
+ struct manconv_codes *codes = data;
+@@ -139,6 +115,40 @@ void add_manconv (pipeline *p, const char *source, const char *target)
+ name = appendstr (name, " -t ", codes->to, NULL);
+ if (quiet >= 2)
+ name = appendstr (name, " -q", NULL);
++
++#ifdef MAN_OWNER
++ /* iconv_open may not work correctly in setuid processes; in GNU
++ * libc, gconv modules may be linked against other gconv modules and
++ * rely on RPATH $ORIGIN to load those modules from the correct
++ * path, but $ORIGIN is disabled in setuid processes. It is
++ * impossible to reset libc's idea of setuidness without creating a
++ * whole new process image. Therefore, if the calling process is
++ * setuid, we must drop privileges and execute manconv.
++ */
++ if (running_setuid ()) {
++ char **from_code;
++ char *sources = NULL;
++
++ cmd = pipecmd_new_args (MANCONV, "-f", NULL);
++ for (from_code = codes->from; *from_code; ++from_code) {
++ sources = appendstr (sources, *from_code, NULL);
++ if (*(from_code + 1))
++ sources = appendstr (sources, ":", NULL);
++ }
++ pipecmd_arg (cmd, sources);
++ free (sources);
++ pipecmd_args (cmd, "-t", codes->to, NULL);
++ if (quiet >= 2)
++ pipecmd_arg (cmd, "-q");
++ pipecmd_pre_exec (cmd, manconv_pre_exec, sandbox_free,
++ sandbox);
++ free (name);
++ free_manconv_codes (codes);
++ pipeline_command (p, cmd);
++ return;
++ }
++#endif /* MAN_OWNER */
++
+ cmd = pipecmd_new_function (name, &manconv_stdin, &free_manconv_codes,
+ codes);
+ free (name);
+--
+2.16.1
+