]>
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>
23 #ifndef HAVE_ENVIRON_DECL
24 extern char **environ
;
27 static char * const forbid
[] = {
28 "BASH_ENV=", /* GNU creeping featurism strikes again... */
33 "LD_", /* anything with the LD_ prefix */
43 /* these are allowed, but with no slashes inside
44 (to work around security problems in GNU gettext) */
45 static char * const noslash
[] = {
48 "LC_", /* anything with the LC_ prefix */
55 struct ul_env_list
*next
;
59 * Saves @name env.variable to @ls, returns pointer to the new head of the list.
61 static struct ul_env_list
*env_list_add(struct ul_env_list
*ls0
, const char *str
)
63 struct ul_env_list
*ls
;
71 p
= malloc(sizeof(struct ul_env_list
) + sz
);
73 ls
= (struct ul_env_list
*) p
;
74 p
+= sizeof(struct ul_env_list
);
83 * Use setenv() for all stuff in @ls.
85 * It would be possible to use putenv(), but we want to keep @ls free()-able.
87 int env_list_setenv(struct ul_env_list
*ls
)
91 while (ls
&& rc
== 0) {
93 char *val
= strchr(ls
->env
, '=');
97 rc
= setenv(ls
->env
, val
+ 1, 0);
105 void env_list_free(struct ul_env_list
*ls
)
108 struct ul_env_list
*x
= ls
;
115 * Removes unwanted variables from environ[]. If @ls is not NULL than stores
116 * unwnated variables to the list.
118 void __sanitize_env(struct ul_env_list
**org
)
120 char **envp
= environ
;
125 for (cur
= envp
; *cur
; cur
++)
128 for (cur
= envp
; *cur
; cur
++) {
129 for (bad
= forbid
; *bad
; bad
++) {
130 if (strncmp(*cur
, *bad
, strlen(*bad
)) == 0) {
132 *org
= env_list_add(*org
, *cur
);
133 last
= remote_entry(envp
, cur
- envp
, last
);
140 for (cur
= envp
; *cur
; cur
++) {
141 for (bad
= noslash
; *bad
; bad
++) {
142 if (strncmp(*cur
, *bad
, strlen(*bad
)) != 0)
144 if (!strchr(*cur
, '/'))
147 *org
= env_list_add(*org
, *cur
);
148 last
= remote_entry(envp
, cur
- envp
, last
);
155 void sanitize_env(void)
157 __sanitize_env(NULL
);
160 char *safe_getenv(const char *arg
)
162 uid_t ruid
= getuid();
164 if (ruid
!= 0 || (ruid
!= geteuid()) || (getgid() != getegid()))
167 if (prctl(PR_GET_DUMPABLE
, 0, 0, 0, 0) == 0)
170 #if (defined(linux) && defined(SYS_prctl))
171 if (syscall(SYS_prctl
, PR_GET_DUMPABLE
, 0, 0, 0, 0) == 0)
175 #ifdef HAVE_SECURE_GETENV
176 return secure_getenv(arg
);
177 #elif HAVE___SECURE_GETENV
178 return __secure_getenv(arg
);
190 int retval
= EXIT_SUCCESS
;
191 struct ul_env_list
*removed
= NULL
;
193 for (bad
= forbid
; *bad
; bad
++) {
195 p
= strchr(copy
, '=');
198 setenv(copy
, copy
, 1);
202 __sanitize_env(&removed
);
205 for (bad
= forbid
; *bad
; bad
++) {
207 p
= strchr(copy
, '=');
212 warnx("%s was not removed", copy
);
213 retval
= EXIT_FAILURE
;
217 /* restore removed */
218 env_list_setenv(removed
);
221 for (bad
= forbid
; *bad
; bad
++) {
223 p
= strchr(copy
, '=');
228 warnx("%s was not restored", copy
);
229 retval
= EXIT_FAILURE
;
233 env_list_free(removed
);