f45cd146210ec8801d0e76729b02993c41d04503
[uid_wrapper.git] / tests / test_glibc_thread_support.c
1 #include "config.h"
2
3 #include <stdarg.h>
4 #include <stddef.h>
5 #include <setjmp.h>
6 #include <cmocka.h>
7
8 #include <pthread.h>
9
10 #include <stdlib.h>
11 #include <sys/types.h>
12 #include <sys/stat.h>
13 #include <unistd.h>
14
15 #ifdef HAVE_SYS_SYSCALL_H
16 #include <sys/syscall.h>
17 #endif
18 #ifdef HAVE_SYSCALL_H
19 #include <syscall.h>
20 #endif
21
22 #define NUM_THREADS 3
23
24 struct parm {
25         int id;
26         int ready;
27 };
28
29 pthread_mutex_t msg_mutex = PTHREAD_MUTEX_INITIALIZER;
30
31 static void *syscall_setreuid(void *arg)
32 {
33         long int rc;
34         uid_t u;
35
36         (void) arg; /* unused */
37
38         rc = syscall(SYS_setreuid, -1, 0);
39         assert_int_equal(rc, 0);
40
41         u = geteuid();
42         assert_int_equal(u, 0);
43
44         return NULL;
45 }
46
47 static void test_syscall_setreuid(void **state)
48 {
49         pthread_attr_t pthread_custom_attr;
50         pthread_t threads[NUM_THREADS];
51         int i;
52
53         (void) state; /* unused */
54
55         pthread_attr_init(&pthread_custom_attr);
56
57         for (i = 0; i < NUM_THREADS; i++) {
58                 pthread_create(&threads[i],
59                                &pthread_custom_attr,
60                                syscall_setreuid,
61                                NULL);
62         }
63
64         for (i = 0; i < NUM_THREADS; i++) {
65                 pthread_join(threads[i], NULL);
66         }
67
68         pthread_attr_destroy(&pthread_custom_attr);
69 }
70
71 static void *sync_setreuid(void *arg)
72 {
73         struct parm *p = (struct parm *)arg;
74         uid_t u;
75
76         syscall_setreuid(arg);
77
78         p->ready = 1;
79
80         pthread_mutex_lock(&msg_mutex);
81
82         u = geteuid();
83         assert_int_equal(u, 42);
84
85         pthread_mutex_unlock(&msg_mutex);
86
87         return NULL;
88 }
89
90 static void test_sync_setreuid(void **state)
91 {
92         pthread_attr_t pthread_custom_attr;
93         pthread_t threads[NUM_THREADS];
94         struct parm *p;
95         int rc;
96         int i;
97
98         (void) state; /* unused */
99
100         pthread_attr_init(&pthread_custom_attr);
101
102         p = malloc(NUM_THREADS * sizeof(struct parm));
103         assert_non_null(p);
104
105         pthread_mutex_lock(&msg_mutex);
106
107         for (i = 0; i < NUM_THREADS; i++) {
108                 p[i].id = i;
109                 p[i].ready = 0;
110
111                 pthread_create(&threads[i],
112                                &pthread_custom_attr,
113                                sync_setreuid,
114                                (void *)&p[i]);
115         }
116
117         /* wait for the reads to set euid to 0 */
118         for (i = 0; i < NUM_THREADS; i++) {
119                 while (p[i].ready != 1) {
120                         sleep(1);
121                 }
122         }
123
124         rc = setreuid(-1, 42);
125         assert_int_equal(rc, 0);
126
127         pthread_mutex_unlock(&msg_mutex);
128
129         for (i = 0; i < NUM_THREADS; i++) {
130                 pthread_join(threads[i], NULL);
131         }
132
133         pthread_attr_destroy(&pthread_custom_attr);
134         free(p);
135 }
136
137 int main(void) {
138         int rc;
139
140         const UnitTest tests[] = {
141                 unit_test(test_syscall_setreuid),
142                 unit_test(test_sync_setreuid),
143         };
144
145         rc = run_tests(tests);
146
147         return rc;
148 }