1 /* 2 * Check decoding of setgroups/setgroups32 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 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #ifdef __NR_setgroups32 32 33 # define SYSCALL_NR __NR_setgroups32 34 # define SYSCALL_NAME "setgroups32" 35 # define GID_TYPE unsigned int 36 37 #else 38 39 # include "tests.h" 40 # include <asm/unistd.h> 41 42 # ifdef __NR_setgroups 43 44 # define SYSCALL_NR __NR_setgroups 45 # define SYSCALL_NAME "setgroups" 46 # if defined __NR_setgroups32 && __NR_setgroups != __NR_setgroups32 47 # define GID_TYPE unsigned short 48 # else 49 # define GID_TYPE unsigned int 50 # endif 51 52 # endif 53 54 #endif 55 56 #ifdef GID_TYPE 57 58 # include <stdio.h> 59 # include <unistd.h> 60 61 void 62 printuid(GID_TYPE id) 63 { 64 if (id == (GID_TYPE) -1U) 65 printf("-1"); 66 else 67 printf("%u", id); 68 } 69 70 int 71 main(void) 72 { 73 const char *errstr; 74 75 /* check how the first argument is decoded */ 76 long rc = syscall(SYSCALL_NR, 0, 0); 77 printf("%s(0, NULL) = %s\n", SYSCALL_NAME, sprintrc(rc)); 78 79 rc = syscall(SYSCALL_NR, F8ILL_KULONG_MASK, 0); 80 printf("%s(0, NULL) = %s\n", SYSCALL_NAME, sprintrc(rc)); 81 82 rc = syscall(SYSCALL_NR, 1, 0); 83 printf("%s(1, NULL) = %s\n", SYSCALL_NAME, sprintrc(rc)); 84 85 rc = syscall(SYSCALL_NR, (long) 0xffffffff00000001ULL, 0); 86 printf("%s(1, NULL) = %s\n", SYSCALL_NAME, sprintrc(rc)); 87 88 rc = syscall(SYSCALL_NR, -1U, 0); 89 printf("%s(%d, NULL) = %s\n", SYSCALL_NAME, -1, sprintrc(rc)); 90 91 rc = syscall(SYSCALL_NR, -1L, 0); 92 printf("%s(%d, NULL) = %s\n", SYSCALL_NAME, -1, sprintrc(rc)); 93 94 /* check how the second argument is decoded */ 95 TAIL_ALLOC_OBJECT_CONST_PTR(const GID_TYPE, g1); 96 GID_TYPE *const g2 = tail_alloc(sizeof(*g2) * 2); 97 GID_TYPE *const g3 = tail_alloc(sizeof(*g3) * 3); 98 99 rc = syscall(SYSCALL_NR, 0, g1 + 1); 100 printf("%s(0, []) = %s\n", SYSCALL_NAME, sprintrc(rc)); 101 102 rc = syscall(SYSCALL_NR, 1, g1); 103 errstr = sprintrc(rc); 104 printf("%s(1, [", SYSCALL_NAME); 105 printuid(*g1); 106 printf("]) = %s\n", errstr); 107 108 rc = syscall(SYSCALL_NR, 1, g1 + 1); 109 printf("%s(1, %p) = %s\n", SYSCALL_NAME, g1 + 1, sprintrc(rc)); 110 111 rc = syscall(SYSCALL_NR, 1, -1L); 112 printf("%s(1, %#lx) = %s\n", SYSCALL_NAME, -1L, sprintrc(rc)); 113 114 rc = syscall(SYSCALL_NR, 2, g1); 115 errstr = sprintrc(rc); 116 printf("%s(2, [", SYSCALL_NAME); 117 printuid(*g1); 118 printf(", %p]) = %s\n", g1 + 1, errstr); 119 120 g2[0] = -2; 121 g2[1] = -3; 122 rc = syscall(SYSCALL_NR, 2, g2); 123 errstr = sprintrc(rc); 124 printf("%s(2, [", SYSCALL_NAME); 125 printuid(g2[0]); 126 printf(", "); 127 printuid(g2[1]); 128 printf("]) = %s\n", errstr); 129 130 rc = syscall(SYSCALL_NR, 3, g2); 131 errstr = sprintrc(rc); 132 printf("%s(3, [", SYSCALL_NAME); 133 printuid(g2[0]); 134 printf(", "); 135 printuid(g2[1]); 136 printf(", %p]) = %s\n", g2 + 2, errstr); 137 138 g3[0] = 0; 139 g3[1] = 1; 140 rc = syscall(SYSCALL_NR, 3, g3); 141 errstr = sprintrc(rc); 142 printf("%s(3, [", SYSCALL_NAME); 143 printuid(g3[0]); 144 printf(", "); 145 printuid(g3[1]); 146 printf(", ...]) = %s\n", errstr); 147 148 rc = syscall(SYSCALL_NR, 4, g3); 149 errstr = sprintrc(rc); 150 printf("%s(4, [", SYSCALL_NAME); 151 printuid(g3[0]); 152 printf(", "); 153 printuid(g3[1]); 154 printf(", ...]) = %s\n", errstr); 155 156 rc = sysconf(_SC_NGROUPS_MAX); 157 const unsigned ngroups_max = rc; 158 159 if ((unsigned long) rc == ngroups_max && (int) ngroups_max > 0) { 160 rc = syscall(SYSCALL_NR, ngroups_max, g3); 161 errstr = sprintrc(rc); 162 printf("%s(%d, [", SYSCALL_NAME, ngroups_max); 163 printuid(g3[0]); 164 printf(", "); 165 printuid(g3[1]); 166 printf(", ...]) = %s\n", errstr); 167 168 rc = syscall(SYSCALL_NR, F8ILL_KULONG_MASK | ngroups_max, g3); 169 errstr = sprintrc(rc); 170 printf("%s(%d, [", SYSCALL_NAME, ngroups_max); 171 printuid(g3[0]); 172 printf(", "); 173 printuid(g3[1]); 174 printf(", ...]) = %s\n", errstr); 175 176 rc = syscall(SYSCALL_NR, ngroups_max + 1, g3); 177 printf("%s(%d, %p) = %s\n", SYSCALL_NAME, 178 ngroups_max + 1, g3, sprintrc(rc)); 179 } 180 181 puts("+++ exited with 0 +++"); 182 return 0; 183 } 184 185 #else 186 187 SKIP_MAIN_UNDEFINED("__NR_setgroups") 188 189 #endif 190