1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright (c) International Business Machines Corp., 2001 4 * Ported by John George 5 * Copyright (C) 2021 SUSE LLC <mdoucha@suse.cz> 6 */ 7 8/*\ 9 * [Description] 10 * 11 * Test the setreuid() feature, verifying the role of the saved-set-uid 12 * and setreuid's effect on it. 13 */ 14 15#include <sys/types.h> 16#include <pwd.h> 17#include <stdlib.h> 18 19#include "tst_test.h" 20#include "tst_uid.h" 21#include "compat_tst_16.h" 22 23static uid_t root_uid, nobody_uid, main_uid, other_uid, neg_one = -1; 24 25struct test_data_t { 26 uid_t *real_uid; 27 uid_t *eff_uid; 28 int exp_ret; 29 uid_t *exp_real_uid; 30 uid_t *exp_eff_uid; 31 uid_t *exp_sav_uid; 32 const char *test_msg; 33} test_data[] = { 34 {&nobody_uid, &root_uid, 0, &nobody_uid, &root_uid, &root_uid, 35 "setreuid(nobody, root)"}, 36 {&neg_one, &nobody_uid, 0, &nobody_uid, &nobody_uid, &root_uid, 37 "setreuid(-1, nobody)"}, 38 {&neg_one, &root_uid, 0, &nobody_uid, &root_uid, &root_uid, 39 "setreuid(-1, root)"}, 40 {&main_uid, &neg_one, 0, &main_uid, &root_uid, &root_uid, 41 "setreuid(main, -1)"}, 42 {&neg_one, &other_uid, 0, &main_uid, &other_uid, &other_uid, 43 "setreuid(-1, other)"}, 44 {&neg_one, &root_uid, -1, &main_uid, &other_uid, &other_uid, 45 "setreuid(-1, root)"}, 46 {&neg_one, &nobody_uid, -1, &main_uid, &other_uid, &other_uid, 47 "setreuid(-1, nobody)"}, 48 {&neg_one, &main_uid, 0, &main_uid, &main_uid, &other_uid, 49 "setreuid(-1, main)"}, 50 {&neg_one, &other_uid, 0, &main_uid, &other_uid, &other_uid, 51 "setreuid(-1, other)"}, 52 {&other_uid, &main_uid, 0, &other_uid, &main_uid, &main_uid, 53 "setreuid(other, main)"}, 54 {&neg_one, &other_uid, 0, &other_uid, &other_uid, &main_uid, 55 "setreuid(-1, other)"}, 56 {&neg_one, &main_uid, 0, &other_uid, &main_uid, &main_uid, 57 "setreuid(-1, main)"}, 58 {&main_uid, &neg_one, 0, &main_uid, &main_uid, &main_uid, 59 "setreuid(main, -1)"}, 60 {&neg_one, &other_uid, -1, &main_uid, &main_uid, &main_uid, 61 "setreuid(-1, other)"}, 62}; 63 64static void setup(void) 65{ 66 uid_t test_users[3]; 67 struct passwd *pw; 68 69 root_uid = getuid(); 70 pw = SAFE_GETPWNAM("nobody"); 71 nobody_uid = test_users[0] = pw->pw_uid; 72 tst_get_uids(test_users, 1, 3); 73 main_uid = test_users[1]; 74 other_uid = test_users[2]; 75 76 UID16_CHECK(root_uid, setreuid); 77 UID16_CHECK(nobody_uid, setreuid); 78 UID16_CHECK(main_uid, setreuid); 79 UID16_CHECK(other_uid, setreuid); 80 81 /* Make sure that saved UID is also set to root */ 82 SAFE_SETUID(root_uid); 83} 84 85static void run_child(const struct test_data_t *tc) 86{ 87 if (tc->exp_ret) { 88 TST_EXP_FAIL(SETREUID(*tc->real_uid, *tc->eff_uid), EPERM, 89 "%s", tc->test_msg); 90 } else { 91 TST_EXP_PASS(SETREUID(*tc->real_uid, *tc->eff_uid), "%s", 92 tc->test_msg); 93 } 94 95 if (!TST_PASS) 96 return; 97 98 tst_check_resuid(tc->test_msg, *tc->exp_real_uid, *tc->exp_eff_uid, 99 *tc->exp_sav_uid); 100} 101 102static void run(void) 103{ 104 if (!SAFE_FORK()) { 105 unsigned int i; 106 107 for (i = 0; i < ARRAY_SIZE(test_data); i++) 108 run_child(test_data + i); 109 110 exit(0); 111 } 112 113 tst_reap_children(); 114} 115 116static struct tst_test test = { 117 .test_all = run, 118 .setup = setup, 119 .needs_root = 1, 120 .forks_child = 1, 121}; 122