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     robbiew@us.ibm.com
7  * 06/30/2001	Port to Linux	nsharoff@us.ibm.com
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	0755
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 #define FILE_EFAULT		"invalid/file/name"
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 static char *file_efault;
50 
setup_euid(void)51 static void setup_euid(void)
52 {
53 	SAFE_SETEUID(ltpuser->pw_uid);
54 }
55 
cleanup_euid(void)56 static void cleanup_euid(void)
57 {
58 	SAFE_SETEUID(0);
59 }
60 
setup_emem(void)61 static void setup_emem(void)
62 {
63 	file_efault = SAFE_MMAP(NULL, 1, PROT_NONE,
64 			MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
65 }
cleanup_emem(void)66 static void cleanup_emem(void)
67 {
68 	SAFE_MUNMAP(file_efault, 1);
69 }
70 
71 static struct test_case {
72 	char **filename;
73 	char *desc;
74 	int exp_errno;
75 	void (*setupfunc)();
76 	void (*cleanfunc)();
77 } tcases[] = {
78 	{&file_eisdir,  FILE_EISDIR,  EISDIR,  NULL,   NULL},
79 	{&file_eaccess, FILE_EACCESS, EACCES,  NULL,   NULL},
80 	{&file_enoent,  FILE_ENOENT,  ENOENT,  NULL,   NULL},
81 	{&file_enotdir, FILE_ENOTDIR, ENOTDIR, NULL,   NULL},
82 	{&file_tmpfile, FILE_TMPFILE, EPERM,   setup_euid, cleanup_euid},
83 	{&file_null,    "NULL",       EPERM,   setup_euid, cleanup_euid},
84 	{&file_eloop,   FILE_ELOOP,   ELOOP,        NULL, NULL},
85 	{&file_enametoolong, "aaaa...", ENAMETOOLONG, NULL, NULL},
86 	{&file_erofs,   FILE_EROFS,   EROFS,        NULL, NULL},
87 	{&file_efault,	"Invalid address",  EFAULT,  setup_emem, cleanup_emem},
88 };
89 
setup(void)90 static void setup(void)
91 {
92 	int fd;
93 
94 	TEST(acct(NULL));
95 
96 	ltpuser = SAFE_GETPWNAM("nobody");
97 
98 	fd = SAFE_CREAT(FILE_TMPFILE, 0777);
99 	SAFE_CLOSE(fd);
100 
101 	TEST(acct(FILE_TMPFILE));
102 	if (TST_RET == -1)
103 		tst_brk(TBROK | TTERRNO, "acct failed unexpectedly");
104 
105 	/* turn off acct, so we are in a known state */
106 	TEST(acct(NULL));
107 	if (TST_RET == -1)
108 		tst_brk(TBROK | TTERRNO, "acct(NULL) failed");
109 
110 	/* ELOOP SETTING */
111 	SAFE_SYMLINK(FILE_ELOOP, "test_file_eloop2");
112 	SAFE_SYMLINK("test_file_eloop2", FILE_ELOOP);
113 
114 	memset(file_enametoolong, 'a', PATH_MAX+1);
115 	file_enametoolong[PATH_MAX+1] = 0;
116 }
117 
verify_acct(unsigned int nr)118 static void verify_acct(unsigned int nr)
119 {
120 	struct test_case *tcase = &tcases[nr];
121 
122 	if (tcase->setupfunc)
123 		tcase->setupfunc();
124 
125 	TST_EXP_FAIL(acct(*tcase->filename), tcase->exp_errno,
126 		"acct(%s)", tcase->desc);
127 
128 	if (tcase->cleanfunc)
129 		tcase->cleanfunc();
130 }
131 
132 static struct tst_test test = {
133 	.needs_root = 1,
134 	.mntpoint = "ro_mntpoint",
135 	.needs_rofs = 1,
136 	.tcnt = ARRAY_SIZE(tcases),
137 	.setup = setup,
138 	.test = verify_acct,
139 	.bufs = (struct tst_buffers []) {
140 		{&file_eisdir, .str = FILE_EISDIR},
141 		{&file_eaccess, .str = FILE_EACCESS},
142 		{&file_enoent, .str = FILE_ENOENT},
143 		{&file_enotdir, .str = FILE_ENOTDIR},
144 		{&file_tmpfile, .str = FILE_TMPFILE},
145 		{&file_eloop, .str = FILE_ELOOP},
146 		{&file_enametoolong, .size = PATH_MAX+2},
147 		{&file_erofs, .str = FILE_EROFS},
148 		{}
149 	},
150 	.needs_kconfigs = (const char *[]) {
151 		"CONFIG_BSD_PROCESS_ACCT=y",
152 		NULL,
153 	}
154 };
155