1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) International Business Machines Corp., 2001 4f08c3bdfSopenharmony_ci * Ported to LTP: Wayne Boyer 5f08c3bdfSopenharmony_ci * Copyright (c) 2014-2018 Cyril Hrubis <chrubis@suse.cz> 6f08c3bdfSopenharmony_ci */ 7f08c3bdfSopenharmony_ci 8f08c3bdfSopenharmony_ci/* 9f08c3bdfSopenharmony_ci * Test Name: chmod06 10f08c3bdfSopenharmony_ci * 11f08c3bdfSopenharmony_ci * Test Description: 12f08c3bdfSopenharmony_ci * Verify that, 13f08c3bdfSopenharmony_ci * 1) chmod(2) returns -1 and sets errno to EPERM if the effective user id 14f08c3bdfSopenharmony_ci * of process does not match the owner of the file and the process is 15f08c3bdfSopenharmony_ci * not super user. 16f08c3bdfSopenharmony_ci * 2) chmod(2) returns -1 and sets errno to EACCES if search permission is 17f08c3bdfSopenharmony_ci * denied on a component of the path prefix. 18f08c3bdfSopenharmony_ci * 3) chmod(2) returns -1 and sets errno to EFAULT if pathname points 19f08c3bdfSopenharmony_ci * outside user's accessible address space. 20f08c3bdfSopenharmony_ci * 4) chmod(2) returns -1 and sets errno to ENAMETOOLONG if the pathname 21f08c3bdfSopenharmony_ci * component is too long. 22f08c3bdfSopenharmony_ci * 5) chmod(2) returns -1 and sets errno to ENOTDIR if the directory 23f08c3bdfSopenharmony_ci * component in pathname is not a directory. 24f08c3bdfSopenharmony_ci * 6) chmod(2) returns -1 and sets errno to ENOENT if the specified file 25f08c3bdfSopenharmony_ci * does not exists. 26f08c3bdfSopenharmony_ci */ 27f08c3bdfSopenharmony_ci#include <pwd.h> 28f08c3bdfSopenharmony_ci#include <errno.h> 29f08c3bdfSopenharmony_ci#include "tst_test.h" 30f08c3bdfSopenharmony_ci 31f08c3bdfSopenharmony_ci#define MODE_RWX (S_IRWXU|S_IRWXG|S_IRWXO) 32f08c3bdfSopenharmony_ci#define FILE_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) 33f08c3bdfSopenharmony_ci#define DIR_TEMP "testdir_1" 34f08c3bdfSopenharmony_ci#define TEST_FILE1 "tfile_1" 35f08c3bdfSopenharmony_ci#define TEST_FILE2 "testdir_1/tfile_2" 36f08c3bdfSopenharmony_ci#define TEST_FILE3 "t_file/tfile_3" 37f08c3bdfSopenharmony_ci#define TEST_FILE4 "test_file4" 38f08c3bdfSopenharmony_ci#define MNT_POINT "mntpoint" 39f08c3bdfSopenharmony_ci 40f08c3bdfSopenharmony_ci#define DIR_MODE (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP| \ 41f08c3bdfSopenharmony_ci S_IXGRP|S_IROTH|S_IXOTH) 42f08c3bdfSopenharmony_ci 43f08c3bdfSopenharmony_cistatic char long_path[PATH_MAX + 2]; 44f08c3bdfSopenharmony_ci 45f08c3bdfSopenharmony_cistatic uid_t nobody_uid; 46f08c3bdfSopenharmony_ci 47f08c3bdfSopenharmony_cistatic void set_root(void); 48f08c3bdfSopenharmony_cistatic void set_nobody(void); 49f08c3bdfSopenharmony_ci 50f08c3bdfSopenharmony_cistatic struct tcase { 51f08c3bdfSopenharmony_ci char *pathname; 52f08c3bdfSopenharmony_ci mode_t mode; 53f08c3bdfSopenharmony_ci int exp_errno; 54f08c3bdfSopenharmony_ci void (*setup)(void); 55f08c3bdfSopenharmony_ci void (*cleanup)(void); 56f08c3bdfSopenharmony_ci} tc[] = { 57f08c3bdfSopenharmony_ci {TEST_FILE1, FILE_MODE, EPERM, set_nobody, set_root}, 58f08c3bdfSopenharmony_ci {TEST_FILE2, FILE_MODE, EACCES, set_nobody, set_root}, 59f08c3bdfSopenharmony_ci {(char *)-1, FILE_MODE, EFAULT, NULL, NULL}, 60f08c3bdfSopenharmony_ci {NULL, FILE_MODE, EFAULT, NULL, NULL}, 61f08c3bdfSopenharmony_ci {long_path, FILE_MODE, ENAMETOOLONG, NULL, NULL}, 62f08c3bdfSopenharmony_ci {"", FILE_MODE, ENOENT, NULL, NULL}, 63f08c3bdfSopenharmony_ci {TEST_FILE3, FILE_MODE, ENOTDIR, NULL, NULL}, 64f08c3bdfSopenharmony_ci {MNT_POINT, FILE_MODE, EROFS, NULL, NULL}, 65f08c3bdfSopenharmony_ci {TEST_FILE4, FILE_MODE, ELOOP, NULL, NULL}, 66f08c3bdfSopenharmony_ci}; 67f08c3bdfSopenharmony_ci 68f08c3bdfSopenharmony_cistatic char *bad_addr; 69f08c3bdfSopenharmony_ci 70f08c3bdfSopenharmony_civoid run(unsigned int i) 71f08c3bdfSopenharmony_ci{ 72f08c3bdfSopenharmony_ci if (tc[i].setup) 73f08c3bdfSopenharmony_ci tc[i].setup(); 74f08c3bdfSopenharmony_ci 75f08c3bdfSopenharmony_ci TEST(chmod(tc[i].pathname, tc[i].mode)); 76f08c3bdfSopenharmony_ci 77f08c3bdfSopenharmony_ci if (tc[i].cleanup) 78f08c3bdfSopenharmony_ci tc[i].cleanup(); 79f08c3bdfSopenharmony_ci 80f08c3bdfSopenharmony_ci if (TST_RET != -1) { 81f08c3bdfSopenharmony_ci tst_res(TFAIL, "chmod succeeded unexpectedly"); 82f08c3bdfSopenharmony_ci return; 83f08c3bdfSopenharmony_ci } 84f08c3bdfSopenharmony_ci 85f08c3bdfSopenharmony_ci if (TST_ERR == tc[i].exp_errno) { 86f08c3bdfSopenharmony_ci tst_res(TPASS | TTERRNO, "chmod failed as expected"); 87f08c3bdfSopenharmony_ci } else { 88f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, "chmod failed unexpectedly; " 89f08c3bdfSopenharmony_ci "expected %d - %s", tc[i].exp_errno, 90f08c3bdfSopenharmony_ci tst_strerrno(tc[i].exp_errno)); 91f08c3bdfSopenharmony_ci } 92f08c3bdfSopenharmony_ci} 93f08c3bdfSopenharmony_ci 94f08c3bdfSopenharmony_civoid set_root(void) 95f08c3bdfSopenharmony_ci{ 96f08c3bdfSopenharmony_ci SAFE_SETEUID(0); 97f08c3bdfSopenharmony_ci} 98f08c3bdfSopenharmony_ci 99f08c3bdfSopenharmony_civoid set_nobody(void) 100f08c3bdfSopenharmony_ci{ 101f08c3bdfSopenharmony_ci SAFE_SETEUID(nobody_uid); 102f08c3bdfSopenharmony_ci} 103f08c3bdfSopenharmony_ci 104f08c3bdfSopenharmony_civoid setup(void) 105f08c3bdfSopenharmony_ci{ 106f08c3bdfSopenharmony_ci struct passwd *nobody; 107f08c3bdfSopenharmony_ci unsigned int i; 108f08c3bdfSopenharmony_ci 109f08c3bdfSopenharmony_ci nobody = SAFE_GETPWNAM("nobody"); 110f08c3bdfSopenharmony_ci nobody_uid = nobody->pw_uid; 111f08c3bdfSopenharmony_ci 112f08c3bdfSopenharmony_ci bad_addr = SAFE_MMAP(0, 1, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); 113f08c3bdfSopenharmony_ci 114f08c3bdfSopenharmony_ci for (i = 0; i < ARRAY_SIZE(tc); i++) { 115f08c3bdfSopenharmony_ci if (!tc[i].pathname) 116f08c3bdfSopenharmony_ci tc[i].pathname = bad_addr; 117f08c3bdfSopenharmony_ci } 118f08c3bdfSopenharmony_ci 119f08c3bdfSopenharmony_ci SAFE_TOUCH(TEST_FILE1, 0666, NULL); 120f08c3bdfSopenharmony_ci SAFE_MKDIR(DIR_TEMP, MODE_RWX); 121f08c3bdfSopenharmony_ci SAFE_TOUCH(TEST_FILE2, 0666, NULL); 122f08c3bdfSopenharmony_ci SAFE_CHMOD(DIR_TEMP, FILE_MODE); 123f08c3bdfSopenharmony_ci SAFE_TOUCH("t_file", MODE_RWX, NULL); 124f08c3bdfSopenharmony_ci 125f08c3bdfSopenharmony_ci memset(long_path, 'a', PATH_MAX+1); 126f08c3bdfSopenharmony_ci 127f08c3bdfSopenharmony_ci /* 128f08c3bdfSopenharmony_ci * create two symbolic links who point to each other for 129f08c3bdfSopenharmony_ci * test ELOOP. 130f08c3bdfSopenharmony_ci */ 131f08c3bdfSopenharmony_ci SAFE_SYMLINK("test_file4", "test_file5"); 132f08c3bdfSopenharmony_ci SAFE_SYMLINK("test_file5", "test_file4"); 133f08c3bdfSopenharmony_ci} 134f08c3bdfSopenharmony_ci 135f08c3bdfSopenharmony_cistatic void cleanup(void) 136f08c3bdfSopenharmony_ci{ 137f08c3bdfSopenharmony_ci SAFE_CHMOD(DIR_TEMP, MODE_RWX); 138f08c3bdfSopenharmony_ci} 139f08c3bdfSopenharmony_ci 140f08c3bdfSopenharmony_cistatic struct tst_test test = { 141f08c3bdfSopenharmony_ci .setup = setup, 142f08c3bdfSopenharmony_ci .cleanup = cleanup, 143f08c3bdfSopenharmony_ci .test = run, 144f08c3bdfSopenharmony_ci .tcnt = ARRAY_SIZE(tc), 145f08c3bdfSopenharmony_ci .needs_root = 1, 146f08c3bdfSopenharmony_ci .needs_rofs = 1, 147f08c3bdfSopenharmony_ci .mntpoint = MNT_POINT, 148f08c3bdfSopenharmony_ci}; 149