1 /*
2 * Check decoding of setresuid/setresgid/setresuid32/setresgid32 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 TRIPLE(val) \
39 { val, ugid, ugid }, { ugid, val, ugid }, { ugid, ugid, val }
40
41 int
42 main(void)
43 {
44 unsigned int ugid = GETUGID;
45 CHECK_OVERFLOWUGID(ugid);
46
47 const struct {
48 const long r, e, s;
49 } tests[] = {
50 { ugid, ugid, ugid },
51 TRIPLE((unsigned long) 0xffffffff00000000ULL | ugid),
52 TRIPLE(-1U),
53 TRIPLE(-1L),
54 TRIPLE(0xffff0000U | ugid),
55 TRIPLE(0xffff),
56 TRIPLE(0xc0deffffU)
57 };
58
59 for (unsigned int i = 0; i < ARRAY_SIZE(tests); ++i) {
60 const unsigned int rn = ugid2int(tests[i].r);
61 const unsigned int en = ugid2int(tests[i].e);
62 const unsigned int sn = ugid2int(tests[i].s);
63
64 if (!num_matches_id(rn, ugid) ||
65 !num_matches_id(en, ugid) ||
66 !num_matches_id(sn, ugid))
67 continue;
68
69 if (syscall(SYSCALL_NR, tests[i].r, tests[i].e, tests[i].s)) {
70 if (!i && ENOSYS == errno) {
71 printf("%s(%u, %u, %u) = -1 ENOSYS (%m)\n",
72 SYSCALL_NAME, ugid, ugid, ugid);
73 break;
74 }
75 perror_msg_and_fail("%s(%#lx, %#lx, %#lx)",
76 SYSCALL_NAME,
77 tests[i].r, tests[i].e, tests[i].s);
78 }
79
80 printf("%s(", SYSCALL_NAME);
81 print_int(rn);
82 printf(", ");
83 print_int(en);
84 printf(", ");
85 print_int(sn);
86 printf(") = 0\n");
87 }
88
89 puts("+++ exited with 0 +++");
90 return 0;
91 }