]> granicus.if.org Git - strace/blob - tests/getgroups.c
4239e96b2a0d1c47469f3bffe2bee5abfb1de67a
[strace] / tests / getgroups.c
1 /*
2  * Check decoding of getgroups/getgroups32 syscalls.
3  *
4  * Copyright (c) 2016 Dmitry V. Levin <ldv@altlinux.org>
5  * Copyright (c) 2016-2017 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
18
19 # include "tests.h"
20 # include <asm/unistd.h>
21
22 # ifdef __NR_getgroups
23
24 #  define SYSCALL_NR    __NR_getgroups
25 #  define SYSCALL_NAME  "getgroups"
26 #  if defined __NR_getgroups32 && __NR_getgroups != __NR_getgroups32
27 #   define GID_TYPE     unsigned short
28 #  else
29 #   define GID_TYPE     unsigned int
30 #  endif
31
32 # endif
33
34 #endif
35
36 #ifdef GID_TYPE
37
38 # include <stdio.h>
39 # include <unistd.h>
40
41 #define MAX_STRLEN 32
42 static long ngroups;
43
44 static void
45 get_groups(const long size, GID_TYPE *const g)
46 {
47         long i = syscall(SYSCALL_NR, size, g);
48         if (i != ngroups)
49                 perror_msg_and_fail("%s(%#lx, %p)", SYSCALL_NAME, size, g);
50
51         printf("%s(%d, [", SYSCALL_NAME, (int) size);
52         for (i = 0; i < ngroups; ++i) {
53                 if (i)
54                         printf(", ");
55                 if (i >= MAX_STRLEN) {
56                         printf("...");
57                         break;
58                 }
59                 printf("%u", (unsigned int) g[i]);
60         }
61         printf("]) = %ld\n", ngroups);
62 }
63
64 int
65 main(void)
66 {
67         long rc;
68
69         /* check how the first argument is decoded */
70         ngroups = syscall(SYSCALL_NR, 0, 0);
71         printf("%s(0, NULL) = %ld\n", SYSCALL_NAME, ngroups);
72         if (ngroups < 0)
73                 perror_msg_and_fail(SYSCALL_NAME);
74
75         rc = syscall(SYSCALL_NR, F8ILL_KULONG_MASK, 0);
76         printf("%s(0, NULL) = %ld\n", SYSCALL_NAME, rc);
77
78         rc = syscall(SYSCALL_NR, -1U, 0);
79         printf("%s(%d, NULL) = %s\n", SYSCALL_NAME, -1, sprintrc(rc));
80
81         rc = syscall(SYSCALL_NR, -1L, 0);
82         printf("%s(%d, NULL) = %s\n", SYSCALL_NAME, -1, sprintrc(rc));
83
84         const unsigned int ngroups_max = sysconf(_SC_NGROUPS_MAX);
85
86         rc = syscall(SYSCALL_NR, ngroups_max, 0);
87         printf("%s(%d, NULL) = %s\n", SYSCALL_NAME, ngroups_max, sprintrc(rc));
88
89         rc = syscall(SYSCALL_NR, F8ILL_KULONG_MASK | ngroups_max, 0);
90         printf("%s(%d, NULL) = %s\n", SYSCALL_NAME, ngroups_max, sprintrc(rc));
91
92         /* check how the second argument is decoded */
93         GID_TYPE *const g1 =
94                 tail_alloc(ngroups ? sizeof(*g1) * ngroups : 1);
95         GID_TYPE *const g2 = tail_alloc(sizeof(*g2) * (ngroups + 1));
96         void *efault = g2 + ngroups + 1;
97
98         get_groups(ngroups, g1);
99         get_groups(ngroups + 1, g1);
100         get_groups(ngroups + 1, g2);
101
102         if (ngroups) {
103                 rc = syscall(SYSCALL_NR, ngroups, efault);
104                 printf("%s(%d, %p) = %s\n",
105                        SYSCALL_NAME, (unsigned) ngroups, efault, sprintrc(rc));
106         }
107
108         puts("+++ exited with 0 +++");
109         return 0;
110 }
111
112 #else
113
114 SKIP_MAIN_UNDEFINED("__NR_getgroups")
115
116 #endif