1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) Linux Test Project, 2022 4f08c3bdfSopenharmony_ci * Copyright (c) Wipro Technologies Ltd, 2002. All Rights Reserved. 5f08c3bdfSopenharmony_ci */ 6f08c3bdfSopenharmony_ci 7f08c3bdfSopenharmony_ci/*\ 8f08c3bdfSopenharmony_ci * [Description] 9f08c3bdfSopenharmony_ci * 10f08c3bdfSopenharmony_ci * Check mount(2) system call with various flags. 11f08c3bdfSopenharmony_ci * 12f08c3bdfSopenharmony_ci * Verify that mount(2) syscall passes for each flag setting and validate 13f08c3bdfSopenharmony_ci * the flags: 14f08c3bdfSopenharmony_ci * 15f08c3bdfSopenharmony_ci * - MS_RDONLY - mount read-only 16f08c3bdfSopenharmony_ci * - MS_NODEV - disallow access to device special files 17f08c3bdfSopenharmony_ci * - MS_NOEXEC - disallow program execution 18f08c3bdfSopenharmony_ci * - MS_REMOUNT - alter flags of a mounted FS 19f08c3bdfSopenharmony_ci * - MS_NOSUID - ignore suid and sgid bits 20f08c3bdfSopenharmony_ci * - MS_NOATIME - do not update access times 21f08c3bdfSopenharmony_ci * - MS_NODIRATIME - only update access_time for directory instead of all types 22f08c3bdfSopenharmony_ci * - MS_STRICTATIME - always update access times 23f08c3bdfSopenharmony_ci */ 24f08c3bdfSopenharmony_ci 25f08c3bdfSopenharmony_ci#include <stdio.h> 26f08c3bdfSopenharmony_ci#include <stdlib.h> 27f08c3bdfSopenharmony_ci#include <sys/types.h> 28f08c3bdfSopenharmony_ci#include <sys/wait.h> 29f08c3bdfSopenharmony_ci#include <sys/vfs.h> 30f08c3bdfSopenharmony_ci#include <pwd.h> 31f08c3bdfSopenharmony_ci#include "tst_test.h" 32f08c3bdfSopenharmony_ci#include "lapi/mount.h" 33f08c3bdfSopenharmony_ci 34f08c3bdfSopenharmony_ci#define MNTPOINT "mntpoint" 35f08c3bdfSopenharmony_ci#define TESTBIN "mount03_suid_child" 36f08c3bdfSopenharmony_ci#define BIN_PATH MNTPOINT "/" TESTBIN 37f08c3bdfSopenharmony_ci#define TEST_STR "abcdefghijklmnopqrstuvwxyz" 38f08c3bdfSopenharmony_ci#define FILE_MODE 0644 39f08c3bdfSopenharmony_ci#define SUID_MODE (0511 | S_ISUID) 40f08c3bdfSopenharmony_ci 41f08c3bdfSopenharmony_ci#define CHECK_ENOENT(x) ((x) == -1 && errno == ENOENT) 42f08c3bdfSopenharmony_ci 43f08c3bdfSopenharmony_cistatic int otfd; 44f08c3bdfSopenharmony_cistatic char file[PATH_MAX]; 45f08c3bdfSopenharmony_cistatic char dir[PATH_MAX]; 46f08c3bdfSopenharmony_cistatic uid_t nobody_uid; 47f08c3bdfSopenharmony_cistatic gid_t nobody_gid; 48f08c3bdfSopenharmony_ci 49f08c3bdfSopenharmony_cistatic void test_rdonly(void) 50f08c3bdfSopenharmony_ci{ 51f08c3bdfSopenharmony_ci snprintf(file, PATH_MAX, "%s/rdonly", MNTPOINT); 52f08c3bdfSopenharmony_ci TST_EXP_FAIL(otfd = open(file, O_CREAT | O_RDWR, 0700), EROFS); 53f08c3bdfSopenharmony_ci} 54f08c3bdfSopenharmony_ci 55f08c3bdfSopenharmony_cistatic void test_nodev(void) 56f08c3bdfSopenharmony_ci{ 57f08c3bdfSopenharmony_ci snprintf(file, PATH_MAX, "%s/nodev", MNTPOINT); 58f08c3bdfSopenharmony_ci SAFE_MKNOD(file, S_IFBLK | 0777, 0); 59f08c3bdfSopenharmony_ci TST_EXP_FAIL(otfd = open(file, O_RDWR, 0700), EACCES); 60f08c3bdfSopenharmony_ci SAFE_UNLINK(file); 61f08c3bdfSopenharmony_ci} 62f08c3bdfSopenharmony_ci 63f08c3bdfSopenharmony_cistatic void test_noexec(void) 64f08c3bdfSopenharmony_ci{ 65f08c3bdfSopenharmony_ci snprintf(file, PATH_MAX, "%s/noexec", MNTPOINT); 66f08c3bdfSopenharmony_ci otfd = SAFE_OPEN(file, O_CREAT | O_RDWR, 0700); 67f08c3bdfSopenharmony_ci TST_EXP_FAIL(execlp(file, basename(file), NULL), EACCES); 68f08c3bdfSopenharmony_ci} 69f08c3bdfSopenharmony_ci 70f08c3bdfSopenharmony_cistatic void test_remount(void) 71f08c3bdfSopenharmony_ci{ 72f08c3bdfSopenharmony_ci SAFE_MOUNT(tst_device->dev, MNTPOINT, tst_device->fs_type, MS_REMOUNT, NULL); 73f08c3bdfSopenharmony_ci snprintf(file, PATH_MAX, "%s/remount", MNTPOINT); 74f08c3bdfSopenharmony_ci TST_EXP_FD(otfd = open(file, O_CREAT | O_RDWR, 0700)); 75f08c3bdfSopenharmony_ci} 76f08c3bdfSopenharmony_ci 77f08c3bdfSopenharmony_cistatic void test_nosuid(void) 78f08c3bdfSopenharmony_ci{ 79f08c3bdfSopenharmony_ci int ret; 80f08c3bdfSopenharmony_ci struct stat st; 81f08c3bdfSopenharmony_ci 82f08c3bdfSopenharmony_ci if (!SAFE_FORK()) { 83f08c3bdfSopenharmony_ci SAFE_CP(TESTBIN, BIN_PATH); 84f08c3bdfSopenharmony_ci 85f08c3bdfSopenharmony_ci ret = TST_RETRY_FN_EXP_BACKOFF(access(BIN_PATH, F_OK), !CHECK_ENOENT, 15); 86f08c3bdfSopenharmony_ci if (CHECK_ENOENT(ret)) 87f08c3bdfSopenharmony_ci tst_brk(TBROK, "Timeout, %s does not exist", BIN_PATH); 88f08c3bdfSopenharmony_ci 89f08c3bdfSopenharmony_ci SAFE_STAT(BIN_PATH, &st); 90f08c3bdfSopenharmony_ci if (st.st_mode != SUID_MODE) 91f08c3bdfSopenharmony_ci SAFE_CHMOD(BIN_PATH, SUID_MODE); 92f08c3bdfSopenharmony_ci 93f08c3bdfSopenharmony_ci SAFE_SETREUID(nobody_uid, nobody_uid); 94f08c3bdfSopenharmony_ci SAFE_EXECL(BIN_PATH, BIN_PATH, NULL); 95f08c3bdfSopenharmony_ci tst_brk(TFAIL | TTERRNO, "Failed to execute %s", BIN_PATH); 96f08c3bdfSopenharmony_ci } 97f08c3bdfSopenharmony_ci 98f08c3bdfSopenharmony_ci tst_reap_children(); 99f08c3bdfSopenharmony_ci} 100f08c3bdfSopenharmony_ci 101f08c3bdfSopenharmony_cistatic void test_file_dir_noatime(int update_fatime, int update_datime) 102f08c3bdfSopenharmony_ci{ 103f08c3bdfSopenharmony_ci time_t atime, dir_atime; 104f08c3bdfSopenharmony_ci struct stat st, dir_st; 105f08c3bdfSopenharmony_ci char readbuf[20]; 106f08c3bdfSopenharmony_ci DIR *test_dir; 107f08c3bdfSopenharmony_ci 108f08c3bdfSopenharmony_ci snprintf(file, PATH_MAX, "%s/noatime", MNTPOINT); 109f08c3bdfSopenharmony_ci TST_EXP_FD_SILENT(otfd = open(file, O_CREAT | O_RDWR, 0700)); 110f08c3bdfSopenharmony_ci 111f08c3bdfSopenharmony_ci snprintf(dir, PATH_MAX, "%s/nodiratime", MNTPOINT); 112f08c3bdfSopenharmony_ci if (access(dir, F_OK) == -1 && errno == ENOENT) 113f08c3bdfSopenharmony_ci SAFE_MKDIR(dir, 0700); 114f08c3bdfSopenharmony_ci 115f08c3bdfSopenharmony_ci SAFE_WRITE(1, otfd, TEST_STR, strlen(TEST_STR)); 116f08c3bdfSopenharmony_ci SAFE_FSTAT(otfd, &st); 117f08c3bdfSopenharmony_ci atime = st.st_atime; 118f08c3bdfSopenharmony_ci 119f08c3bdfSopenharmony_ci test_dir = SAFE_OPENDIR(dir); 120f08c3bdfSopenharmony_ci SAFE_STAT(dir, &dir_st); 121f08c3bdfSopenharmony_ci SAFE_READDIR(test_dir); 122f08c3bdfSopenharmony_ci SAFE_CLOSEDIR(test_dir); 123f08c3bdfSopenharmony_ci dir_atime = dir_st.st_atime; 124f08c3bdfSopenharmony_ci 125f08c3bdfSopenharmony_ci usleep(1001000); 126f08c3bdfSopenharmony_ci 127f08c3bdfSopenharmony_ci SAFE_READ(0, otfd, readbuf, sizeof(readbuf)); 128f08c3bdfSopenharmony_ci SAFE_FSTAT(otfd, &st); 129f08c3bdfSopenharmony_ci 130f08c3bdfSopenharmony_ci test_dir = SAFE_OPENDIR(dir); 131f08c3bdfSopenharmony_ci SAFE_READDIR(test_dir); 132f08c3bdfSopenharmony_ci SAFE_CLOSEDIR(test_dir); 133f08c3bdfSopenharmony_ci SAFE_STAT(dir, &dir_st); 134f08c3bdfSopenharmony_ci 135f08c3bdfSopenharmony_ci if (update_fatime) { 136f08c3bdfSopenharmony_ci if (st.st_atime > atime) 137f08c3bdfSopenharmony_ci tst_res(TPASS, "st.st_atime(%ld) > atime(%ld)", 138f08c3bdfSopenharmony_ci st.st_atime, atime); 139f08c3bdfSopenharmony_ci else 140f08c3bdfSopenharmony_ci tst_res(TFAIL, "st.st_atime(%ld) < atime(%ld)", 141f08c3bdfSopenharmony_ci st.st_atime, atime); 142f08c3bdfSopenharmony_ci } else { 143f08c3bdfSopenharmony_ci TST_EXP_EQ_LI(st.st_atime, atime); 144f08c3bdfSopenharmony_ci } 145f08c3bdfSopenharmony_ci 146f08c3bdfSopenharmony_ci if (update_datime) { 147f08c3bdfSopenharmony_ci if (dir_st.st_atime > dir_atime) 148f08c3bdfSopenharmony_ci tst_res(TPASS, "dir_st.st_atime(%ld) > dir_atime(%ld)", 149f08c3bdfSopenharmony_ci dir_st.st_atime, dir_atime); 150f08c3bdfSopenharmony_ci else 151f08c3bdfSopenharmony_ci tst_res(TFAIL, "dir_st.st_atime(%ld) < dir_atime(%ld)", 152f08c3bdfSopenharmony_ci dir_st.st_atime, dir_atime); 153f08c3bdfSopenharmony_ci } else { 154f08c3bdfSopenharmony_ci TST_EXP_EQ_LI(dir_st.st_atime, dir_atime); 155f08c3bdfSopenharmony_ci } 156f08c3bdfSopenharmony_ci} 157f08c3bdfSopenharmony_ci 158f08c3bdfSopenharmony_cistatic void test_noatime(void) 159f08c3bdfSopenharmony_ci{ 160f08c3bdfSopenharmony_ci test_file_dir_noatime(0, 0); 161f08c3bdfSopenharmony_ci} 162f08c3bdfSopenharmony_ci 163f08c3bdfSopenharmony_cistatic void test_nodiratime(void) 164f08c3bdfSopenharmony_ci{ 165f08c3bdfSopenharmony_ci test_file_dir_noatime(1, 0); 166f08c3bdfSopenharmony_ci} 167f08c3bdfSopenharmony_ci 168f08c3bdfSopenharmony_cistatic void test_strictatime(void) 169f08c3bdfSopenharmony_ci{ 170f08c3bdfSopenharmony_ci test_file_dir_noatime(1, 1); 171f08c3bdfSopenharmony_ci} 172f08c3bdfSopenharmony_ci 173f08c3bdfSopenharmony_ci#define FLAG_DESC(x) .flag = x, .flag2 = x, .desc = #x 174f08c3bdfSopenharmony_ci#define FLAG_DESC2(x) .flag2 = x, .desc = #x 175f08c3bdfSopenharmony_cistatic struct tcase { 176f08c3bdfSopenharmony_ci unsigned int flag; 177f08c3bdfSopenharmony_ci unsigned int flag2; 178f08c3bdfSopenharmony_ci char *desc; 179f08c3bdfSopenharmony_ci void (*test)(void); 180f08c3bdfSopenharmony_ci} tcases[] = { 181f08c3bdfSopenharmony_ci {FLAG_DESC(MS_RDONLY), test_rdonly}, 182f08c3bdfSopenharmony_ci {FLAG_DESC(MS_NODEV), test_nodev}, 183f08c3bdfSopenharmony_ci {FLAG_DESC(MS_NOEXEC), test_noexec}, 184f08c3bdfSopenharmony_ci {MS_RDONLY, FLAG_DESC2(MS_REMOUNT), test_remount}, 185f08c3bdfSopenharmony_ci {FLAG_DESC(MS_NOSUID), test_nosuid}, 186f08c3bdfSopenharmony_ci {FLAG_DESC(MS_NOATIME), test_noatime}, 187f08c3bdfSopenharmony_ci {FLAG_DESC(MS_NODIRATIME), test_nodiratime}, 188f08c3bdfSopenharmony_ci {FLAG_DESC(MS_STRICTATIME), test_strictatime} 189f08c3bdfSopenharmony_ci}; 190f08c3bdfSopenharmony_ci 191f08c3bdfSopenharmony_cistatic void setup(void) 192f08c3bdfSopenharmony_ci{ 193f08c3bdfSopenharmony_ci struct passwd *ltpuser = SAFE_GETPWNAM("nobody"); 194f08c3bdfSopenharmony_ci 195f08c3bdfSopenharmony_ci nobody_uid = ltpuser->pw_uid; 196f08c3bdfSopenharmony_ci nobody_gid = ltpuser->pw_gid; 197f08c3bdfSopenharmony_ci} 198f08c3bdfSopenharmony_ci 199f08c3bdfSopenharmony_cistatic void cleanup(void) 200f08c3bdfSopenharmony_ci{ 201f08c3bdfSopenharmony_ci if (otfd >= 0) 202f08c3bdfSopenharmony_ci SAFE_CLOSE(otfd); 203f08c3bdfSopenharmony_ci 204f08c3bdfSopenharmony_ci if (tst_is_mounted(MNTPOINT)) 205f08c3bdfSopenharmony_ci SAFE_UMOUNT(MNTPOINT); 206f08c3bdfSopenharmony_ci} 207f08c3bdfSopenharmony_ci 208f08c3bdfSopenharmony_ci 209f08c3bdfSopenharmony_cistatic void run(unsigned int n) 210f08c3bdfSopenharmony_ci{ 211f08c3bdfSopenharmony_ci struct tcase *tc = &tcases[n]; 212f08c3bdfSopenharmony_ci struct statfs stfs; 213f08c3bdfSopenharmony_ci 214f08c3bdfSopenharmony_ci tst_res(TINFO, "Testing flag %s", tc->desc); 215f08c3bdfSopenharmony_ci 216f08c3bdfSopenharmony_ci TST_EXP_PASS_SILENT(mount(tst_device->dev, MNTPOINT, tst_device->fs_type, 217f08c3bdfSopenharmony_ci tc->flag, NULL)); 218f08c3bdfSopenharmony_ci if (!TST_PASS) 219f08c3bdfSopenharmony_ci return; 220f08c3bdfSopenharmony_ci 221f08c3bdfSopenharmony_ci if (tc->test) 222f08c3bdfSopenharmony_ci tc->test(); 223f08c3bdfSopenharmony_ci 224f08c3bdfSopenharmony_ci SAFE_STATFS(MNTPOINT, &stfs); 225f08c3bdfSopenharmony_ci if (tc->flag == MS_STRICTATIME) { 226f08c3bdfSopenharmony_ci if (stfs.f_flags & (MS_NOATIME | MS_RELATIME)) 227f08c3bdfSopenharmony_ci tst_res(TFAIL, "statfs() gets the incorrect mount flag"); 228f08c3bdfSopenharmony_ci else 229f08c3bdfSopenharmony_ci tst_res(TPASS, "statfs() gets the correct mount flag"); 230f08c3bdfSopenharmony_ci cleanup(); 231f08c3bdfSopenharmony_ci return; 232f08c3bdfSopenharmony_ci } 233f08c3bdfSopenharmony_ci 234f08c3bdfSopenharmony_ci if (stfs.f_flags & tc->flag2) 235f08c3bdfSopenharmony_ci tst_res(TPASS, "statfs() gets the correct mount flag"); 236f08c3bdfSopenharmony_ci else 237f08c3bdfSopenharmony_ci tst_res(TFAIL, "statfs() gets the incorrect mount flag"); 238f08c3bdfSopenharmony_ci 239f08c3bdfSopenharmony_ci cleanup(); 240f08c3bdfSopenharmony_ci} 241f08c3bdfSopenharmony_ci 242f08c3bdfSopenharmony_cistatic struct tst_test test = { 243f08c3bdfSopenharmony_ci .tcnt = ARRAY_SIZE(tcases), 244f08c3bdfSopenharmony_ci .test = run, 245f08c3bdfSopenharmony_ci .setup = setup, 246f08c3bdfSopenharmony_ci .cleanup = cleanup, 247f08c3bdfSopenharmony_ci .needs_root = 1, 248f08c3bdfSopenharmony_ci .format_device = 1, 249f08c3bdfSopenharmony_ci .resource_files = (const char *const[]) { 250f08c3bdfSopenharmony_ci TESTBIN, 251f08c3bdfSopenharmony_ci NULL, 252f08c3bdfSopenharmony_ci }, 253f08c3bdfSopenharmony_ci .forks_child = 1, 254f08c3bdfSopenharmony_ci .child_needs_reinit = 1, 255f08c3bdfSopenharmony_ci .mntpoint = MNTPOINT, 256f08c3bdfSopenharmony_ci .all_filesystems = 1, 257f08c3bdfSopenharmony_ci .skip_filesystems = (const char *const []){ 258f08c3bdfSopenharmony_ci "exfat", 259f08c3bdfSopenharmony_ci "vfat", 260f08c3bdfSopenharmony_ci "ntfs", 261f08c3bdfSopenharmony_ci NULL 262f08c3bdfSopenharmony_ci }, 263f08c3bdfSopenharmony_ci}; 264