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