/[path-sandbox]/trunk/src/environ.c
Gentoo

Contents of /trunk/src/environ.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 370 - (show annotations) (download) (as text)
Sun Nov 9 10:29:58 2008 UTC (6 years, 8 months ago) by vapier
File MIME type: text/x-csrc
File size: 9658 byte(s)
consolidate all random system includes into headers.h
1 /*
2 * environ.c
3 *
4 * Environment setup and related functions.
5 *
6 * Copyright 1999-2008 Gentoo Foundation
7 * Licensed under the GPL-2
8 */
9
10 #include "headers.h"
11 #include "sbutil.h"
12 #include "sandbox.h"
13
14 static char *subst_env_vars(rc_dynbuf_t *);
15 static void setup_cfg_var(const char *);
16 static int setup_access_var(const char *);
17 static int setup_cfg_vars(struct sandbox_info_t *);
18 static int sb_setenv(char ***, const char *, const char *);
19
20 extern char **environ;
21
22 /* Replace '${FOO}' style strings in passed data with the value of named
23 * environment variable. */
24 static char *subst_env_vars(rc_dynbuf_t *env_data)
25 {
26 rc_dynbuf_t *new_data = NULL;
27 char *tmp_ptr, *tmp_data = NULL;
28 char *var_start, *var_stop;
29
30 new_data = rc_dynbuf_new();
31 if (NULL == new_data)
32 return NULL;
33
34 tmp_data = rc_dynbuf_read_line(env_data);
35 if (NULL == tmp_data)
36 goto error;
37 tmp_ptr = tmp_data;
38
39 while (NULL != (var_start = strchr(tmp_ptr, '$'))) {
40 char *env = NULL;
41
42 var_stop = strchr(var_start, '}');
43
44 /* We only support ${} style env var names, so just skip any
45 * '$' that do not follow this syntax */
46 if (('{' != var_start[1]) || (NULL == var_stop)) {
47 tmp_ptr = var_start + 1;
48 continue;
49 }
50
51 /* Terminate part before env string so that we can copy it */
52 var_start[0] = '\0';
53 /* Move var_start past '${' */
54 var_start += 2;
55 /* Terminate the name of the env var */
56 var_stop[0] = '\0';
57
58 if (strlen(var_start) > 0)
59 env = getenv(var_start);
60 if (-1 == rc_dynbuf_sprintf(new_data, "%s%s",
61 tmp_ptr ? tmp_ptr : "",
62 env ? env : ""))
63 goto error;
64
65 /* Move tmp_ptr past the '}' of the env var */
66 tmp_ptr = var_stop + 1;
67 }
68
69 if (0 != strlen(tmp_ptr))
70 if (-1 == rc_dynbuf_write(new_data, tmp_ptr, strlen(tmp_ptr)))
71 goto error;
72
73 free(tmp_data);
74
75 tmp_data = rc_dynbuf_read_line(new_data);
76 if (NULL == tmp_data)
77 goto error;
78
79 rc_dynbuf_free(new_data);
80
81 return tmp_data;
82
83 error:
84 if (NULL != new_data)
85 rc_dynbuf_free(new_data);
86 if (NULL != tmp_data)
87 free(tmp_data);
88
89 return NULL;
90 }
91
92 /* Get passed variable from sandbox.conf, and set it in the environment. */
93 static void setup_cfg_var(const char *env_var)
94 {
95 char *config;
96
97 /* We check if the variable is set in the environment, and if not, we
98 * get it from sandbox.conf, and if they exist, we just add them to the
99 * environment if not already present. */
100 config = rc_get_cnf_entry(SANDBOX_CONF_FILE, env_var, NULL);
101 if (NULL != config) {
102 setenv(ENV_SANDBOX_VERBOSE, config, 0);
103 free(config);
104 }
105 }
106
107 /* Get passed access variable from sandbox.conf for sandbox.d/, and set it in
108 * the environment. */
109 static int setup_access_var(const char *access_var)
110 {
111 rc_dynbuf_t *env_data = NULL;
112 int count = 0;
113 char *config = NULL;
114 char **confd_files = NULL;
115 bool use_confd = TRUE;
116
117 env_data = rc_dynbuf_new();
118 if (NULL == env_data)
119 return -1;
120
121 /* Now get the defaults for the access variable from sandbox.conf.
122 * These do not get overridden via the environment. */
123 config = rc_get_cnf_entry(SANDBOX_CONF_FILE, access_var, ":");
124 if (NULL != config) {
125 if (-1 == rc_dynbuf_write(env_data, config, strlen(config)))
126 goto error;
127 free(config);
128 config = NULL;
129 }
130 /* Append whatever might be already set. If anything is set, we do
131 * not process the sandbox.d/ files for this variable. */
132 if (NULL != getenv(access_var)) {
133 use_confd = FALSE;
134 if (-1 == rc_dynbuf_sprintf(env_data, env_data->wr_index ? ":%s" : "%s",
135 getenv(access_var)))
136 goto error;
137 }
138
139 if (!use_confd)
140 goto done;
141
142 /* Now scan the files in sandbox.d/ if the access variable was not
143 * alreay set. */
144 confd_files = rc_ls_dir(SANDBOX_CONFD_DIR, FALSE, TRUE);
145 if (NULL != confd_files) {
146 while (NULL != confd_files[count]) {
147 config = rc_get_cnf_entry(confd_files[count], access_var, ":");
148 if (NULL != config) {
149 if (-1 == rc_dynbuf_sprintf(env_data,
150 env_data->wr_index ? ":%s" : "%s",
151 config))
152 goto error;
153 free(config);
154 config = NULL;
155 }
156 count++;
157 }
158
159 str_list_free(confd_files);
160 }
161
162 done:
163 if (env_data->wr_index > 0) {
164 char *subst;
165
166 subst = subst_env_vars(env_data);
167 if (NULL == subst)
168 goto error;
169
170 setenv(access_var, subst, 1);
171 free(subst);
172 }
173
174 rc_dynbuf_free(env_data);
175
176 return 0;
177
178 error:
179 if (NULL != env_data)
180 rc_dynbuf_free(env_data);
181 if (NULL != config)
182 free(config);
183 if (NULL != confd_files)
184 str_list_free(confd_files);
185
186 return -1;
187 }
188
189 /* Initialize all config and access variables, and set them in the
190 * environment. */
191 static int setup_cfg_vars(struct sandbox_info_t *sandbox_info)
192 {
193 setup_cfg_var(ENV_SANDBOX_VERBOSE);
194 setup_cfg_var(ENV_SANDBOX_DEBUG);
195 setup_cfg_var(ENV_SANDBOX_BEEP);
196 setup_cfg_var(ENV_NOCOLOR);
197
198 if (-1 == setup_access_var(ENV_SANDBOX_DENY))
199 return -1;
200 if (NULL == getenv(ENV_SANDBOX_DENY))
201 setenv(ENV_SANDBOX_DENY, LD_PRELOAD_FILE, 1);
202
203 if (-1 == setup_access_var(ENV_SANDBOX_READ))
204 return -1;
205 if (NULL == getenv(ENV_SANDBOX_READ))
206 setenv(ENV_SANDBOX_READ, "/", 1);
207
208 if (-1 == setup_access_var(ENV_SANDBOX_WRITE))
209 return -1;
210 if ((NULL == getenv(ENV_SANDBOX_WRITE)) &&
211 (NULL != sandbox_info->work_dir))
212 setenv(ENV_SANDBOX_WRITE, sandbox_info->work_dir, 1);
213
214 if (-1 == setup_access_var(ENV_SANDBOX_PREDICT))
215 return -1;
216 if ((NULL == getenv(ENV_SANDBOX_PREDICT)) &&
217 (NULL != sandbox_info->home_dir))
218 setenv(ENV_SANDBOX_PREDICT, sandbox_info->home_dir, 1);
219
220 return 0;
221 }
222
223 static int sb_setenv(char ***envp, const char *name, const char *val)
224 {
225 char *tmp_string = NULL;
226
227 /* strlen(name) + strlen(val) + '=' + '\0' */
228 tmp_string = xmalloc((strlen(name) + strlen(val) + 2) * sizeof(char));
229 if (NULL == tmp_string)
230 goto error;
231
232 snprintf(tmp_string, strlen(name) + strlen(val) + 2,
233 "%s=%s", name, val);
234
235 str_list_add_item((*envp), tmp_string, error);
236
237 return 0;
238
239 error:
240 perror("sandbox: Out of memory (sb_setenv)");
241 exit(EXIT_FAILURE);
242 }
243
244 /* We setup the environment child side only to prevent issues with
245 * setting LD_PRELOAD parent side */
246 char **setup_environ(struct sandbox_info_t *sandbox_info, bool interactive)
247 {
248 int have_ld_preload = 0;
249
250 char **new_environ = NULL;
251 char **env_ptr;
252 char *ld_preload_envvar = NULL;
253 char *orig_ld_preload_envvar = NULL;
254 char sb_pid[64];
255
256 if (-1 == setup_cfg_vars(sandbox_info))
257 return NULL;
258
259 /* Unset these, as its easier than replacing when setting up our
260 * new environment below */
261 unsetenv(ENV_SANDBOX_ON);
262 unsetenv(ENV_SANDBOX_PID);
263 unsetenv(ENV_SANDBOX_LIB);
264 unsetenv(ENV_SANDBOX_BASHRC);
265 unsetenv(ENV_SANDBOX_LOG);
266 unsetenv(ENV_SANDBOX_DEBUG_LOG);
267 unsetenv(ENV_SANDBOX_WORKDIR);
268 unsetenv(ENV_SANDBOX_ACTIVE);
269 unsetenv(ENV_SANDBOX_INTRACTV);
270 unsetenv(ENV_BASH_ENV);
271
272 if (NULL != getenv(ENV_LD_PRELOAD)) {
273 have_ld_preload = 1;
274 orig_ld_preload_envvar = getenv(ENV_LD_PRELOAD);
275
276 ld_preload_envvar = xcalloc(strlen(orig_ld_preload_envvar) +
277 strlen(sandbox_info->sandbox_lib) + 2,
278 sizeof(char));
279 if (NULL == ld_preload_envvar)
280 return NULL;
281 snprintf(ld_preload_envvar, strlen(orig_ld_preload_envvar) +
282 strlen(sandbox_info->sandbox_lib) + 2, "%s %s",
283 sandbox_info->sandbox_lib, orig_ld_preload_envvar);
284 } else {
285 ld_preload_envvar = rc_strndup(sandbox_info->sandbox_lib,
286 strlen(sandbox_info->sandbox_lib));
287 if (NULL == ld_preload_envvar)
288 return NULL;
289 }
290 /* Do not unset this, as strange things might happen */
291 /* unsetenv(ENV_LD_PRELOAD); */
292
293 snprintf(sb_pid, sizeof(sb_pid), "%i", getpid());
294
295 /* First add our new variables to the beginning - this is due to some
296 * weirdness that I cannot remember */
297 sb_setenv(&new_environ, ENV_SANDBOX_ON, "1");
298 sb_setenv(&new_environ, ENV_SANDBOX_PID, sb_pid);
299 sb_setenv(&new_environ, ENV_SANDBOX_LIB, sandbox_info->sandbox_lib);
300 sb_setenv(&new_environ, ENV_SANDBOX_BASHRC, sandbox_info->sandbox_rc);
301 sb_setenv(&new_environ, ENV_SANDBOX_LOG, sandbox_info->sandbox_log);
302 sb_setenv(&new_environ, ENV_SANDBOX_DEBUG_LOG,
303 sandbox_info->sandbox_debug_log);
304 /* Is this an interactive session? */
305 if (interactive)
306 sb_setenv(&new_environ, ENV_SANDBOX_INTRACTV, "1");
307 /* Just set the these if not already set so that is_env_on() work */
308 if (!getenv(ENV_SANDBOX_VERBOSE))
309 sb_setenv(&new_environ, ENV_SANDBOX_VERBOSE, "1");
310 if (!getenv(ENV_SANDBOX_DEBUG))
311 sb_setenv(&new_environ, ENV_SANDBOX_DEBUG, "0");
312 if (!getenv(ENV_NOCOLOR))
313 sb_setenv(&new_environ, ENV_NOCOLOR, "no");
314 /* If LD_PRELOAD was not set, set it here, else do it below */
315 if (1 != have_ld_preload)
316 sb_setenv(&new_environ, ENV_LD_PRELOAD, ld_preload_envvar);
317
318 /* Make sure our bashrc gets preference */
319 sb_setenv(&new_environ, ENV_BASH_ENV, sandbox_info->sandbox_rc);
320
321 /* This one should NEVER be set in ebuilds, as it is the one
322 * private thing libsandbox.so use to test if the sandbox
323 * should be active for this pid, or not.
324 *
325 * azarah (3 Aug 2002)
326 */
327
328 sb_setenv(&new_environ, ENV_SANDBOX_ACTIVE, SANDBOX_ACTIVE);
329
330 /* Now add the rest */
331 env_ptr = environ;
332 while (NULL != *env_ptr) {
333 if ((1 == have_ld_preload) &&
334 (strstr(*env_ptr, LD_PRELOAD_EQ) == *env_ptr))
335 /* If LD_PRELOAD was set, and this is it in the original
336 * environment, replace it with our new copy */
337 /* XXX: The following works as it just add whatever as
338 * the last variable to nev_environ */
339 sb_setenv(&new_environ, ENV_LD_PRELOAD,
340 ld_preload_envvar);
341 else
342 str_list_add_item_copy(new_environ, (*env_ptr), error);
343
344 env_ptr++;
345 }
346
347 if (NULL != ld_preload_envvar)
348 free(ld_preload_envvar);
349
350 return new_environ;
351
352 error:
353 if (NULL != new_environ)
354 str_list_free(new_environ);
355 if (NULL != ld_preload_envvar)
356 free(ld_preload_envvar);
357
358 return NULL;
359 }

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

  ViewVC Help
Powered by ViewVC 1.1.20