1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /*
4 * Copyright (c) International Business Machines Corp., 2002
5 * Copyright (c) Linux Test Project, 2003-2023
6 * 12/03/2002 Port to LTP [email protected]
7 * 06/30/2001 Port to Linux [email protected]
8 */
9
10 /*\
11 * [Description]
12 *
13 * Verify that acct() returns proper errno on failure.
14 */
15
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <pwd.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <sys/mount.h>
25
26 #include "tst_test.h"
27
28 #define DIR_MODE (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP| \
29 S_IXGRP|S_IROTH|S_IXOTH)
30 #define FILE_EISDIR "."
31 #define FILE_EACCESS "/dev/null"
32 #define FILE_ENOENT "/tmp/does/not/exist"
33 #define FILE_ENOTDIR "./tmpfile/"
34 #define FILE_TMPFILE "./tmpfile"
35 #define FILE_ELOOP "test_file_eloop1"
36 #define FILE_EROFS "ro_mntpoint/file"
37
38 static struct passwd *ltpuser;
39
40 static char *file_eisdir;
41 static char *file_eaccess;
42 static char *file_enoent;
43 static char *file_enotdir;
44 static char *file_tmpfile;
45 static char *file_eloop;
46 static char *file_enametoolong;
47 static char *file_erofs;
48 static char *file_null;
49
setup_euid(void)50 static void setup_euid(void)
51 {
52 SAFE_SETEUID(ltpuser->pw_uid);
53 }
54
cleanup_euid(void)55 static void cleanup_euid(void)
56 {
57 SAFE_SETEUID(0);
58 }
59
60 static struct test_case {
61 char **filename;
62 char *desc;
63 int exp_errno;
64 void (*setupfunc) ();
65 void (*cleanfunc) ();
66 } tcases[] = {
67 {&file_eisdir, FILE_EISDIR, EISDIR, NULL, NULL},
68 {&file_eaccess, FILE_EACCESS, EACCES, NULL, NULL},
69 {&file_enoent, FILE_ENOENT, ENOENT, NULL, NULL},
70 {&file_enotdir, FILE_ENOTDIR, ENOTDIR, NULL, NULL},
71 {&file_tmpfile, FILE_TMPFILE, EPERM, setup_euid, cleanup_euid},
72 {&file_null, "NULL", EPERM, setup_euid, cleanup_euid},
73 {&file_eloop, FILE_ELOOP, ELOOP, NULL, NULL},
74 {&file_enametoolong, "aaaa...", ENAMETOOLONG, NULL, NULL},
75 {&file_erofs, FILE_EROFS, EROFS, NULL, NULL},
76 };
77
setup(void)78 static void setup(void)
79 {
80 int fd;
81
82 TEST(acct(NULL));
83 if (TST_RET == -1 && TST_ERR == ENOSYS)
84 tst_brk(TCONF, "acct() system call isn't configured in kernel");
85
86 ltpuser = SAFE_GETPWNAM("nobody");
87
88 fd = SAFE_CREAT(FILE_TMPFILE, 0777);
89 SAFE_CLOSE(fd);
90
91 TEST(acct(FILE_TMPFILE));
92 if (TST_RET == -1)
93 tst_brk(TBROK | TTERRNO, "acct failed unexpectedly");
94
95 /* turn off acct, so we are in a known state */
96 TEST(acct(NULL));
97 if (TST_RET == -1)
98 tst_brk(TBROK | TTERRNO, "acct(NULL) failed");
99
100 /* ELOOP SETTING */
101 SAFE_SYMLINK(FILE_ELOOP, "test_file_eloop2");
102 SAFE_SYMLINK("test_file_eloop2", FILE_ELOOP);
103
104 memset(file_enametoolong, 'a', PATH_MAX+1);
105 file_enametoolong[PATH_MAX+1] = 0;
106 }
107
verify_acct(unsigned int nr)108 static void verify_acct(unsigned int nr)
109 {
110 struct test_case *tcase = &tcases[nr];
111
112 if (tcase->setupfunc)
113 tcase->setupfunc();
114
115 TST_EXP_FAIL(acct(*tcase->filename), tcase->exp_errno,
116 "acct(%s)", tcase->desc);
117
118 if (tcase->cleanfunc)
119 tcase->cleanfunc();
120 }
121
122 static struct tst_test test = {
123 .needs_root = 1,
124 .mntpoint = "ro_mntpoint",
125 .needs_rofs = 1,
126 .tcnt = ARRAY_SIZE(tcases),
127 .setup = setup,
128 .test = verify_acct,
129 .bufs = (struct tst_buffers []) {
130 {&file_eisdir, .str = FILE_EISDIR},
131 {&file_eaccess, .str = FILE_EACCESS},
132 {&file_enoent, .str = FILE_ENOENT},
133 {&file_enotdir, .str = FILE_ENOTDIR},
134 {&file_tmpfile, .str = FILE_TMPFILE},
135 {&file_eloop, .str = FILE_ELOOP},
136 {&file_enametoolong, .size = PATH_MAX+2},
137 {&file_erofs, .str = FILE_EROFS},
138 {}
139 }
140 };
141