1 /*
2 * Check decoding of setreuid/setregid/setreuid32/setregid32 syscalls.
3 *
4 * Copyright (c) 2016-2021 Dmitry V. Levin <ldv@strace.io>
5 * All rights reserved.
6 *
7 * SPDX-License-Identifier: GPL-2.0-or-later
8 */
9
10 #include <errno.h>
11 #include <stdio.h>
12 #include <unistd.h>
13
14 static int
15 ugid2int(const unsigned UGID_TYPE ugid)
16 {
17 if ((unsigned UGID_TYPE) -1U == ugid)
18 return -1;
19 else
20 return ugid;
21 }
22
23 static void
24 print_int(const unsigned int num)
25 {
26 if (num == -1U)
27 printf("-1");
28 else
29 printf("%u", num);
30 }
31
32 static int
33 num_matches_id(const unsigned int num, const unsigned int ugid)
34 {
35 return num == ugid || num == -1U;
36 }
37
38 #define PAIR(val) { val, ugid }, { ugid, val }
39
40 int
41 main(void)
42 {
43 unsigned int ugid = GETUGID;
44 CHECK_OVERFLOWUGID(ugid);
45
46 const struct {
47 const long r, e;
48 } tests[] = {
49 { ugid, ugid },
50 PAIR((unsigned long) 0xffffffff00000000ULL | ugid),
51 PAIR(-1U),
52 PAIR(-1L),
53 PAIR(0xffff0000U | ugid),
54 PAIR(0xffff),
55 PAIR(0xc0deffffU)
56 };
57
58 for (unsigned int i = 0; i < ARRAY_SIZE(tests); ++i) {
59 const unsigned int rn = ugid2int(tests[i].r);
60 const unsigned int en = ugid2int(tests[i].e);
61
62 if (!num_matches_id(rn, ugid) || !num_matches_id(en, ugid))
63 continue;
64
65 if (syscall(SYSCALL_NR, tests[i].r, tests[i].e)) {
66 if (!i && ENOSYS == errno) {
67 printf("%s(%u, %u) = -1 ENOSYS (%m)\n",
68 SYSCALL_NAME, ugid, ugid);
69 break;
70 }
71 perror_msg_and_fail("%s(%#lx, %#lx)", SYSCALL_NAME,
72 tests[i].r, tests[i].e);
73 }
74
75 printf("%s(", SYSCALL_NAME);
76 print_int(rn);
77 printf(", ");
78 print_int(en);
79 printf(") = 0\n");
80 }
81
82 puts("+++ exited with 0 +++");
83 return 0;
84 }