lib/roken: is_special_auxv_p test for AT_HWCAP2
[heimdal.git] / lib / roken / test-auxval.c
blob69ab359920bdc84cbf085daa82b659f8af1c652c
1 /*
2 * Copyright (c) 1999 - 2004 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
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
31 * SUCH DAMAGE.
34 #include <config.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <err.h>
39 #include <fcntl.h>
40 #include <stdio.h>
41 #include <string.h>
42 #include <unistd.h>
43 #include "roken.h"
44 #include "getauxval.h"
46 static void
47 check_secure_getenv(char **env)
49 size_t i;
50 char *v;
52 for (i = 0; env[i] != NULL; i++) {
53 if (strchr(env[i], '=') == NULL)
54 continue;
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()");
62 free(v);
63 return;
67 static void
68 inject_suid(int suid)
70 #if defined(AT_SECURE) || (defined(AT_EUID) && defined(AT_RUID) && defined(AT_EGID) && defined(AT_RGID))
71 auxv_t e;
72 #ifdef AT_SECURE
73 unsigned long secure = suid ? 1 : 0;
74 #endif
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 */
79 e.a_un.a_val = 1000;
80 e.a_type = AT_UID;
81 if ((errno = rk_injectauxv(&e)) != 0)
82 err(1, "rk_injectauxv(AT_RUID) failed");
83 e.a_type = AT_GID;
84 if ((errno = rk_injectauxv(&e)) != 0)
85 err(1, "rk_injectauxv(AT_RGID) failed");
87 /* Inject effective UID and GID */
88 e.a_un.a_val = eid;
89 e.a_type = AT_EUID;
90 if ((errno = rk_injectauxv(&e)) != 0)
91 err(1, "rk_injectauxv(AT_EUID) failed");
92 e.a_type = AT_EGID;
93 if ((errno = rk_injectauxv(&e)) != 0)
94 err(1, "rk_injectauxv(AT_RGID) failed");
95 #endif
97 #ifdef AT_SECURE
98 e.a_un.a_val = secure;
99 e.a_type = AT_SECURE;
100 if ((errno = rk_injectauxv(&e)) != 0)
101 err(1, "rk_injectauxv(AT_SECURE) failed");
102 #endif
104 return;
105 #else
106 warnx("No ELF auxv types to inject");
107 #endif
110 static
111 unsigned long
112 getprocauxval(unsigned long type)
114 const auxv_t *e;
116 if ((e = rk_getauxv(type)) == NULL) {
117 errno = ENOENT;
118 return 0;
120 return e->a_un.a_val;
123 /* returns 1 if auxval type is handled specially by libc */
124 static int
125 is_special_auxv_p(long type)
127 #ifdef AT_HWCAP
128 if (type == AT_HWCAP)
129 return 1;
130 #endif
131 #ifdef AT_HWCAP2
132 if (type == AT_HWCAP2)
133 return 1;
134 #endif
136 return 0;
140 main(int argc, char **argv, char **env)
142 unsigned long max_t = 0;
143 unsigned long a[2];
144 unsigned long v;
145 ssize_t bytes;
146 int am_suid = issuid();
147 int fd;
149 (void) argc;
150 (void) argv;
152 if (getuid() == geteuid() && getgid() == getegid()) {
153 if (issuid())
154 errx(1, "issuid() false positive? Check AT_SECURE?");
155 } else {
156 if (!issuid())
157 errx(1, "issuid() did not detect set-uid-ness!");
160 if ((fd = open("/proc/self/auxv", O_RDONLY)) == -1)
161 return 0;
164 * Check that for every ELF auxv entry in /proc/self/auxv we
165 * find the correct answer from the rk_get*auxval() functions.
167 do {
168 bytes = read(fd, a, sizeof(a));
169 if (bytes != sizeof(a)) {
170 if (bytes == -1)
171 err(1, "Error reading from /proc/self/auxv");
172 if (bytes == 0)
173 warnx("Did not see terminator in /proc/self/auxv");
174 else
175 warnx("Partial entry in /proc/self/auxv or test interrupted");
176 (void) close(fd);
177 return 1;
179 if (a[0] > max_t)
180 max_t = a[0];
181 if (a[0] == 0) {
182 if (a[1] != 0)
183 warnx("AT_NULL with non-zero value %lu?!", a[1]);
184 continue;
185 } else if (is_special_auxv_p(a[0]))
186 continue;
188 errno = EACCES;
190 if ((v = rk_getauxval(a[0])) != a[1])
191 errx(1, "rk_getauxval(%lu) should have been %lu, was %lu",
192 a[0], a[1], v);
193 if (errno != EACCES)
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",
198 a[0], a[1], v);
199 if (errno != EACCES)
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);
205 (void) close(fd);
206 if (max_t == 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 "
209 "rk_getauxval()");
210 return 0;
213 errno = EACCES;
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);
217 if (errno != ENOENT)
218 errx(1, "rk_getauxval((max_type_seen = %lu) + 1) did not set "
219 "errno = ENOENT!", max_t);
221 errno = EACCES;
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);
225 if (errno != ENOENT)
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);
235 return 0;