/[baselayout]/branches/baselayout-1_12/src/runscript.c
Gentoo

Contents of /branches/baselayout-1_12/src/runscript.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1462 - (show annotations) (download) (as text)
Fri Sep 2 07:49:48 2005 UTC (9 years, 3 months ago) by azarah
File MIME type: text/x-csrc
File size: 6055 byte(s)
Split the enviroment whitelist for runscript into a system and user part.
Update it to use LIBDIR so that we can set 'lib' or 'lib64'.

1 /*
2 * runscript.c
3 * Handle launching of Gentoo init scripts.
4 *
5 * Copyright 1999-2004 Gentoo Foundation
6 * Distributed under the terms of the GNU General Public License v2
7 * $Header$
8 */
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <unistd.h>
13 #include <string.h>
14 #include <errno.h>
15 #include <sys/types.h>
16 #include <sys/wait.h>
17 #include <dlfcn.h>
18
19 #include "core/debug.h"
20 #include "core/misc.h"
21
22 #ifndef LIBDIR
23 # define LIBDIR "lib"
24 #endif
25
26 #define SBIN_RC "/sbin/rc"
27 #define PROFILE_ENV "/etc/profile.env"
28 #define RCSCRIPTS_LIB "/" LIBDIR "/rcscripts"
29 #define SYS_WHITELIST RCSCRIPTS_LIB "/conf.d/env_whitlist"
30 #define USR_WHITELIST "/etc/conf.d/env_whitlist"
31 #define RCSCRIPT_HELP RCSCRIPTS_LIB "/sh/rc-help.sh"
32 #define SELINUX_LIB RCSCRIPTS_LIB "/runscript_selinux.so"
33 #define SOFTLEVEL "SOFTLEVEL"
34
35 #define DEFAULT_PATH "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/sbin"
36
37 #define IS_SBIN_RC() (0 == strcmp(caller, SBIN_RC))
38
39 static void (*selinux_run_init_old) (void);
40 static void (*selinux_run_init_new) (int argc, char **argv);
41
42 extern char **environ;
43
44 void setup_selinux(int argc, char **argv) {
45 void *lib_handle = NULL;
46
47 lib_handle = dlopen(SELINUX_LIB, RTLD_NOW | RTLD_GLOBAL);
48 if (NULL != lib_handle) {
49 selinux_run_init_old = dlsym(lib_handle, "selinux_runscript");
50 selinux_run_init_new = dlsym(lib_handle, "selinux_runscript2");
51
52 /* Use new run_init if it exists, else fall back to old */
53 if (NULL != selinux_run_init_new)
54 selinux_run_init_new(argc, argv);
55 else if (NULL != selinux_run_init_old)
56 selinux_run_init_old();
57 else {
58 /* This shouldnt happen... probably corrupt lib */
59 fprintf(stderr, "Run_init is missing from runscript_selinux.so!\n");
60 exit(127);
61 }
62 }
63 }
64
65 char **get_whitelist(char **whitelist, char *filename) {
66 char *buf = NULL;
67 char *tmp_buf = NULL;
68 char *tmp_p = NULL;
69 char *token = NULL;
70 size_t lenght = 0;
71 int count = 0;
72 int current = 0;
73
74 if (-1 == file_map(filename, &buf, &lenght))
75 return NULL;
76
77 while (current < lenght) {
78 count = buf_get_line(buf, lenght, current);
79
80 tmp_buf = strndup(&buf[current], count);
81 if (NULL == tmp_buf) {
82 DBG_MSG("Failed to allocate temporary buffer!\n");
83 goto error;
84 }
85 tmp_p = tmp_buf;
86
87 /* Strip leading spaces/tabs */
88 while ((tmp_p[0] == ' ') || (tmp_p[0] == '\t'))
89 tmp_p++;
90
91 /* Get entry - we do not want comments, and only the first word
92 * on a line is valid */
93 token = strsep(&tmp_p, "# \t");
94 if (NULL != token && '\0' != token[0]) {
95 tmp_p = strndup(token, strlen(token));
96 STRING_LIST_ADD(whitelist, tmp_p, error);
97 }
98
99 current += count + 1;
100 free(tmp_buf);
101 /* Set to NULL in case we error out above and have
102 * to free below */
103 tmp_buf = NULL;
104 }
105
106
107 file_unmap(buf, lenght);
108
109 return whitelist;
110
111 error:
112 if (NULL != tmp_buf)
113 free(tmp_buf);
114 file_unmap(buf, lenght);
115 STRING_LIST_FREE(whitelist);
116
117 return NULL;
118 }
119
120 char **filter_environ(char *caller) {
121 char **myenv = NULL;
122 char **whitelist = NULL;
123 char *env_name = NULL;
124 int check_profile = 1;
125 int count = 0;
126
127 if (NULL != getenv(SOFTLEVEL) && !IS_SBIN_RC())
128 /* Called from /sbin/rc, but not /sbin/rc itself, so current
129 * environment should be fine */
130 return environ;
131
132 if (1 == is_file(SYS_WHITELIST, 1))
133 whitelist = get_whitelist(whitelist, SYS_WHITELIST);
134 else
135 EWARN("System environment whitelist missing!\n");
136
137 if (1 == is_file(USR_WHITELIST, 1))
138 whitelist = get_whitelist(whitelist, USR_WHITELIST);
139
140 if (NULL == whitelist)
141 /* If no whitelist is present, revert to old behaviour */
142 return environ;
143
144 if (1 != is_file(PROFILE_ENV, 1))
145 /* XXX: Maybe warn here? */
146 check_profile = 0;
147
148 STRING_LIST_FOR_EACH(whitelist, env_name, count) {
149 char *env_var = NULL;
150 char *tmp_p = NULL;
151 int env_len = 0;
152
153 env_var = getenv(env_name);
154 if (NULL != env_var)
155 goto add_entry;
156
157 if (1 == check_profile) {
158 char *tmp_env_name = NULL;
159 int tmp_len = 0;
160
161 /* The entries in PROFILE_ENV is of the form:
162 * export VAR_NAME=value */
163 tmp_len = strlen(env_name) + strlen("export ") + 1;
164 tmp_env_name = calloc(tmp_len, sizeof(char *));
165 if (NULL == tmp_env_name) {
166 DBG_MSG("Failed to allocate temporary buffer!\n");
167 goto error;
168 }
169 snprintf(tmp_env_name, tmp_len, "export %s", env_name);
170
171 /* Clear errno so that subsequent calls do not trigger
172 * DBG_MSG */
173 errno = 0;
174 env_var = get_cnf_entry(PROFILE_ENV, tmp_env_name);
175 free(tmp_env_name);
176 if (NULL == env_var && ENOMSG != errno)
177 goto error;
178 else if (NULL != env_var)
179 goto add_entry;
180 }
181
182 continue;
183
184 add_entry:
185 env_len = strlen(env_name) + strlen(env_var) + 2;
186 tmp_p = calloc(env_len, sizeof(char *));
187 if (NULL == tmp_p) {
188 DBG_MSG("Failed to allocate temporary buffer!\n");
189 goto error;
190 }
191 snprintf(tmp_p, env_len, "%s=%s", env_name, env_var);
192 STRING_LIST_ADD(myenv, tmp_p, error);
193 }
194
195 STRING_LIST_FREE(whitelist);
196
197 if (NULL == myenv)
198 /* If all else fails, just add a default PATH */
199 STRING_LIST_ADD(myenv, strdup(DEFAULT_PATH), error);
200
201 return myenv;
202
203 error:
204 STRING_LIST_FREE(myenv);
205 STRING_LIST_FREE(whitelist);
206
207 return NULL;
208 }
209
210 int main(int argc, char *argv[]) {
211 char *myargs[32];
212 char **myenv = NULL;
213 char *caller = argv[1];
214 int new = 1;
215
216 myargs[0] = "runscript";
217 while (argv[new] != 0) {
218 myargs[new] = argv[new];
219 new++;
220 }
221 myargs[new] = NULL;
222
223 /* Do not do help for /sbin/rc */
224 if (argc < 3 && !IS_SBIN_RC()) {
225 execv(RCSCRIPT_HELP, myargs);
226 exit(1);
227 }
228
229 /* Setup a filtered environment according to the whitelist */
230 myenv = filter_environ(caller);
231 if (NULL == myenv) {
232 EWARN("%s: Failed to filter the environment!\n", caller);
233 /* XXX: Might think to bail here, but it could mean the system
234 * is rendered unbootable, so rather not */
235 myenv = environ;
236 }
237
238 /* Ok, we are ready to go, so setup selinux if applicable */
239 setup_selinux(argc, argv);
240
241 if (!IS_SBIN_RC()) {
242 if (execve("/sbin/runscript.sh", myargs, myenv) < 0)
243 exit(1);
244 } else {
245 if (execve("/bin/bash", myargs, myenv) < 0)
246 exit(1);
247 }
248
249 return 0;
250 }

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.20