uwrap: Add UID_WRAPPER_ROOT=2 mode.
[uid_wrapper.git] / src / uid_wrapper.c
1 /*
2  * Copyright (c) 2009      Andrew Tridgell
3  * Copyright (c) 2011-2013 Andreas Schneider <asn@samba.org>
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 #include "config.h"
20
21 #include <errno.h>
22 #include <stdarg.h>
23 #include <stdbool.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <sys/types.h>
28 #include <unistd.h>
29 #include <grp.h>
30 #ifdef HAVE_SYS_SYSCALL_H
31 #include <sys/syscall.h>
32 #endif
33 #ifdef HAVE_SYSCALL_H
34 #include <syscall.h>
35 #endif
36 #include <dlfcn.h>
37
38 #include <pthread.h>
39
40 #ifdef HAVE_GCC_THREAD_LOCAL_STORAGE
41 # define UWRAP_THREAD __thread
42 #else
43 # define UWRAP_THREAD
44 #endif
45
46 #ifdef NDEBUG
47 #define UWRAP_DEBUG(...)
48 #else
49 #define UWRAP_DEBUG(...) fprintf(stderr, __VA_ARGS__)
50 #endif
51
52 #define UWRAP_DLIST_ADD(list,item) do { \
53         if (!(list)) { \
54                 (item)->prev    = NULL; \
55                 (item)->next    = NULL; \
56                 (list)          = (item); \
57         } else { \
58                 (item)->prev    = NULL; \
59                 (item)->next    = (list); \
60                 (list)->prev    = (item); \
61                 (list)          = (item); \
62         } \
63 } while (0)
64
65 #define UWRAP_DLIST_REMOVE(list,item) do { \
66         if ((list) == (item)) { \
67                 (list)          = (item)->next; \
68                 if (list) { \
69                         (list)->prev    = NULL; \
70                 } \
71         } else { \
72                 if ((item)->prev) { \
73                         (item)->prev->next      = (item)->next; \
74                 } \
75                 if ((item)->next) { \
76                         (item)->next->prev      = (item)->prev; \
77                 } \
78         } \
79         (item)->prev    = NULL; \
80         (item)->next    = NULL; \
81 } while (0)
82
83 #define LIBC_NAME "libc.so"
84
85 struct uwrap_libc_fns {
86         int (*_libc_setuid)(uid_t uid);
87         uid_t (*_libc_getuid)(void);
88
89 #ifdef HAVE_SETEUID
90         int (*_libc_seteuid)(uid_t euid);
91 #endif
92 #ifdef HAVE_SETREUID
93         int (*_libc_setreuid)(uid_t ruid, uid_t euid);
94 #endif
95 #ifdef HAVE_SETREUID
96         int (*_libc_setresuid)(uid_t ruid, uid_t euid, uid_t suid);
97 #endif
98         uid_t (*_libc_geteuid)(void);
99
100         int (*_libc_setgid)(gid_t gid);
101         gid_t (*_libc_getgid)(void);
102 #ifdef HAVE_SETEGID
103         int (*_libc_setegid)(uid_t egid);
104 #endif
105 #ifdef HAVE_SETREGID
106         int (*_libc_setregid)(uid_t rgid, uid_t egid);
107 #endif
108 #ifdef HAVE_SETREGID
109         int (*_libc_setresgid)(uid_t rgid, uid_t egid, uid_t sgid);
110 #endif
111         gid_t (*_libc_getegid)(void);
112         int (*_libc_getgroups)(int size, gid_t list[]);
113         int (*_libc_setgroups)(size_t size, const gid_t *list);
114 #ifdef HAVE_SYSCALL
115         long int (*_libc_syscall)(long int sysno, ...);
116 #endif
117 };
118
119 /*
120  * We keep the virtualised euid/egid/groups information here
121  */
122 struct uwrap_thread {
123         pthread_t tid;
124         bool dead;
125
126         uid_t ruid;
127         uid_t euid;
128         uid_t suid;
129
130         gid_t rgid;
131         gid_t egid;
132         gid_t sgid;
133
134         gid_t *groups;
135         int ngroups;
136
137         struct uwrap_thread *next;
138         struct uwrap_thread *prev;
139 };
140
141 struct uwrap {
142         struct {
143                 void *handle;
144                 struct uwrap_libc_fns fns;
145         } libc;
146
147         bool initialised;
148         bool enabled;
149
150         uid_t myuid;
151         uid_t mygid;
152
153         struct uwrap_thread *ids;
154 };
155
156 static struct uwrap uwrap;
157
158 /* Shortcut to the list item */
159 static UWRAP_THREAD struct uwrap_thread *uwrap_tls_id;
160
161 /* The mutex or accessing the id */
162 static pthread_mutex_t uwrap_id_mutex = PTHREAD_MUTEX_INITIALIZER;
163
164 static void *uwrap_libc_fn(struct uwrap *u, const char *fn_name)
165 {
166         void *func;
167
168         if (u->libc.handle == NULL) {
169                 return NULL;
170         }
171
172         func = dlsym(u->libc.handle, fn_name);
173         if (func == NULL) {
174                 printf("Failed to find %s in %s: %s\n",
175                                 fn_name, LIBC_NAME, dlerror());
176                 exit(-1);
177         }
178
179         return func;
180 }
181
182 static void uwrap_libc_init(struct uwrap *u)
183 {
184         unsigned int i;
185         int flags = RTLD_LAZY;
186
187 #ifdef RTLD_DEEPBIND
188         flags |= RTLD_DEEPBIND;
189 #endif
190
191         for (u->libc.handle = NULL, i = 10; u->libc.handle == NULL; i--) {
192                 char soname[256] = {0};
193
194                 snprintf(soname, sizeof(soname), "%s.%u", LIBC_NAME, i);
195                 u->libc.handle = dlopen(soname, flags);
196         }
197
198         if (u->libc.handle == NULL) {
199                 printf("Failed to dlopen %s.%u: %s\n", LIBC_NAME, i, dlerror());
200                 exit(-1);
201         }
202
203         *(void **) (&u->libc.fns._libc_setuid) = uwrap_libc_fn(u, "setuid");
204         *(void **) (&u->libc.fns._libc_getuid) = uwrap_libc_fn(u, "getuid");
205
206 #ifdef HAVE_SETEUID
207         *(void **) (&u->libc.fns._libc_seteuid) = uwrap_libc_fn(u, "seteuid");
208 #endif
209 #ifdef HAVE_SETREUID
210         *(void **) (&u->libc.fns._libc_setreuid) = uwrap_libc_fn(u, "setreuid");
211 #endif
212 #ifdef HAVE_SETRESUID
213         *(void **) (&u->libc.fns._libc_setresuid) = uwrap_libc_fn(u, "setresuid");
214 #endif
215         *(void **) (&u->libc.fns._libc_geteuid) = uwrap_libc_fn(u, "geteuid");
216
217         *(void **) (&u->libc.fns._libc_setgid) = uwrap_libc_fn(u, "setgid");
218         *(void **) (&u->libc.fns._libc_getgid) = uwrap_libc_fn(u, "getgid");
219 #ifdef HAVE_SETEGID
220         *(void **) (&u->libc.fns._libc_setegid) = uwrap_libc_fn(u, "setegid");
221 #endif
222 #ifdef HAVE_SETREGID
223         *(void **) (&u->libc.fns._libc_setregid) = uwrap_libc_fn(u, "setregid");
224 #endif
225 #ifdef HAVE_SETRESGID
226         *(void **) (&u->libc.fns._libc_setresgid) = uwrap_libc_fn(u, "setresgid");
227 #endif
228         *(void **) (&u->libc.fns._libc_getegid) = uwrap_libc_fn(u, "getegid");
229         *(void **) (&u->libc.fns._libc_getgroups) = uwrap_libc_fn(u, "getgroups");
230         *(void **) (&u->libc.fns._libc_setgroups) = uwrap_libc_fn(u, "setgroups");
231         *(void **) (&u->libc.fns._libc_getuid) = uwrap_libc_fn(u, "getuid");
232         *(void **) (&u->libc.fns._libc_getgid) = uwrap_libc_fn(u, "getgid");
233 #ifdef HAVE_SYSCALL
234         *(void **) (&u->libc.fns._libc_syscall) = uwrap_libc_fn(u, "syscall");
235 #endif
236 }
237
238 static struct uwrap_thread *find_uwrap_id(pthread_t tid)
239 {
240         struct uwrap_thread *id;
241
242         for (id = uwrap.ids; id; id = id->next) {
243                 if (pthread_equal(id->tid, tid)) {
244                         return id;
245                 }
246         }
247
248         return NULL;
249 }
250
251 static int uwrap_new_id(pthread_t tid, bool do_alloc)
252 {
253         struct uwrap_thread *id = uwrap_tls_id;
254
255         if (do_alloc) {
256                 id = malloc(sizeof(struct uwrap_thread));
257                 if (id == NULL) {
258                         errno = ENOMEM;
259                         return -1;
260                 }
261         }
262
263         id->tid = tid;
264         id->dead = false;
265
266         id->ruid = id->euid = id->suid = uwrap.myuid;
267         id->rgid = id->egid = id->sgid = uwrap.mygid;
268
269         id->ngroups = 1;
270         id->groups = malloc(sizeof(gid_t) * id->ngroups);
271         id->groups[0] = uwrap.mygid;
272
273         if (do_alloc) {
274                 UWRAP_DLIST_ADD(uwrap.ids, id);
275                 uwrap_tls_id = id;
276         }
277
278         return 0;
279 }
280
281 static void uwrap_init(void)
282 {
283         const char *env = getenv("UID_WRAPPER");
284         pthread_t tid = pthread_self();
285
286
287
288         if (uwrap.initialised) {
289                 struct uwrap_thread *id = uwrap_tls_id;
290                 int rc;
291
292                 if (id != NULL) {
293                         return;
294                 }
295
296                 pthread_mutex_lock(&uwrap_id_mutex);
297                 id = find_uwrap_id(tid);
298                 if (id == NULL) {
299                         rc = uwrap_new_id(tid, 1);
300                         if (rc < 0) {
301                                 exit(-1);
302                         }
303                 } else {
304                         /* We reuse an old thread id */
305                         uwrap_tls_id = id;
306
307                         uwrap_new_id(tid, 0);
308                 }
309                 pthread_mutex_unlock(&uwrap_id_mutex);
310
311                 return;
312         }
313
314         pthread_mutex_lock(&uwrap_id_mutex);
315
316         uwrap_libc_init(&uwrap);
317
318         uwrap.initialised = true;
319         uwrap.enabled = false;
320
321         if (env != NULL && env[0] == '1') {
322                 const char *root = getenv("UID_WRAPPER_ROOT");
323                 int rc;
324
325                 /* put us in one group */
326                 if (root != NULL && root[0] == '1') {
327                         uwrap.myuid = 0;
328                         uwrap.mygid = 0;
329                 } else {
330                         uwrap.myuid = uwrap.libc.fns._libc_geteuid();
331                         uwrap.mygid = uwrap.libc.fns._libc_getegid();
332                 }
333
334                 rc = uwrap_new_id(tid, 1);
335                 if (rc < 0) {
336                         exit(-1);
337                 }
338
339                 uwrap.enabled = true;
340         }
341
342         pthread_mutex_unlock(&uwrap_id_mutex);
343 }
344
345 static int uwrap_enabled(void)
346 {
347         uwrap_init();
348
349         return uwrap.enabled ? 1 : 0;
350 }
351
352 static int uwrap_setresuid_thread(uid_t ruid, uid_t euid, uid_t suid)
353 {
354         struct uwrap_thread *id = uwrap_tls_id;
355
356         if (ruid == (uid_t)-1 && euid == (uid_t)-1 && suid == (uid_t)-1) {
357                 errno = EINVAL;
358                 return -1;
359         }
360
361         pthread_mutex_lock(&uwrap_id_mutex);
362         if (ruid != (uid_t)-1) {
363                 id->ruid = ruid;
364         }
365
366         if (euid != (uid_t)-1) {
367                 id->euid = euid;
368         }
369
370         if (suid != (uid_t)-1) {
371                 id->suid = suid;
372         }
373         pthread_mutex_unlock(&uwrap_id_mutex);
374
375         return 0;
376 }
377
378 static int uwrap_setresuid(uid_t ruid, uid_t euid, uid_t suid)
379 {
380         struct uwrap_thread *id;
381
382         if (ruid == (uid_t)-1 && euid == (uid_t)-1 && suid == (uid_t)-1) {
383                 errno = EINVAL;
384                 return -1;
385         }
386
387         pthread_mutex_lock(&uwrap_id_mutex);
388         for (id = uwrap.ids; id; id = id->next) {
389                 if (id->dead) {
390                         continue;
391                 }
392
393                 if (ruid != (uid_t)-1) {
394                         id->ruid = ruid;
395                 }
396
397                 if (euid != (uid_t)-1) {
398                         id->euid = euid;
399                 }
400
401                 if (suid != (uid_t)-1) {
402                         id->suid = suid;
403                 }
404         }
405         pthread_mutex_unlock(&uwrap_id_mutex);
406
407         return 0;
408 }
409
410 /*
411  * SETUID
412  */
413 int setuid(uid_t uid)
414 {
415         if (!uwrap_enabled()) {
416                 return uwrap.libc.fns._libc_setuid(uid);
417         }
418
419         return uwrap_setresuid(uid, -1, -1);
420 }
421
422 #ifdef HAVE_SETEUID
423 int seteuid(uid_t euid)
424 {
425         if (euid == (uid_t)-1) {
426                 errno = EINVAL;
427                 return -1;
428         }
429
430         if (!uwrap_enabled()) {
431                 return uwrap.libc.fns._libc_seteuid(euid);
432         }
433
434         return uwrap_setresuid(-1, euid, -1);
435 }
436 #endif
437
438 #ifdef HAVE_SETREUID
439 int setreuid(uid_t ruid, uid_t euid)
440 {
441         if (ruid == (uid_t)-1 && euid == (uid_t)-1) {
442                 errno = EINVAL;
443                 return -1;
444         }
445
446         if (!uwrap_enabled()) {
447                 return uwrap.libc.fns._libc_setreuid(ruid, euid);
448         }
449
450         return uwrap_setresuid(ruid, euid, -1);
451 }
452 #endif
453
454 #ifdef HAVE_SETRESUID
455 int setresuid(uid_t ruid, uid_t euid, uid_t suid)
456 {
457         if (!uwrap_enabled()) {
458                 return uwrap.libc.fns._libc_setresuid(ruid, euid, suid);
459         }
460
461         return uwrap_setresuid(ruid, euid, suid);
462 }
463 #endif
464
465 /*
466  * GETUID
467  */
468 static uid_t uwrap_getuid(void)
469 {
470         struct uwrap_thread *id = uwrap_tls_id;
471         uid_t uid;
472
473         pthread_mutex_lock(&uwrap_id_mutex);
474         uid = id->ruid;
475         pthread_mutex_unlock(&uwrap_id_mutex);
476
477         return uid;
478 }
479
480 uid_t getuid(void)
481 {
482         if (!uwrap_enabled()) {
483                 return uwrap.libc.fns._libc_getuid();
484         }
485
486         return uwrap_getuid();
487 }
488
489 /*
490  * GETEUID
491  */
492 static uid_t uwrap_geteuid(void)
493 {
494         const char *env = getenv("UID_WRAPPER_ROOT");
495         struct uwrap_thread *id = uwrap_tls_id;
496         uid_t uid;
497
498         pthread_mutex_lock(&uwrap_id_mutex);
499         uid = id->euid;
500         pthread_mutex_unlock(&uwrap_id_mutex);
501
502         /* Disable root and return myuid */
503         if (env != NULL && env[0] == '2') {
504                 uid = uwrap.myuid;
505         }
506
507         return uid;
508 }
509
510 uid_t geteuid(void)
511 {
512         if (!uwrap_enabled()) {
513                 return uwrap.libc.fns._libc_geteuid();
514         }
515
516         return uwrap_geteuid();
517 }
518
519 static int uwrap_setresgid_thread(gid_t rgid, gid_t egid, gid_t sgid)
520 {
521         struct uwrap_thread *id = uwrap_tls_id;
522
523         if (rgid == (gid_t)-1 && egid == (gid_t)-1 && sgid == (gid_t)-1) {
524                 errno = EINVAL;
525                 return -1;
526         }
527
528         pthread_mutex_lock(&uwrap_id_mutex);
529         if (rgid != (gid_t)-1) {
530                 id->rgid = rgid;
531         }
532
533         if (egid != (gid_t)-1) {
534                 id->egid = egid;
535         }
536
537         if (sgid != (gid_t)-1) {
538                 id->sgid = sgid;
539         }
540         pthread_mutex_unlock(&uwrap_id_mutex);
541
542         return 0;
543 }
544
545 static int uwrap_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
546 {
547         struct uwrap_thread *id;
548
549         if (rgid == (gid_t)-1 && egid == (gid_t)-1 && sgid == (gid_t)-1) {
550                 errno = EINVAL;
551                 return -1;
552         }
553
554         pthread_mutex_lock(&uwrap_id_mutex);
555         for (id = uwrap.ids; id; id = id->next) {
556                 if (id->dead) {
557                         continue;
558                 }
559
560                 if (rgid != (gid_t)-1) {
561                         id->rgid = rgid;
562                 }
563
564                 if (egid != (gid_t)-1) {
565                         id->egid = egid;
566                 }
567
568                 if (sgid != (gid_t)-1) {
569                         id->sgid = sgid;
570                 }
571         }
572         pthread_mutex_unlock(&uwrap_id_mutex);
573
574         return 0;
575 }
576
577 /*
578  * SETGID
579  */
580 int setgid(gid_t gid)
581 {
582         if (!uwrap_enabled()) {
583                 return uwrap.libc.fns._libc_setgid(gid);
584         }
585
586         return uwrap_setresgid(gid, -1, -1);
587 }
588
589 #ifdef HAVE_SETEGID
590 int setegid(gid_t egid)
591 {
592         if (!uwrap_enabled()) {
593                 return uwrap.libc.fns._libc_setegid(egid);
594         }
595
596         return uwrap_setresgid(-1, egid, -1);
597 }
598 #endif
599
600 #ifdef HAVE_SETREGID
601 int setregid(gid_t rgid, gid_t egid)
602 {
603         if (!uwrap_enabled()) {
604                 return uwrap.libc.fns._libc_setregid(rgid, egid);
605         }
606
607         return uwrap_setresgid(rgid, egid, -1);
608 }
609 #endif
610
611 #ifdef HAVE_SETRESGID
612 int setresgid(gid_t rgid, gid_t egid, gid_t sgid)
613 {
614         if (!uwrap_enabled()) {
615                 return uwrap.libc.fns._libc_setregid(rgid, egid, sgid);
616         }
617
618         return uwrap_setresgid(rgid, egid, sgid);
619 }
620 #endif
621
622 /*
623  * GETGID
624  */
625 static gid_t uwrap_getgid(void)
626 {
627         struct uwrap_thread *id = uwrap_tls_id;
628         gid_t gid;
629
630         pthread_mutex_lock(&uwrap_id_mutex);
631         gid = id->rgid;
632         pthread_mutex_unlock(&uwrap_id_mutex);
633
634         return gid;
635 }
636
637 gid_t getgid(void)
638 {
639         if (!uwrap_enabled()) {
640                 return uwrap.libc.fns._libc_getgid();
641         }
642
643         return uwrap_getgid();
644 }
645
646 /*
647  * GETEGID
648  */
649 static uid_t uwrap_getegid(void)
650 {
651         struct uwrap_thread *id = uwrap_tls_id;
652         gid_t gid;
653
654         pthread_mutex_lock(&uwrap_id_mutex);
655         gid = id->egid;
656         pthread_mutex_unlock(&uwrap_id_mutex);
657
658         return gid;
659 }
660
661 uid_t getegid(void)
662 {
663         if (!uwrap_enabled()) {
664                 return uwrap.libc.fns._libc_getegid();
665         }
666
667         return uwrap_getegid();
668 }
669
670 static int uwrap_setgroups_thread(size_t size, const gid_t *list)
671 {
672         struct uwrap_thread *id = uwrap_tls_id;
673         int rc = -1;
674
675         pthread_mutex_lock(&uwrap_id_mutex);
676         free(id->groups);
677         id->groups = NULL;
678         id->ngroups = 0;
679
680         if (size != 0) {
681                 id->groups = malloc(sizeof(gid_t) * size);
682                 if (id->groups == NULL) {
683                         errno = ENOMEM;
684                         goto out;
685                 }
686                 id->ngroups = size;
687                 memcpy(id->groups, list, size * sizeof(gid_t));
688         }
689
690         rc = 0;
691 out:
692         pthread_mutex_unlock(&uwrap_id_mutex);
693
694         return rc;
695 }
696
697 static int uwrap_setgroups(size_t size, const gid_t *list)
698 {
699         struct uwrap_thread *id;
700         int rc = -1;
701
702         pthread_mutex_lock(&uwrap_id_mutex);
703         for (id = uwrap.ids; id; id = id->next) {
704                 free(id->groups);
705                 id->groups = NULL;
706                 id->ngroups = 0;
707
708                 if (size != 0) {
709                         id->groups = malloc(sizeof(gid_t) * size);
710                         if (id->groups == NULL) {
711                                 errno = ENOMEM;
712                                 goto out;
713                         }
714                         id->ngroups = size;
715                         memcpy(id->groups, list, size * sizeof(gid_t));
716                 }
717         }
718
719         rc = 0;
720 out:
721         pthread_mutex_unlock(&uwrap_id_mutex);
722
723         return rc;
724 }
725
726 int setgroups(size_t size, const gid_t *list)
727 {
728         if (!uwrap_enabled()) {
729                 return uwrap.libc.fns._libc_setgroups(size, list);
730         }
731
732         return uwrap_setgroups(size, list);
733 }
734
735 static int uwrap_getgroups(int size, gid_t *list)
736 {
737         struct uwrap_thread *id = uwrap_tls_id;
738         int ngroups;
739
740         pthread_mutex_lock(&uwrap_id_mutex);
741         ngroups = id->ngroups;
742
743         if (size > ngroups) {
744                 size = ngroups;
745         }
746         if (size == 0) {
747                 goto out;
748         }
749         if (size < ngroups) {
750                 errno = EINVAL;
751                 ngroups = -1;
752         }
753         memcpy(list, id->groups, size * sizeof(gid_t));
754
755 out:
756         pthread_mutex_unlock(&uwrap_id_mutex);
757
758         return ngroups;
759 }
760
761 int getgroups(int size, gid_t *list)
762 {
763         if (!uwrap_enabled()) {
764                 return uwrap.libc.fns._libc_getgroups(size, list);
765         }
766
767         return uwrap_getgroups(size, list);
768 }
769
770 static long int libc_vsyscall(long int sysno, va_list va)
771 {
772         long int args[8];
773         long int rc;
774         int i;
775
776         for (i = 0; i < 8; i++) {
777                 args[i] = va_arg(va, long int);
778         }
779
780         rc = uwrap.libc.fns._libc_syscall(sysno,
781                                           args[0],
782                                           args[1],
783                                           args[2],
784                                           args[3],
785                                           args[4],
786                                           args[5],
787                                           args[6],
788                                           args[7]);
789
790         return rc;
791 }
792
793 #if (defined(HAVE_SYS_SYSCALL_H) || defined(HAVE_SYSCALL_H)) \
794     && (defined(SYS_setreuid) || defined(SYS_setreuid32))
795 static long int uwrap_syscall (long int sysno, va_list vp)
796 {
797         long int rc;
798
799         switch (sysno) {
800                 /* gid */
801                 case SYS_getgid:
802 #ifdef HAVE_LINUX_32BIT_SYSCALLS
803                 case SYS_getgid32:
804 #endif
805                         {
806                                 rc = uwrap_getgid();
807                         }
808                         break;
809                 case SYS_getegid:
810 #ifdef HAVE_LINUX_32BIT_SYSCALLS
811                 case SYS_getegid32:
812 #endif
813                         {
814                                 rc = uwrap_getegid();
815                         }
816                         break;
817                 case SYS_setgid:
818 #ifdef HAVE_LINUX_32BIT_SYSCALLS
819                 case SYS_setgid32:
820 #endif
821                         {
822                                 gid_t gid = (gid_t) va_arg(vp, int);
823
824                                 rc = uwrap_setresgid_thread(gid, -1, -1);
825                         }
826                         break;
827                 case SYS_setregid:
828 #ifdef HAVE_LINUX_32BIT_SYSCALLS
829                 case SYS_setregid32:
830 #endif
831                         {
832                                 uid_t rgid = (uid_t) va_arg(vp, int);
833                                 uid_t egid = (uid_t) va_arg(vp, int);
834
835                                 rc = uwrap_setresgid_thread(rgid, egid, -1);
836                         }
837                         break;
838                 case SYS_setresgid:
839 #ifdef HAVE_LINUX_32BIT_SYSCALLS
840                 case SYS_setresgid32:
841 #endif
842                         {
843                                 uid_t rgid = (uid_t) va_arg(vp, int);
844                                 uid_t egid = (uid_t) va_arg(vp, int);
845                                 uid_t sgid = (uid_t) va_arg(vp, int);
846
847                                 rc = uwrap_setresgid_thread(rgid, egid, sgid);
848                         }
849                         break;
850
851                 /* uid */
852                 case SYS_getuid:
853 #ifdef HAVE_LINUX_32BIT_SYSCALLS
854                 case SYS_getuid32:
855 #endif
856                         {
857                                 rc = uwrap_getuid();
858                         }
859                         break;
860                 case SYS_geteuid:
861 #ifdef HAVE_LINUX_32BIT_SYSCALLS
862                 case SYS_geteuid32:
863 #endif
864                         {
865                                 rc = uwrap_geteuid();
866                         }
867                         break;
868                 case SYS_setuid:
869 #ifdef HAVE_LINUX_32BIT_SYSCALLS
870                 case SYS_setuid32:
871 #endif
872                         {
873                                 uid_t uid = (uid_t) va_arg(vp, int);
874
875                                 rc = uwrap_setresuid_thread(uid, -1, -1);
876                         }
877                         break;
878                 case SYS_setreuid:
879 #ifdef HAVE_LINUX_32BIT_SYSCALLS
880                 case SYS_setreuid32:
881 #endif
882                         {
883                                 uid_t ruid = (uid_t) va_arg(vp, int);
884                                 uid_t euid = (uid_t) va_arg(vp, int);
885
886                                 rc = uwrap_setresuid_thread(ruid, euid, -1);
887                         }
888                         break;
889                 case SYS_setresuid:
890 #ifdef HAVE_LINUX_32BIT_SYSCALLS
891                 case SYS_setresuid32:
892 #endif
893                         {
894                                 uid_t ruid = (uid_t) va_arg(vp, int);
895                                 uid_t euid = (uid_t) va_arg(vp, int);
896                                 uid_t suid = (uid_t) va_arg(vp, int);
897
898                                 rc = uwrap_setresuid_thread(ruid, euid, suid);
899                         }
900                         break;
901
902                 /* groups */
903                 case SYS_setgroups:
904 #ifdef HAVE_LINUX_32BIT_SYSCALLS
905                 case SYS_setgroups32:
906 #endif
907                         {
908                                 size_t size = (size_t) va_arg(vp, size_t);
909                                 gid_t *list = (gid_t *) va_arg(vp, int *);
910
911                                 rc = uwrap_setgroups_thread(size, list);
912                         }
913                         break;
914                 default:
915                         UWRAP_DEBUG("UID_WRAPPER calling non-wrapped syscall "
916                                     "%lu\n", sysno);
917
918                         rc = libc_vsyscall(sysno, vp);
919                         break;
920         }
921
922         return rc;
923 }
924
925 #ifdef HAVE_SYSCALL
926 long int syscall (long int sysno, ...)
927 {
928         long int rc;
929         va_list va;
930
931         va_start(va, sysno);
932
933         if (!uwrap_enabled()) {
934                 rc = libc_vsyscall(sysno, va);
935                 va_end(va);
936                 return rc;
937         }
938
939         rc = uwrap_syscall(sysno, va);
940         va_end(va);
941
942         return rc;
943 }
944 #endif /* HAVE_SYSCALL */
945 #endif /* HAVE_SYS_SYSCALL_H || HAVE_SYSCALL_H */