1f08c3bdfSopenharmony_ci/// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) International Business Machines Corp., 2001 4f08c3bdfSopenharmony_ci */ 5f08c3bdfSopenharmony_ci 6f08c3bdfSopenharmony_ci/* 7f08c3bdfSopenharmony_ci * Test Name: chmod05 8f08c3bdfSopenharmony_ci * 9f08c3bdfSopenharmony_ci * Test Description: 10f08c3bdfSopenharmony_ci * Verify that, chmod(2) will succeed to change the mode of a directory 11f08c3bdfSopenharmony_ci * but fails to set the setgid bit on it if invoked by non-root (uid != 0) 12f08c3bdfSopenharmony_ci * process with the following constraints, 13f08c3bdfSopenharmony_ci * - the process is the owner of the directory. 14f08c3bdfSopenharmony_ci * - the effective group ID or one of the supplementary group ID's of the 15f08c3bdfSopenharmony_ci * process is not equal to the group ID of the directory. 16f08c3bdfSopenharmony_ci * 17f08c3bdfSopenharmony_ci * Expected Result: 18f08c3bdfSopenharmony_ci * chmod() should return value 0 on success and though succeeds to change 19f08c3bdfSopenharmony_ci * the mode of a directory but fails to set setgid bit on it. 20f08c3bdfSopenharmony_ci * 21f08c3bdfSopenharmony_ci */ 22f08c3bdfSopenharmony_ci 23f08c3bdfSopenharmony_ci#ifndef _GNU_SOURCE 24f08c3bdfSopenharmony_ci# define _GNU_SOURCE 25f08c3bdfSopenharmony_ci#endif 26f08c3bdfSopenharmony_ci 27f08c3bdfSopenharmony_ci#include <stdio.h> 28f08c3bdfSopenharmony_ci#include <stdlib.h> 29f08c3bdfSopenharmony_ci#include <sys/types.h> 30f08c3bdfSopenharmony_ci#include <sys/stat.h> 31f08c3bdfSopenharmony_ci#include <fcntl.h> 32f08c3bdfSopenharmony_ci#include <errno.h> 33f08c3bdfSopenharmony_ci#include <string.h> 34f08c3bdfSopenharmony_ci#include <signal.h> 35f08c3bdfSopenharmony_ci#include <unistd.h> 36f08c3bdfSopenharmony_ci#include <grp.h> 37f08c3bdfSopenharmony_ci#include <pwd.h> 38f08c3bdfSopenharmony_ci 39f08c3bdfSopenharmony_ci#include "tst_test.h" 40f08c3bdfSopenharmony_ci#include "tst_uid.h" 41f08c3bdfSopenharmony_ci 42f08c3bdfSopenharmony_ci#define MODE_RWX (mode_t)(S_IRWXU | S_IRWXG | S_IRWXO) 43f08c3bdfSopenharmony_ci#define DIR_MODE (mode_t)(S_ISVTX | S_ISGID | S_IFDIR) 44f08c3bdfSopenharmony_ci#define PERMS (mode_t)(MODE_RWX | DIR_MODE) 45f08c3bdfSopenharmony_ci#define TESTDIR "testdir" 46f08c3bdfSopenharmony_ci 47f08c3bdfSopenharmony_cistatic void test_chmod(void) 48f08c3bdfSopenharmony_ci{ 49f08c3bdfSopenharmony_ci struct stat stat_buf; 50f08c3bdfSopenharmony_ci mode_t dir_mode; 51f08c3bdfSopenharmony_ci 52f08c3bdfSopenharmony_ci TEST(chmod(TESTDIR, PERMS)); 53f08c3bdfSopenharmony_ci if (TST_RET == -1) { 54f08c3bdfSopenharmony_ci tst_res(TFAIL, "chmod(%s, %#o) failed", TESTDIR, PERMS); 55f08c3bdfSopenharmony_ci return; 56f08c3bdfSopenharmony_ci } 57f08c3bdfSopenharmony_ci 58f08c3bdfSopenharmony_ci SAFE_STAT(TESTDIR, &stat_buf); 59f08c3bdfSopenharmony_ci dir_mode = stat_buf.st_mode; 60f08c3bdfSopenharmony_ci if ((PERMS & ~S_ISGID) != dir_mode) { 61f08c3bdfSopenharmony_ci tst_res(TFAIL, "%s: Incorrect modes 0%03o, " 62f08c3bdfSopenharmony_ci "Expected 0%03o", TESTDIR, dir_mode, 63f08c3bdfSopenharmony_ci PERMS & ~S_ISGID); 64f08c3bdfSopenharmony_ci } else { 65f08c3bdfSopenharmony_ci tst_res(TPASS, "Functionality of chmod(%s, %#o) successful", 66f08c3bdfSopenharmony_ci TESTDIR, PERMS); 67f08c3bdfSopenharmony_ci } 68f08c3bdfSopenharmony_ci} 69f08c3bdfSopenharmony_ci 70f08c3bdfSopenharmony_cistatic void setup(void) 71f08c3bdfSopenharmony_ci{ 72f08c3bdfSopenharmony_ci struct passwd *nobody_u; 73f08c3bdfSopenharmony_ci gid_t free_gid; 74f08c3bdfSopenharmony_ci 75f08c3bdfSopenharmony_ci nobody_u = SAFE_GETPWNAM("nobody"); 76f08c3bdfSopenharmony_ci free_gid = tst_get_free_gid(nobody_u->pw_gid); 77f08c3bdfSopenharmony_ci 78f08c3bdfSopenharmony_ci /* 79f08c3bdfSopenharmony_ci * Create a test directory under temporary directory with specified 80f08c3bdfSopenharmony_ci * mode permissions and change the gid of test directory to nobody's 81f08c3bdfSopenharmony_ci * gid. 82f08c3bdfSopenharmony_ci */ 83f08c3bdfSopenharmony_ci SAFE_MKDIR(TESTDIR, MODE_RWX); 84f08c3bdfSopenharmony_ci if (setgroups(1, &nobody_u->pw_gid) == -1) 85f08c3bdfSopenharmony_ci tst_brk(TBROK | TERRNO, "setgroups to nobody's gid failed"); 86f08c3bdfSopenharmony_ci 87f08c3bdfSopenharmony_ci SAFE_CHOWN(TESTDIR, nobody_u->pw_uid, free_gid); 88f08c3bdfSopenharmony_ci 89f08c3bdfSopenharmony_ci /* change to nobody:nobody */ 90f08c3bdfSopenharmony_ci SAFE_SETEGID(nobody_u->pw_gid); 91f08c3bdfSopenharmony_ci SAFE_SETEUID(nobody_u->pw_uid); 92f08c3bdfSopenharmony_ci} 93f08c3bdfSopenharmony_ci 94f08c3bdfSopenharmony_cistatic struct tst_test test = { 95f08c3bdfSopenharmony_ci .needs_root = 1, 96f08c3bdfSopenharmony_ci .needs_tmpdir = 1, 97f08c3bdfSopenharmony_ci .setup = setup, 98f08c3bdfSopenharmony_ci .test_all = test_chmod, 99f08c3bdfSopenharmony_ci}; 100