1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
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
|