xref: /aosp_15_r20/external/ltp/testcases/kernel/syscalls/acct/acct01.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
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