// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) International Business Machines Corp., 2002 * Copyright (c) Linux Test Project, 2003-2023 * 12/03/2002 Port to LTP robbiew@us.ibm.com * 06/30/2001 Port to Linux nsharoff@us.ibm.com */ /*\ * [Description] * * Verify that acct() returns proper errno on failure. */ #include #include #include #include #include #include #include #include #include #include "tst_test.h" #define DIR_MODE (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP| \ S_IXGRP|S_IROTH|S_IXOTH) #define FILE_EISDIR "." #define FILE_EACCESS "/dev/null" #define FILE_ENOENT "/tmp/does/not/exist" #define FILE_ENOTDIR "./tmpfile/" #define FILE_TMPFILE "./tmpfile" #define FILE_ELOOP "test_file_eloop1" #define FILE_EROFS "ro_mntpoint/file" static struct passwd *ltpuser; static char *file_eisdir; static char *file_eaccess; static char *file_enoent; static char *file_enotdir; static char *file_tmpfile; static char *file_eloop; static char *file_enametoolong; static char *file_erofs; static char *file_null; static void setup_euid(void) { SAFE_SETEUID(ltpuser->pw_uid); } static void cleanup_euid(void) { SAFE_SETEUID(0); } static struct test_case { char **filename; char *desc; int exp_errno; void (*setupfunc) (); void (*cleanfunc) (); } tcases[] = { {&file_eisdir, FILE_EISDIR, EISDIR, NULL, NULL}, {&file_eaccess, FILE_EACCESS, EACCES, NULL, NULL}, {&file_enoent, FILE_ENOENT, ENOENT, NULL, NULL}, {&file_enotdir, FILE_ENOTDIR, ENOTDIR, NULL, NULL}, {&file_tmpfile, FILE_TMPFILE, EPERM, setup_euid, cleanup_euid}, {&file_null, "NULL", EPERM, setup_euid, cleanup_euid}, {&file_eloop, FILE_ELOOP, ELOOP, NULL, NULL}, {&file_enametoolong, "aaaa...", ENAMETOOLONG, NULL, NULL}, {&file_erofs, FILE_EROFS, EROFS, NULL, NULL}, }; static void setup(void) { int fd; TEST(acct(NULL)); if (TST_RET == -1 && TST_ERR == ENOSYS) tst_brk(TCONF, "acct() system call isn't configured in kernel"); ltpuser = SAFE_GETPWNAM("nobody"); fd = SAFE_CREAT(FILE_TMPFILE, 0777); SAFE_CLOSE(fd); TEST(acct(FILE_TMPFILE)); if (TST_RET == -1) tst_brk(TBROK | TTERRNO, "acct failed unexpectedly"); /* turn off acct, so we are in a known state */ TEST(acct(NULL)); if (TST_RET == -1) tst_brk(TBROK | TTERRNO, "acct(NULL) failed"); /* ELOOP SETTING */ SAFE_SYMLINK(FILE_ELOOP, "test_file_eloop2"); SAFE_SYMLINK("test_file_eloop2", FILE_ELOOP); memset(file_enametoolong, 'a', PATH_MAX+1); file_enametoolong[PATH_MAX+1] = 0; } static void verify_acct(unsigned int nr) { struct test_case *tcase = &tcases[nr]; if (tcase->setupfunc) tcase->setupfunc(); TST_EXP_FAIL(acct(*tcase->filename), tcase->exp_errno, "acct(%s)", tcase->desc); if (tcase->cleanfunc) tcase->cleanfunc(); } static struct tst_test test = { .needs_root = 1, .mntpoint = "ro_mntpoint", .needs_rofs = 1, .tcnt = ARRAY_SIZE(tcases), .setup = setup, .test = verify_acct, .bufs = (struct tst_buffers []) { {&file_eisdir, .str = FILE_EISDIR}, {&file_eaccess, .str = FILE_EACCESS}, {&file_enoent, .str = FILE_ENOENT}, {&file_enotdir, .str = FILE_ENOTDIR}, {&file_tmpfile, .str = FILE_TMPFILE}, {&file_eloop, .str = FILE_ELOOP}, {&file_enametoolong, .size = PATH_MAX+2}, {&file_erofs, .str = FILE_EROFS}, {} } };