1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (C) Bull S.A. 2001 4f08c3bdfSopenharmony_ci * Copyright (c) International Business Machines Corp., 2001 5f08c3bdfSopenharmony_ci * Copyright (c) Linux Test Project, 2003-2023 6f08c3bdfSopenharmony_ci * 07/2001 Ported by Wayne Boyer 7f08c3bdfSopenharmony_ci * 05/2002 Ported by Andre Merlier 8f08c3bdfSopenharmony_ci */ 9f08c3bdfSopenharmony_ci 10f08c3bdfSopenharmony_ci/*\ 11f08c3bdfSopenharmony_ci * [Description] 12f08c3bdfSopenharmony_ci * 13f08c3bdfSopenharmony_ci * Test for EINVAL, EPERM, EFAULT errors. 14f08c3bdfSopenharmony_ci * 15f08c3bdfSopenharmony_ci * - setgroups() fails with EINVAL if the size argument value is > NGROUPS. 16f08c3bdfSopenharmony_ci * 17f08c3bdfSopenharmony_ci * - setgroups() fails with EPERM if the calling process is not super-user. 18f08c3bdfSopenharmony_ci * 19f08c3bdfSopenharmony_ci * - setgroups() fails with EFAULT if the list has an invalid address. 20f08c3bdfSopenharmony_ci */ 21f08c3bdfSopenharmony_ci 22f08c3bdfSopenharmony_ci#include <pwd.h> 23f08c3bdfSopenharmony_ci#include <stdlib.h> 24f08c3bdfSopenharmony_ci 25f08c3bdfSopenharmony_ci#include "tst_test.h" 26f08c3bdfSopenharmony_ci#include "compat_tst_16.h" 27f08c3bdfSopenharmony_ci 28f08c3bdfSopenharmony_ci#define TESTUSER "nobody" 29f08c3bdfSopenharmony_ci 30f08c3bdfSopenharmony_cistatic GID_T *glist1, *glist2, *glist3; 31f08c3bdfSopenharmony_cistatic struct passwd *user_info; 32f08c3bdfSopenharmony_ci 33f08c3bdfSopenharmony_cistatic struct tcase { 34f08c3bdfSopenharmony_ci int gsize; 35f08c3bdfSopenharmony_ci GID_T **glist; 36f08c3bdfSopenharmony_ci int exp_errno; 37f08c3bdfSopenharmony_ci} tcases[] = { 38f08c3bdfSopenharmony_ci {NGROUPS + 1, &glist1, EINVAL}, 39f08c3bdfSopenharmony_ci {1, &glist2, EPERM}, 40f08c3bdfSopenharmony_ci {NGROUPS, &glist3, EFAULT}, 41f08c3bdfSopenharmony_ci}; 42f08c3bdfSopenharmony_ci 43f08c3bdfSopenharmony_cistatic void verify_setgroups(unsigned int i) 44f08c3bdfSopenharmony_ci{ 45f08c3bdfSopenharmony_ci struct tcase *tc = &tcases[i]; 46f08c3bdfSopenharmony_ci 47f08c3bdfSopenharmony_ci if (tc->exp_errno == EPERM) 48f08c3bdfSopenharmony_ci SAFE_SETEUID(user_info->pw_uid); 49f08c3bdfSopenharmony_ci 50f08c3bdfSopenharmony_ci TST_EXP_FAIL(SETGROUPS(tc->gsize, *tc->glist), tc->exp_errno, 51f08c3bdfSopenharmony_ci "setgroups(%d, groups_list)", tc->gsize); 52f08c3bdfSopenharmony_ci 53f08c3bdfSopenharmony_ci if (tc->exp_errno == EPERM) 54f08c3bdfSopenharmony_ci SAFE_SETEUID(0); 55f08c3bdfSopenharmony_ci} 56f08c3bdfSopenharmony_ci 57f08c3bdfSopenharmony_cistatic void setup(void) 58f08c3bdfSopenharmony_ci{ 59f08c3bdfSopenharmony_ci user_info = SAFE_GETPWNAM(TESTUSER); 60f08c3bdfSopenharmony_ci glist2[0] = 42; 61f08c3bdfSopenharmony_ci glist3 = tst_get_bad_addr(NULL); 62f08c3bdfSopenharmony_ci} 63f08c3bdfSopenharmony_ci 64f08c3bdfSopenharmony_cistatic struct tst_test test = { 65f08c3bdfSopenharmony_ci .test = verify_setgroups, 66f08c3bdfSopenharmony_ci .tcnt = ARRAY_SIZE(tcases), 67f08c3bdfSopenharmony_ci .bufs = (struct tst_buffers []) { 68f08c3bdfSopenharmony_ci {&glist1, .size = sizeof(GID_T) * (NGROUPS + 1)}, 69f08c3bdfSopenharmony_ci {&glist2, .size = sizeof(GID_T)}, 70f08c3bdfSopenharmony_ci {&user_info, .size = sizeof(struct passwd)}, 71f08c3bdfSopenharmony_ci {}, 72f08c3bdfSopenharmony_ci }, 73f08c3bdfSopenharmony_ci .setup = setup, 74f08c3bdfSopenharmony_ci .needs_root = 1, 75f08c3bdfSopenharmony_ci}; 76