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 * 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_getgroups32 32 33 # define SYSCALL_NR __NR_getgroups32 34 # define SYSCALL_NAME "getgroups32" 35 # define GID_TYPE unsigned int 36 37 #else 38 39 # include "tests.h" 40 # include <asm/unistd.h> 41 42 # ifdef __NR_getgroups 43 44 # define SYSCALL_NR __NR_getgroups 45 # define SYSCALL_NAME "getgroups" 46 # if defined __NR_getgroups32 && __NR_getgroups != __NR_getgroups32 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 #define MAX_STRLEN 32 62 static long ngroups; 63 64 static void 65 get_groups(const long size, GID_TYPE *const g) 66 { 67 long i = syscall(SYSCALL_NR, size, g); 68 if (i != ngroups) 69 perror_msg_and_fail("%s(%#lx, %p)", SYSCALL_NAME, size, g); 70 71 printf("%s(%d, [", SYSCALL_NAME, (int) size); 72 for (i = 0; i < ngroups; ++i) { 73 if (i) 74 printf(", "); 75 if (i >= MAX_STRLEN) { 76 printf("..."); 77 break; 78 } 79 printf("%u", (unsigned int) g[i]); 80 } 81 printf("]) = %ld\n", ngroups); 82 } 83 84 int 85 main(void) 86 { 87 long rc; 88 89 /* check how the first argument is decoded */ 90 ngroups = syscall(SYSCALL_NR, 0, 0); 91 printf("%s(0, NULL) = %ld\n", SYSCALL_NAME, ngroups); 92 if (ngroups < 0) 93 perror_msg_and_fail(SYSCALL_NAME); 94 95 rc = syscall(SYSCALL_NR, F8ILL_KULONG_MASK, 0); 96 printf("%s(0, NULL) = %ld\n", SYSCALL_NAME, rc); 97 98 rc = syscall(SYSCALL_NR, -1U, 0); 99 printf("%s(%d, NULL) = %s\n", SYSCALL_NAME, -1, sprintrc(rc)); 100 101 rc = syscall(SYSCALL_NR, -1L, 0); 102 printf("%s(%d, NULL) = %s\n", SYSCALL_NAME, -1, sprintrc(rc)); 103 104 const unsigned int ngroups_max = sysconf(_SC_NGROUPS_MAX); 105 106 rc = syscall(SYSCALL_NR, ngroups_max, 0); 107 printf("%s(%d, NULL) = %s\n", SYSCALL_NAME, ngroups_max, sprintrc(rc)); 108 109 rc = syscall(SYSCALL_NR, F8ILL_KULONG_MASK | ngroups_max, 0); 110 printf("%s(%d, NULL) = %s\n", SYSCALL_NAME, ngroups_max, sprintrc(rc)); 111 112 /* check how the second argument is decoded */ 113 GID_TYPE *const g1 = 114 tail_alloc(ngroups ? sizeof(*g1) * ngroups : 1); 115 GID_TYPE *const g2 = tail_alloc(sizeof(*g2) * (ngroups + 1)); 116 void *efault = g2 + ngroups + 1; 117 118 get_groups(ngroups, g1); 119 get_groups(ngroups + 1, g1); 120 get_groups(ngroups + 1, g2); 121 122 if (ngroups) { 123 rc = syscall(SYSCALL_NR, ngroups, efault); 124 printf("%s(%d, %p) = %s\n", 125 SYSCALL_NAME, (unsigned) ngroups, efault, sprintrc(rc)); 126 } 127 128 puts("+++ exited with 0 +++"); 129 return 0; 130 } 131 132 #else 133 134 SKIP_MAIN_UNDEFINED("__NR_getgroups") 135 136 #endif 137