1105513Sphk/* $NetBSD: t_getgroups.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $ */ 2105513Sphk 3105513Sphk/*- 4105513Sphk * Copyright (c) 2011 The NetBSD Foundation, Inc. 5105513Sphk * All rights reserved. 6105513Sphk * 7314327Savg * This code is derived from software contributed to The NetBSD Foundation 8105513Sphk * by Jukka Ruohonen. 9105513Sphk * 10228610Sdim * Redistribution and use in source and binary forms, with or without 11228610Sdim * modification, are permitted provided that the following conditions 12228610Sdim * are met: 13249657Sed * 1. Redistributions of source code must retain the above copyright 14107982Sphk * notice, this list of conditions and the following disclaimer. 15105610Sphk * 2. Redistributions in binary form must reproduce the above copyright 16113014Sphk * notice, this list of conditions and the following disclaimer in the 17106407Sphk * documentation and/or other materials provided with the distribution. 18106407Sphk * 19105513Sphk * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20105513Sphk * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21105513Sphk * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22105513Sphk * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23115104Sru * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24115104Sru * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25105513Sphk * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26113558Sru * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27105513Sphk * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28105513Sphk * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29105513Sphk * POSSIBILITY OF SUCH DAMAGE. 30113558Sru */ 31121169Sphk#include <sys/cdefs.h> 32113558Sru__RCSID("$NetBSD: t_getgroups.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $"); 33113558Sru 34#include <sys/wait.h> 35 36#include <atf-c.h> 37#include <errno.h> 38#include <limits.h> 39#include <stdlib.h> 40#include <string.h> 41#include <unistd.h> 42 43ATF_TC(getgroups_err); 44ATF_TC_HEAD(getgroups_err, tc) 45{ 46 atf_tc_set_md_var(tc, "descr", "Test errors in getgroups(2)"); 47} 48 49ATF_TC_BODY(getgroups_err, tc) 50{ 51 gid_t gidset[NGROUPS_MAX]; 52 53 errno = 0; 54 55 ATF_REQUIRE(getgroups(10, (gid_t *)-1) == -1); 56 ATF_REQUIRE(errno == EFAULT); 57 58 errno = 0; 59 60#ifdef __FreeBSD__ 61 atf_tc_expect_fail("Reported as kern/189941"); 62#endif 63 ATF_REQUIRE(getgroups(-1, gidset) == -1); 64 ATF_REQUIRE(errno == EINVAL); 65} 66 67ATF_TC(getgroups_getgid); 68ATF_TC_HEAD(getgroups_getgid, tc) 69{ 70 atf_tc_set_md_var(tc, "descr", "Test getgid(2) from getgroups(2)"); 71} 72 73ATF_TC_BODY(getgroups_getgid, tc) 74{ 75 gid_t gidset[NGROUPS_MAX]; 76 gid_t gid = getgid(); 77 int i, n; 78 79 /* 80 * Check that getgid(2) is found from 81 * the GIDs returned by getgroups(2). 82 */ 83 n = getgroups(NGROUPS_MAX, gidset); 84 85 for (i = 0; i < n; i++) { 86 87 if (gidset[i] == gid) 88 return; 89 } 90 91 atf_tc_fail("getgid(2) not found from getgroups(2)"); 92} 93 94ATF_TC(getgroups_setgid); 95ATF_TC_HEAD(getgroups_setgid, tc) 96{ 97 atf_tc_set_md_var(tc, "descr", "Test setgid(2) from getgroups(2)"); 98 atf_tc_set_md_var(tc, "require.user", "root"); 99} 100 101ATF_TC_BODY(getgroups_setgid, tc) 102{ 103 gid_t gidset[NGROUPS_MAX]; 104 int i, n, rv, sta; 105 pid_t pid; 106 107 /* 108 * Check that we can setgid(2) 109 * to the returned group IDs. 110 */ 111 n = getgroups(NGROUPS_MAX, gidset); 112 ATF_REQUIRE(n >= 0); 113 114 for (i = 0; i < n; i++) { 115 116 pid = fork(); 117 ATF_REQUIRE(pid >= 0); 118 119 if (pid == 0) { 120 121 rv = setgid(gidset[i]); 122 123 if (rv != 0) 124 _exit(EXIT_FAILURE); 125 126 _exit(EXIT_SUCCESS); 127 } 128 129 (void)wait(&sta); 130 131 if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS) 132 atf_tc_fail("getgroups(2) is inconsistent"); 133 } 134} 135 136ATF_TC(getgroups_zero); 137ATF_TC_HEAD(getgroups_zero, tc) 138{ 139 atf_tc_set_md_var(tc, "descr", "Test getgroups(2) with zero param"); 140} 141 142ATF_TC_BODY(getgroups_zero, tc) 143{ 144 const gid_t val = 123456789; 145 gid_t gidset[NGROUPS_MAX]; 146 size_t i; 147 148 /* 149 * If the first parameter is zero, the number 150 * of groups should be returned but the supplied 151 * buffer should remain intact. 152 */ 153 for (i = 0; i < __arraycount(gidset); i++) 154 gidset[i] = val; 155 156 ATF_REQUIRE(getgroups(0, gidset) >= 0); 157 158 for (i = 0; i < __arraycount(gidset); i++) { 159 160 if (gidset[i] != val) 161 atf_tc_fail("getgroups(2) modified the buffer"); 162 } 163} 164 165ATF_TP_ADD_TCS(tp) 166{ 167 168 ATF_TP_ADD_TC(tp, getgroups_err); 169 ATF_TP_ADD_TC(tp, getgroups_getgid); 170 ATF_TP_ADD_TC(tp, getgroups_setgid); 171 ATF_TP_ADD_TC(tp, getgroups_zero); 172 173 return atf_no_error(); 174} 175