1 /*
2 * Check decoding of setgroups/setgroups32 syscalls.
3 *
4 * Copyright (c) 2016 Dmitry V. Levin <ldv@strace.io>
5 * Copyright (c) 2016-2021 The strace developers.
6 * All rights reserved.
7 *
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
10
11 #ifdef __NR_setgroups32
12
13 # define SYSCALL_NR __NR_setgroups32
14 # define SYSCALL_NAME "setgroups32"
15 # define GID_TYPE unsigned int
16
17 #else /* __NR_setgroups */
18
19 # include "tests.h"
20 # include "scno.h"
21
22 # define SYSCALL_NR __NR_setgroups
23 # define SYSCALL_NAME "setgroups"
24 # if defined __NR_setgroups32 && __NR_setgroups != __NR_setgroups32
25 # define GID_TYPE unsigned short
26 # else
27 # define GID_TYPE unsigned int
28 # endif
29
30 #endif
31
32 #include <stdio.h>
33 #include <unistd.h>
34
35 static void
36 printuid(GID_TYPE id)
37 {
38 if (id == (GID_TYPE) -1U)
39 printf("-1");
40 else
41 printf("%u", id);
42 }
43
44 int
45 main(void)
46 {
47 const char *errstr;
48
49 /* check how the first argument is decoded */
50 long rc = syscall(SYSCALL_NR, 0, 0);
51 printf("%s(0, NULL) = %s\n", SYSCALL_NAME, sprintrc(rc));
52
53 rc = syscall(SYSCALL_NR, F8ILL_KULONG_MASK, 0);
54 printf("%s(0, NULL) = %s\n", SYSCALL_NAME, sprintrc(rc));
55
56 rc = syscall(SYSCALL_NR, 1, 0);
57 printf("%s(1, NULL) = %s\n", SYSCALL_NAME, sprintrc(rc));
58
59 rc = syscall(SYSCALL_NR, (long) 0xffffffff00000001ULL, 0);
60 printf("%s(1, NULL) = %s\n", SYSCALL_NAME, sprintrc(rc));
61
62 rc = syscall(SYSCALL_NR, -1U, 0);
63 printf("%s(%d, NULL) = %s\n", SYSCALL_NAME, -1, sprintrc(rc));
64
65 rc = syscall(SYSCALL_NR, -1L, 0);
66 printf("%s(%d, NULL) = %s\n", SYSCALL_NAME, -1, sprintrc(rc));
67
68 /* check how the second argument is decoded */
69 TAIL_ALLOC_OBJECT_CONST_PTR(const GID_TYPE, g1);
70 GID_TYPE *const g2 = tail_alloc(sizeof(*g2) * 2);
71 GID_TYPE *const g3 = tail_alloc(sizeof(*g3) * 3);
72
73 rc = syscall(SYSCALL_NR, 0, g1 + 1);
74 printf("%s(0, []) = %s\n", SYSCALL_NAME, sprintrc(rc));
75
76 rc = syscall(SYSCALL_NR, 1, g1);
77 errstr = sprintrc(rc);
78 printf("%s(1, [", SYSCALL_NAME);
79 printuid(*g1);
80 printf("]) = %s\n", errstr);
81
82 rc = syscall(SYSCALL_NR, 1, g1 + 1);
83 printf("%s(1, %p) = %s\n", SYSCALL_NAME, g1 + 1, sprintrc(rc));
84
85 rc = syscall(SYSCALL_NR, 1, -1L);
86 printf("%s(1, %#lx) = %s\n", SYSCALL_NAME, -1L, sprintrc(rc));
87
88 rc = syscall(SYSCALL_NR, 2, g1);
89 errstr = sprintrc(rc);
90 printf("%s(2, [", SYSCALL_NAME);
91 printuid(*g1);
92 printf(", ... /* %p */]) = %s\n", g1 + 1, errstr);
93
94 g2[0] = -2;
95 g2[1] = -3;
96 rc = syscall(SYSCALL_NR, 2, g2);
97 errstr = sprintrc(rc);
98 printf("%s(2, [", SYSCALL_NAME);
99 printuid(g2[0]);
100 printf(", ");
101 printuid(g2[1]);
102 printf("]) = %s\n", errstr);
103
104 rc = syscall(SYSCALL_NR, 3, g2);
105 errstr = sprintrc(rc);
106 printf("%s(3, [", SYSCALL_NAME);
107 printuid(g2[0]);
108 printf(", ");
109 printuid(g2[1]);
110 printf(", ... /* %p */]) = %s\n", g2 + 2, errstr);
111
112 g3[0] = 0;
113 g3[1] = 1;
114 rc = syscall(SYSCALL_NR, 3, g3);
115 errstr = sprintrc(rc);
116 printf("%s(3, [", SYSCALL_NAME);
117 printuid(g3[0]);
118 printf(", ");
119 printuid(g3[1]);
120 printf(", ...]) = %s\n", errstr);
121
122 rc = syscall(SYSCALL_NR, 4, g3);
123 errstr = sprintrc(rc);
124 printf("%s(4, [", SYSCALL_NAME);
125 printuid(g3[0]);
126 printf(", ");
127 printuid(g3[1]);
128 printf(", ...]) = %s\n", errstr);
129
130 rc = sysconf(_SC_NGROUPS_MAX);
131 const unsigned ngroups_max = rc;
132
133 if ((unsigned long) rc == ngroups_max && (int) ngroups_max > 0) {
134 rc = syscall(SYSCALL_NR, ngroups_max, g3);
135 errstr = sprintrc(rc);
136 printf("%s(%d, [", SYSCALL_NAME, ngroups_max);
137 printuid(g3[0]);
138 printf(", ");
139 printuid(g3[1]);
140 printf(", ...]) = %s\n", errstr);
141
142 rc = syscall(SYSCALL_NR, F8ILL_KULONG_MASK | ngroups_max, g3);
143 errstr = sprintrc(rc);
144 printf("%s(%d, [", SYSCALL_NAME, ngroups_max);
145 printuid(g3[0]);
146 printf(", ");
147 printuid(g3[1]);
148 printf(", ...]) = %s\n", errstr);
149
150 rc = syscall(SYSCALL_NR, ngroups_max + 1, g3);
151 printf("%s(%d, %p) = %s\n", SYSCALL_NAME,
152 ngroups_max + 1, g3, sprintrc(rc));
153 }
154
155 puts("+++ exited with 0 +++");
156 return 0;
157 }