2 * Copyright (c) 1999 - 2004 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 #include <sys/types.h>
44 #include "getauxval.h"
47 check_secure_getenv(char **env
)
52 for (i
= 0; env
[i
] != NULL
; i
++) {
53 if (strchr(env
[i
], '=') == NULL
)
55 if ((v
= strdup(env
[i
])) == NULL
)
56 err(1, "could not allocate copy of %s", env
[i
]);
57 *strchr(v
, '=') = '\0';
58 if (issuid() && rk_secure_getenv(v
) != NULL
)
59 err(1, "rk_secure_getenv() returned non-NULL when issuid()!");
60 if (!issuid() && rk_secure_getenv(v
) == NULL
)
61 err(1, "rk_secure_getenv() returned NULL when !issuid()");
70 #if defined(AT_SECURE) || (defined(AT_EUID) && defined(AT_RUID) && defined(AT_EGID) && defined(AT_RGID))
73 unsigned long secure
= suid
? 1 : 0;
75 #if defined(AT_EUID) && defined(AT_RUID) && defined(AT_EGID) && defined(AT_RGID)
76 unsigned long eid
= suid
? 0 : 1000;
78 /* Inject real UID and GID */
81 if ((errno
= rk_injectauxv(&e
)) != 0)
82 err(1, "rk_injectauxv(AT_RUID) failed");
84 if ((errno
= rk_injectauxv(&e
)) != 0)
85 err(1, "rk_injectauxv(AT_RGID) failed");
87 /* Inject effective UID and GID */
90 if ((errno
= rk_injectauxv(&e
)) != 0)
91 err(1, "rk_injectauxv(AT_EUID) failed");
93 if ((errno
= rk_injectauxv(&e
)) != 0)
94 err(1, "rk_injectauxv(AT_RGID) failed");
98 e
.a_un
.a_val
= secure
;
100 if ((errno
= rk_injectauxv(&e
)) != 0)
101 err(1, "rk_injectauxv(AT_SECURE) failed");
106 warnx("No ELF auxv types to inject");
112 getprocauxval(unsigned long type
)
116 if ((e
= rk_getauxv(type
)) == NULL
) {
120 return e
->a_un
.a_val
;
123 /* returns 1 if auxval type is handled specially by libc */
125 is_special_auxv_p(long type
)
128 if (type
== AT_HWCAP
)
132 if (type
== AT_HWCAP2
)
140 main(int argc
, char **argv
, char **env
)
142 unsigned long max_t
= 0;
146 int am_suid
= issuid();
152 if (getuid() == geteuid() && getgid() == getegid()) {
154 errx(1, "issuid() false positive? Check AT_SECURE?");
157 errx(1, "issuid() did not detect set-uid-ness!");
160 if ((fd
= open("/proc/self/auxv", O_RDONLY
)) == -1)
164 * Check that for every ELF auxv entry in /proc/self/auxv we
165 * find the correct answer from the rk_get*auxval() functions.
168 bytes
= read(fd
, a
, sizeof(a
));
169 if (bytes
!= sizeof(a
)) {
171 err(1, "Error reading from /proc/self/auxv");
173 warnx("Did not see terminator in /proc/self/auxv");
175 warnx("Partial entry in /proc/self/auxv or test interrupted");
183 warnx("AT_NULL with non-zero value %lu?!", a
[1]);
185 } else if (is_special_auxv_p(a
[0]))
190 if ((v
= rk_getauxval(a
[0])) != a
[1])
191 errx(1, "rk_getauxval(%lu) should have been %lu, was %lu",
194 errx(1, "rk_getauxval(%lu) did not preserve errno", a
[0]);
196 if ((v
= getprocauxval(a
[0])) != a
[1])
197 errx(1, "rk_getauxval(%lu) should have been %lu, was %lu",
200 errx(1, "rk_getauxv(%lu) did not preserve errno", a
[0]);
202 printf("auxv type %lu -> %lu\n", a
[0], a
[1]);
203 } while (a
[0] != 0 || a
[1] != 0);
207 warnx("No entries in /proc/self/auxv or it is not available on this "
208 "system or this program is linked statically; cannot test "
214 if ((v
= rk_getauxval(max_t
+ 1)) != 0)
215 errx(1, "rk_getauxval((max_type_seen = %lu) + 1) should have been "
216 "0, was %lu", max_t
, v
);
218 errx(1, "rk_getauxval((max_type_seen = %lu) + 1) did not set "
219 "errno = ENOENT!", max_t
);
222 if ((v
= getprocauxval(max_t
+ 1)) != 0)
223 errx(1, "rk_getauxv((max_type_seen = %lu) + 1) should have been "
224 "0, was %lu", max_t
, v
);
226 errx(1, "rk_getauxv((max_type_seen = %lu) + 1) did not set "
227 "errno = ENOENT!", max_t
);
229 check_secure_getenv(env
);
230 inject_suid(!am_suid
);
231 if ((am_suid
&& issuid()) || (!am_suid
&& !issuid()))
232 errx(1, "rk_injectprocauxv() failed");
233 check_secure_getenv(env
);