1 #ifdef HAVE_CONFIG_H
2 # include "config.h"
3 #endif
4 #include <assert.h>
5 #include <stdlib.h>
6 #include <unistd.h>
7 #include <fcntl.h>
8 #include <sys/syscall.h>
9 
10 int
main(void)11 main(void)
12 {
13 #if defined(__NR_getuid) \
14  && defined(__NR_setuid) \
15  && defined(__NR_getresuid) \
16  && defined(__NR_setreuid) \
17  && defined(__NR_setresuid) \
18  && defined(__NR_fchown) \
19  && defined(__NR_getgroups) \
20  \
21  && defined(__NR_getuid32) \
22  && defined(__NR_setuid32) \
23  && defined(__NR_getresuid32) \
24  && defined(__NR_setreuid32) \
25  && defined(__NR_setresuid32) \
26  && defined(__NR_fchown32) \
27  && defined(__NR_getgroups32) \
28  \
29  && __NR_getuid != __NR_getuid32 \
30  && __NR_setuid != __NR_setuid32 \
31  && __NR_getresuid != __NR_getresuid32 \
32  && __NR_setreuid != __NR_setreuid32 \
33  && __NR_setresuid != __NR_setresuid32 \
34  && __NR_fchown != __NR_fchown32 \
35  && __NR_getgroups != __NR_getgroups32 \
36  /**/
37 	int uid;
38 	int size;
39 	int *list = 0;
40 
41 	uid = syscall(__NR_getuid);
42 
43 	(void) close(0);
44 	if (open("/proc/sys/kernel/overflowuid", O_RDONLY) == 0) {
45 		/* we trust the kernel */
46 		char buf[sizeof(int)*3];
47 		int n = read(0, buf, sizeof(buf) - 1);
48 		if (n) {
49 			buf[n] = '\0';
50 			n = atoi(buf);
51 			if (uid == n)
52 				return 77;
53 		}
54 		close(0);
55 	}
56 
57 	assert(syscall(__NR_setuid, uid) == 0);
58 	{
59 		/*
60 		 * uids returned by getresuid should be ignored
61 		 * to avoid 16bit vs 32bit issues.
62 		 */
63 		int r, e, s;
64 		assert(syscall(__NR_getresuid, &r, &e, &s) == 0);
65 	}
66 	assert(syscall(__NR_setreuid, -1, 0xffff) == 0);
67 	assert(syscall(__NR_setresuid, uid, -1, 0xffff) == 0);
68 	assert(syscall(__NR_fchown, 1, -1, 0xffff) == 0);
69 	assert((size = syscall(__NR_getgroups, 0, list)) >= 0);
70 	assert(list = calloc(size + 1, sizeof(*list)));
71 	assert(syscall(__NR_getgroups, size, list) == size);
72 	return 0;
73 #else
74 	return 77;
75 #endif
76 }
77