xref: /freebsd/tests/sys/audit/file-attribute-access.c (revision 2b6fe1b2da8fcf8e8b075c4e653ab2c65bdc00a8)
1 /*-
2  * Copyright (c) 2018 Aniket Pandey
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * SUCH DAMAGE.
24  *
25  * $FreeBSD$
26  */
27 
28 #include <sys/stat.h>
29 #include <sys/syscall.h>
30 
31 #include <atf-c.h>
32 #include <fcntl.h>
33 #include <unistd.h>
34 
35 #include "utils.h"
36 
37 static struct pollfd fds[1];
38 static mode_t mode = 0777;
39 static char extregex[80];
40 static struct stat statbuff;
41 static const char *auclass = "fa";
42 static const char *path = "fileforaudit";
43 static const char *errpath = "dirdoesnotexist/fileforaudit";
44 static const char *successreg = "fileforaudit.*return,success";
45 static const char *failurereg = "fileforaudit.*return,failure";
46 
47 
48 ATF_TC_WITH_CLEANUP(stat_success);
49 ATF_TC_HEAD(stat_success, tc)
50 {
51 	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
52 					"stat(2) call");
53 }
54 
55 ATF_TC_BODY(stat_success, tc)
56 {
57 	/* File needs to exist to call stat(2) */
58 	ATF_REQUIRE(open(path, O_CREAT, mode) != -1);
59 	FILE *pipefd = setup(fds, auclass);
60 	ATF_REQUIRE_EQ(0, stat(path, &statbuff));
61 	check_audit(fds, successreg, pipefd);
62 }
63 
64 ATF_TC_CLEANUP(stat_success, tc)
65 {
66 	cleanup();
67 }
68 
69 
70 ATF_TC_WITH_CLEANUP(stat_failure);
71 ATF_TC_HEAD(stat_failure, tc)
72 {
73 	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
74 					"stat(2) call");
75 }
76 
77 ATF_TC_BODY(stat_failure, tc)
78 {
79 	FILE *pipefd = setup(fds, auclass);
80 	/* Failure reason: file does not exist */
81 	ATF_REQUIRE_EQ(-1, stat(errpath, &statbuff));
82 	check_audit(fds, failurereg, pipefd);
83 }
84 
85 ATF_TC_CLEANUP(stat_failure, tc)
86 {
87 	cleanup();
88 }
89 
90 
91 ATF_TC_WITH_CLEANUP(lstat_success);
92 ATF_TC_HEAD(lstat_success, tc)
93 {
94 	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
95 					"lstat(2) call");
96 }
97 
98 ATF_TC_BODY(lstat_success, tc)
99 {
100 	/* Symbolic link needs to exist to call lstat(2) */
101 	ATF_REQUIRE_EQ(0, symlink("symlink", path));
102 	FILE *pipefd = setup(fds, auclass);
103 	ATF_REQUIRE_EQ(0, lstat(path, &statbuff));
104 	check_audit(fds, successreg, pipefd);
105 }
106 
107 ATF_TC_CLEANUP(lstat_success, tc)
108 {
109 	cleanup();
110 }
111 
112 
113 ATF_TC_WITH_CLEANUP(lstat_failure);
114 ATF_TC_HEAD(lstat_failure, tc)
115 {
116 	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
117 					"lstat(2) call");
118 }
119 
120 ATF_TC_BODY(lstat_failure, tc)
121 {
122 	FILE *pipefd = setup(fds, auclass);
123 	/* Failure reason: symbolic link does not exist */
124 	ATF_REQUIRE_EQ(-1, lstat(errpath, &statbuff));
125 	check_audit(fds, failurereg, pipefd);
126 }
127 
128 ATF_TC_CLEANUP(lstat_failure, tc)
129 {
130 	cleanup();
131 }
132 
133 
134 ATF_TC_WITH_CLEANUP(fstat_success);
135 ATF_TC_HEAD(fstat_success, tc)
136 {
137 	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
138 					"fstat(2) call");
139 }
140 
141 ATF_TC_BODY(fstat_success, tc)
142 {
143 	int filedesc;
144 	/* File needs to exist to call fstat(2) */
145 	ATF_REQUIRE((filedesc = open(path, O_CREAT | O_RDWR, mode)) != -1);
146 	FILE *pipefd = setup(fds, auclass);
147 	ATF_REQUIRE_EQ(0, fstat(filedesc, &statbuff));
148 
149 	snprintf(extregex, sizeof(extregex),
150 		"fstat.*%jd.*return,success", (intmax_t)statbuff.st_ino);
151 	check_audit(fds, extregex, pipefd);
152 }
153 
154 ATF_TC_CLEANUP(fstat_success, tc)
155 {
156 	cleanup();
157 }
158 
159 
160 ATF_TC_WITH_CLEANUP(fstat_failure);
161 ATF_TC_HEAD(fstat_failure, tc)
162 {
163 	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
164 					"fstat(2) call");
165 }
166 
167 ATF_TC_BODY(fstat_failure, tc)
168 {
169 	FILE *pipefd = setup(fds, auclass);
170 	const char *regex = "fstat.*return,failure : Bad file descriptor";
171 	/* Failure reason: bad file descriptor */
172 	ATF_REQUIRE_EQ(-1, fstat(-1, &statbuff));
173 	check_audit(fds, regex, pipefd);
174 }
175 
176 ATF_TC_CLEANUP(fstat_failure, tc)
177 {
178 	cleanup();
179 }
180 
181 
182 ATF_TC_WITH_CLEANUP(fstatat_success);
183 ATF_TC_HEAD(fstatat_success, tc)
184 {
185 	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
186 					"fstatat(2) call");
187 }
188 
189 ATF_TC_BODY(fstatat_success, tc)
190 {
191 	/* File or Symbolic link needs to exist to call lstat(2) */
192 	ATF_REQUIRE_EQ(0, symlink("symlink", path));
193 	FILE *pipefd = setup(fds, auclass);
194 	ATF_REQUIRE_EQ(0, fstatat(AT_FDCWD, path, &statbuff,
195 		AT_SYMLINK_NOFOLLOW));
196 	check_audit(fds, successreg, pipefd);
197 }
198 
199 ATF_TC_CLEANUP(fstatat_success, tc)
200 {
201 	cleanup();
202 }
203 
204 
205 ATF_TC_WITH_CLEANUP(fstatat_failure);
206 ATF_TC_HEAD(fstatat_failure, tc)
207 {
208 	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
209 					"fstatat(2) call");
210 }
211 
212 ATF_TC_BODY(fstatat_failure, tc)
213 {
214 	FILE *pipefd = setup(fds, auclass);
215 	/* Failure reason: symbolic link does not exist */
216 	ATF_REQUIRE_EQ(-1, fstatat(AT_FDCWD, path, &statbuff,
217 		AT_SYMLINK_NOFOLLOW));
218 	check_audit(fds, failurereg, pipefd);
219 }
220 
221 ATF_TC_CLEANUP(fstatat_failure, tc)
222 {
223 	cleanup();
224 }
225 
226 
227 ATF_TP_ADD_TCS(tp)
228 {
229 	ATF_TP_ADD_TC(tp, stat_success);
230 	ATF_TP_ADD_TC(tp, stat_failure);
231 	ATF_TP_ADD_TC(tp, lstat_success);
232 	ATF_TP_ADD_TC(tp, lstat_failure);
233 	ATF_TP_ADD_TC(tp, fstat_success);
234 	ATF_TP_ADD_TC(tp, fstat_failure);
235 	ATF_TP_ADD_TC(tp, fstatat_success);
236 	ATF_TP_ADD_TC(tp, fstatat_failure);
237 
238 	return (atf_no_error());
239 }
240