1 /*
2 * Check decoding of getgroups/getgroups32 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_getgroups32
12
13 # define SYSCALL_NR __NR_getgroups32
14 # define SYSCALL_NAME "getgroups32"
15 # define GID_TYPE unsigned int
16
17 #else /* __NR_getgroups */
18
19 # include "tests.h"
20 # include "scno.h"
21
22 # define SYSCALL_NR __NR_getgroups
23 # define SYSCALL_NAME "getgroups"
24 # if defined __NR_getgroups32 && __NR_getgroups != __NR_getgroups32
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 #define MAX_STRLEN 32
36 static long ngroups;
37
38 static void
39 get_groups(const long size, GID_TYPE *const g)
40 {
41 long i = syscall(SYSCALL_NR, size, g);
42 if (i != ngroups)
43 perror_msg_and_fail("%s(%#lx, %p)", SYSCALL_NAME, size, g);
44
45 printf("%s(%d, [", SYSCALL_NAME, (int) size);
46 for (i = 0; i < ngroups; ++i) {
47 if (i)
48 printf(", ");
49 if (i >= MAX_STRLEN) {
50 printf("...");
51 break;
52 }
53 printf("%u", (unsigned int) g[i]);
54 }
55 printf("]) = %ld\n", ngroups);
56 }
57
58 int
59 main(void)
60 {
61 long rc;
62
63 /* check how the first argument is decoded */
64 ngroups = syscall(SYSCALL_NR, 0, 0);
65 printf("%s(0, NULL) = %ld\n", SYSCALL_NAME, ngroups);
66 if (ngroups < 0)
67 perror_msg_and_fail(SYSCALL_NAME);
68
69 rc = syscall(SYSCALL_NR, F8ILL_KULONG_MASK, 0);
70 printf("%s(0, NULL) = %ld\n", SYSCALL_NAME, rc);
71
72 rc = syscall(SYSCALL_NR, -1U, 0);
73 printf("%s(%d, NULL) = %s\n", SYSCALL_NAME, -1, sprintrc(rc));
74
75 rc = syscall(SYSCALL_NR, -1L, 0);
76 printf("%s(%d, NULL) = %s\n", SYSCALL_NAME, -1, sprintrc(rc));
77
78 const unsigned int ngroups_max = sysconf(_SC_NGROUPS_MAX);
79
80 rc = syscall(SYSCALL_NR, ngroups_max, 0);
81 printf("%s(%d, NULL) = %s\n", SYSCALL_NAME, ngroups_max, sprintrc(rc));
82
83 rc = syscall(SYSCALL_NR, F8ILL_KULONG_MASK | ngroups_max, 0);
84 printf("%s(%d, NULL) = %s\n", SYSCALL_NAME, ngroups_max, sprintrc(rc));
85
86 /* check how the second argument is decoded */
87 GID_TYPE *const g1 =
88 tail_alloc(ngroups ? sizeof(*g1) * ngroups : 1);
89 GID_TYPE *const g2 = tail_alloc(sizeof(*g2) * (ngroups + 1));
90 void *efault = g2 + ngroups + 1;
91
92 get_groups(ngroups, g1);
93 get_groups(ngroups + 1, g1);
94 get_groups(ngroups + 1, g2);
95
96 if (ngroups) {
97 rc = syscall(SYSCALL_NR, ngroups, efault);
98 printf("%s(%d, %p) = %s\n",
99 SYSCALL_NAME, (unsigned) ngroups, efault, sprintrc(rc));
100 }
101
102 puts("+++ exited with 0 +++");
103 return 0;
104 }