]>
git.ipfire.org Git - thirdparty/util-linux.git/blob - lib/env.c
2 * environ[] array cleanup code and getenv() wrappers
4 * No copyright is claimed. This code is in the public domain; do with
10 #ifdef HAVE_SYS_PRCTL_H
11 #include <sys/prctl.h>
13 #define PR_GET_DUMPABLE 3
15 #if (!defined(HAVE_PRCTL) && defined(linux))
16 #include <sys/syscall.h>
19 #include <sys/types.h>
24 #ifndef HAVE_ENVIRON_DECL
25 extern char **environ
;
28 static char * const forbid
[] = {
29 "BASH_ENV=", /* GNU creeping featurism strikes again... */
34 "LD_", /* anything with the LD_ prefix */
44 /* these are allowed, but with no slashes inside
45 (to work around security problems in GNU gettext) */
46 static char * const noslash
[] = {
49 "LC_", /* anything with the LC_ prefix */
56 struct ul_env_list
*next
;
60 * Saves @name env.variable to @ls, returns pointer to the new head of the list.
62 static struct ul_env_list
*env_list_add(struct ul_env_list
*ls0
, const char *str
)
64 struct ul_env_list
*ls
;
72 p
= malloc(sizeof(struct ul_env_list
) + sz
);
76 ls
= (struct ul_env_list
*) p
;
77 p
+= sizeof(struct ul_env_list
);
86 * Use env_from_fd() to read environment from @fd.
88 * @fd must be /proc/<pid>/environ file.
90 struct ul_env_list
*env_from_fd(int fd
)
94 struct ul_env_list
*ls
= NULL
;
96 if ((rc
= read_all_alloc(fd
, &buf
)) < 1)
102 ls
= env_list_add(ls
, p
);
112 * Use setenv() for all stuff in @ls.
114 * It would be possible to use putenv(), but we want to keep @ls free()-able.
116 int env_list_setenv(struct ul_env_list
*ls
)
120 while (ls
&& rc
== 0) {
122 char *val
= strchr(ls
->env
, '=');
126 rc
= setenv(ls
->env
, val
+ 1, 0);
134 void env_list_free(struct ul_env_list
*ls
)
137 struct ul_env_list
*x
= ls
;
144 * Removes unwanted variables from environ[]. If @org is not NULL than stores
145 * unwnated variables to the list.
147 void __sanitize_env(struct ul_env_list
**org
)
149 char **envp
= environ
;
154 for (cur
= envp
; *cur
; cur
++)
157 for (cur
= envp
; *cur
; cur
++) {
158 for (bad
= forbid
; *bad
; bad
++) {
159 if (strncmp(*cur
, *bad
, strlen(*bad
)) == 0) {
161 *org
= env_list_add(*org
, *cur
);
162 last
= remove_entry(envp
, cur
- envp
, last
);
169 for (cur
= envp
; *cur
; cur
++) {
170 for (bad
= noslash
; *bad
; bad
++) {
171 if (strncmp(*cur
, *bad
, strlen(*bad
)) != 0)
173 if (!strchr(*cur
, '/'))
176 *org
= env_list_add(*org
, *cur
);
177 last
= remove_entry(envp
, cur
- envp
, last
);
184 void sanitize_env(void)
186 __sanitize_env(NULL
);
189 char *safe_getenv(const char *arg
)
191 if ((getuid() != geteuid()) || (getgid() != getegid()))
194 if (prctl(PR_GET_DUMPABLE
, 0, 0, 0, 0) == 0)
197 #if (defined(linux) && defined(SYS_prctl))
198 if (syscall(SYS_prctl
, PR_GET_DUMPABLE
, 0, 0, 0, 0) == 0)
202 #ifdef HAVE_SECURE_GETENV
203 return secure_getenv(arg
);
204 #elif HAVE___SECURE_GETENV
205 return __secure_getenv(arg
);
217 int retval
= EXIT_SUCCESS
;
218 struct ul_env_list
*removed
= NULL
;
220 for (bad
= forbid
; *bad
; bad
++) {
222 p
= strchr(copy
, '=');
225 setenv(copy
, copy
, 1);
229 __sanitize_env(&removed
);
232 for (bad
= forbid
; *bad
; bad
++) {
234 p
= strchr(copy
, '=');
239 warnx("%s was not removed", copy
);
240 retval
= EXIT_FAILURE
;
244 /* restore removed */
245 env_list_setenv(removed
);
248 for (bad
= forbid
; *bad
; bad
++) {
250 p
= strchr(copy
, '=');
255 warnx("%s was not restored", copy
);
256 retval
= EXIT_FAILURE
;
260 env_list_free(removed
);