summaryrefslogtreecommitdiff
blob: 87db57afb9eb3f8b9ce5f121d0b6238b6bd463ec (plain)
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
From 24624eaf853158856b8fd0a6f78c873475a16686 Mon Sep 17 00:00:00 2001
From: Colin Watson <cjwatson@debian.org>
Date: Wed, 7 Feb 2018 12:23:15 +0000
Subject: Refactor do_system_drop_privs

Now that we have pipecmd_pre_exec, this can be simplified quite a bit.

* lib/security.c (drop_privs): New function.
(do_system_drop_privs_child, do_system_drop_privs): Remove.
* lib/security.h (drop_privs): Add prototype.
(do_system_drop_privs): Remove prototype.
* src/man.c (make_browser): Add drop_privs pre-exec hook to browser
command.
(format_display): Call browser using pipeline_run rather than
do_system_drop_privs, since it now has a pre-exec hook to drop
privileges.
---
 lib/security.c | 37 +++----------------------------------
 lib/security.h |  2 +-
 src/man.c      |  7 +++++--
 3 files changed, 9 insertions(+), 37 deletions(-)

diff --git a/lib/security.c b/lib/security.c
index 6e84de8..c9b365d 100644
--- a/lib/security.c
+++ b/lib/security.c
@@ -158,42 +158,11 @@ void regain_effective_privs (void)
 #endif /* MAN_OWNER */
 }
 
-#ifdef MAN_OWNER
-void do_system_drop_privs_child (void *data)
+/* Pipeline command pre-exec hook to permanently drop privileges. */
+void drop_privs (void *data ATTRIBUTE_UNUSED)
 {
-	pipeline *p = data;
-
+#ifdef MAN_OWNER
 	if (idpriv_drop ())
 		gripe_set_euid ();
-	exit (pipeline_run (p));
-}
-#endif /* MAN_OWNER */
-
-/* The safest way to execute a pipeline with no effective privileges is to
- * fork, permanently drop privileges in the child, run the pipeline from the
- * child, and wait for it to die.
- *
- * It is possible to use saved IDs to avoid the fork, since effective IDs
- * are copied to saved IDs on execve; we used to do this.  However, forking
- * is not expensive enough to justify the extra code.
- *
- * Note that this frees the supplied pipeline.
- */
-int do_system_drop_privs (pipeline *p)
-{
-#ifdef MAN_OWNER
-	pipecmd *child_cmd;
-	pipeline *child;
-	int status;
-
-	child_cmd = pipecmd_new_function ("unprivileged child",
-					  do_system_drop_privs_child, NULL, p);
-	child = pipeline_new_commands (child_cmd, NULL);
-	status = pipeline_run (child);
-
-	pipeline_free (p);
-	return status;
-#else  /* !MAN_OWNER */
-	return pipeline_run (p);
 #endif /* MAN_OWNER */
 }
diff --git a/lib/security.h b/lib/security.h
index 7545502..851127d 100644
--- a/lib/security.h
+++ b/lib/security.h
@@ -27,7 +27,7 @@
 /* security.c */
 extern void drop_effective_privs (void);
 extern void regain_effective_privs (void);
-extern int do_system_drop_privs (struct pipeline *p);
+extern void drop_privs (void *data);
 extern void init_security (void);
 extern int running_setuid (void);
 extern struct passwd *get_man_owner (void);
diff --git a/src/man.c b/src/man.c
index 959d6cc..ff7ebc7 100644
--- a/src/man.c
+++ b/src/man.c
@@ -1481,6 +1481,7 @@ static pipeline *make_roff_command (const char *dir, const char *file,
 static pipeline *make_browser (const char *pattern, const char *file)
 {
 	pipeline *p;
+	pipecmd *cmd;
 	char *browser = xmalloc (1);
 	int found_percent_s = 0;
 	char *percent;
@@ -1526,7 +1527,9 @@ static pipeline *make_browser (const char *pattern, const char *file)
 		free (esc_file);
 	}
 
-	p = pipeline_new_command_args ("/bin/sh", "-c", browser, NULL);
+	cmd = pipecmd_new_args ("/bin/sh", "-c", browser, NULL);
+	pipecmd_pre_exec (cmd, drop_privs, NULL, NULL);
+	p = pipeline_new_commands (cmd, NULL);
 	pipeline_ignore_signals (p, 1);
 	free (browser);
 
@@ -2021,7 +2024,7 @@ static void format_display (pipeline *decomp,
 			pipeline *browser;
 			debug ("Trying browser: %s\n", candidate);
 			browser = make_browser (candidate, htmlfile);
-			disp_status = do_system_drop_privs (browser);
+			disp_status = pipeline_run (browser);
 			if (!disp_status)
 				break;
 		}
-- 
cgit v1.0-41-gc330