// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) International Business Machines Corp., 2001 * 07/2001 ported by John George * Copyright (C) 2021 SUSE LLC */ /*\ * [Description] * * Verify that the system call utime() successfully sets the modification * and access times of a file to the current time, under the following * constraints: * * - The times argument is NULL. * - The user ID of the process is not "root". * - The file is not owned by the user ID of the process. * - The user ID of the process has write access to the file. */ #include #include #include #include "tst_test.h" #include "tst_uid.h" #include "tst_clocks.h" #define MNTPOINT "mntpoint" #define TEMP_FILE MNTPOINT"/tmp_file" #define FILE_MODE 0766 static uid_t root_uid, user_uid; static void setup(void) { struct passwd *pw; uid_t test_users[2]; int fd; root_uid = getuid(); pw = SAFE_GETPWNAM("nobody"); test_users[0] = pw->pw_uid; tst_get_uids(test_users, 1, 2); user_uid = test_users[1]; fd = SAFE_CREAT(TEMP_FILE, FILE_MODE); SAFE_CLOSE(fd); /* Override umask */ SAFE_CHMOD(TEMP_FILE, FILE_MODE); SAFE_CHOWN(TEMP_FILE, pw->pw_uid, pw->pw_gid); } static void run(void) { struct utimbuf utbuf; struct stat statbuf; time_t mintime, maxtime; utbuf.modtime = time(0) - 5; utbuf.actime = utbuf.modtime + 1; TST_EXP_PASS_SILENT(utime(TEMP_FILE, &utbuf)); SAFE_STAT(TEMP_FILE, &statbuf); if (statbuf.st_atime != utbuf.actime || statbuf.st_mtime != utbuf.modtime) { tst_res(TFAIL, "Could not set initial file times"); return; } SAFE_SETEUID(user_uid); mintime = tst_get_fs_timestamp(); TST_EXP_PASS(utime(TEMP_FILE, NULL)); maxtime = tst_get_fs_timestamp(); SAFE_SETEUID(root_uid); SAFE_STAT(TEMP_FILE, &statbuf); if (statbuf.st_atime < mintime || statbuf.st_atime > maxtime) tst_res(TFAIL, "utime() did not set expected atime, " "mintime: %ld, maxtime: %ld, st_atime: %ld", mintime, maxtime, statbuf.st_atime); if (statbuf.st_mtime < mintime || statbuf.st_mtime > maxtime) tst_res(TFAIL, "utime() did not set expected mtime, " "mintime: %ld, maxtime: %ld, st_mtime: %ld", mintime, maxtime, statbuf.st_mtime); } static struct tst_test test = { .test_all = run, .setup = setup, .needs_root = 1, .mount_device = 1, .mntpoint = MNTPOINT, .all_filesystems = 1, .skip_filesystems = (const char *const[]) { "vfat", "exfat", NULL } };