1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright (c) International Business Machines Corp., 2001 4 * 07/2001 Ported by Wayne Boyer 5 */ 6 7/*\ 8 * [Description] 9 * 10 * Verify that, chown(2) succeeds to change the group of a file specified 11 * by path when called by non-root user with the following constraints: 12 * 13 * - euid of the process is equal to the owner of the file. 14 * - the intended gid is either egid, or one of the supplementary gids 15 * of the process. 16 * 17 * Also verify that chown() clears the setuid/setgid bits set on the file. 18 */ 19 20#include <pwd.h> 21 22#include "tst_test.h" 23#include "compat_tst_16.h" 24 25#define FILE_MODE (S_IFREG|S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) 26#define NEW_PERMS (S_IFREG|S_IRWXU|S_IRWXG|S_ISUID|S_ISGID) 27#define FILENAME "chown03_testfile" 28 29static struct passwd *ltpuser; 30 31static void check_owner(struct stat *s, uid_t exp_uid, gid_t exp_gid) 32{ 33 if (s->st_uid != exp_uid || s->st_gid != exp_gid) 34 tst_res(TFAIL, "%s: wrong owner set to (uid=%d, gid=%d)," 35 " expected (uid=%d, gid=%d)", 36 FILENAME, s->st_uid, s->st_gid, exp_uid, exp_gid); 37} 38 39static void check_mode(struct stat *s, mode_t exp_mode) 40{ 41 if (s->st_mode != exp_mode) 42 tst_res(TFAIL, "%s: wrong mode permissions %#o, expected %#o", 43 FILENAME, s->st_mode, exp_mode); 44} 45 46static void run(void) 47{ 48 SAFE_SETEUID(0); 49 SAFE_CHOWN(FILENAME, -1, 0); 50 SAFE_CHMOD(FILENAME, NEW_PERMS); 51 SAFE_SETEUID(ltpuser->pw_uid); 52 53 uid_t uid; 54 gid_t gid; 55 UID16_CHECK((uid = geteuid()), "chown"); 56 GID16_CHECK((gid = getegid()), "chown"); 57 58 struct stat stat_buf; 59 SAFE_STAT(FILENAME, &stat_buf); 60 check_owner(&stat_buf, uid, 0); 61 check_mode(&stat_buf, NEW_PERMS); 62 63 TST_EXP_PASS(CHOWN(FILENAME, -1, gid), "chown(%s, %d, %d)", 64 FILENAME, -1, gid); 65 SAFE_STAT(FILENAME, &stat_buf); 66 check_owner(&stat_buf, uid, gid); 67 check_mode(&stat_buf, NEW_PERMS & ~(S_ISUID | S_ISGID)); 68} 69 70static void setup(void) 71{ 72 int fd; 73 74 ltpuser = SAFE_GETPWNAM("nobody"); 75 SAFE_SETEGID(ltpuser->pw_gid); 76 SAFE_SETEUID(ltpuser->pw_uid); 77 78 fd = SAFE_OPEN(FILENAME, O_RDWR | O_CREAT, FILE_MODE); 79 SAFE_CLOSE(fd); 80} 81 82static void cleanup(void) 83{ 84 SAFE_SETEGID(0); 85 SAFE_SETEUID(0); 86} 87 88static struct tst_test test = { 89 .needs_root = 1, 90 .needs_tmpdir = 1, 91 .setup = setup, 92 .cleanup = cleanup, 93 .test_all = run, 94}; 95