xref: /freebsd/tests/sys/audit/open.c (revision b13a70d5a4979997a0dbc0795d27bb7e22ec794b)
1c41bbc0aSAlan Somers /*-
2c41bbc0aSAlan Somers  * Copyright (c) 2018 Aniket Pandey
3c41bbc0aSAlan Somers  *
4c41bbc0aSAlan Somers  * Redistribution and use in source and binary forms, with or without
5c41bbc0aSAlan Somers  * modification, are permitted provided that the following conditions
6c41bbc0aSAlan Somers  * are met:
7c41bbc0aSAlan Somers  * 1. Redistributions of source code must retain the above copyright
8c41bbc0aSAlan Somers  *    notice, this list of conditions and the following disclaimer.
9c41bbc0aSAlan Somers  * 2. Redistributions in binary form must reproduce the above copyright
10c41bbc0aSAlan Somers  *    notice, this list of conditions and the following disclaimer in the
11c41bbc0aSAlan Somers  *    documentation and/or other materials provided with the distribution.
12c41bbc0aSAlan Somers  *
13c41bbc0aSAlan Somers  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14c41bbc0aSAlan Somers  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15c41bbc0aSAlan Somers  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16c41bbc0aSAlan Somers  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17c41bbc0aSAlan Somers  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18c41bbc0aSAlan Somers  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19c41bbc0aSAlan Somers  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
20c41bbc0aSAlan Somers  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21c41bbc0aSAlan Somers  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22c41bbc0aSAlan Somers  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23c41bbc0aSAlan Somers  * SUCH DAMAGE.
24c41bbc0aSAlan Somers  *
25c41bbc0aSAlan Somers  * $FreeBSD$
26c41bbc0aSAlan Somers  */
27c41bbc0aSAlan Somers 
28c41bbc0aSAlan Somers /*
29c41bbc0aSAlan Somers  * Note: open(2) and openat(2) have 12 events each for various values of 'flag'
30c41bbc0aSAlan Somers  * Please see: contrib/openbsm/etc/audit_event#L261
31c41bbc0aSAlan Somers  *
32c41bbc0aSAlan Somers  * 270:AUE_OPENAT_R:openat(2) - read:fr
33c41bbc0aSAlan Somers  * 271:AUE_OPENAT_RC:openat(2) - read,creat:fc,fr,fa,fm
34c41bbc0aSAlan Somers  * 272:AUE_OPENAT_RT:openat(2) - read,trunc:fd,fr,fa,fm
35c41bbc0aSAlan Somers  * 273:AUE_OPENAT_RTC:openat(2) - read,creat,trunc:fc,fd,fr,fa,fm
36c41bbc0aSAlan Somers  * 274:AUE_OPENAT_W:openat(2) - write:fw
37c41bbc0aSAlan Somers  * 275:AUE_OPENAT_WC:openat(2) - write,creat:fc,fw,fa,fm
38c41bbc0aSAlan Somers  * 276:AUE_OPENAT_WT:openat(2) - write,trunc:fd,fw,fa,fm
39c41bbc0aSAlan Somers  * 277:AUE_OPENAT_WTC:openat(2) - write,creat,trunc:fc,fd,fw,fa,fm
40c41bbc0aSAlan Somers  * 278:AUE_OPENAT_RW:openat(2) - read,write:fr,fw
41c41bbc0aSAlan Somers  * 279:AUE_OPENAT_RWC:openat(2) - read,write,create:fc,fw,fr,fa,fm
42c41bbc0aSAlan Somers  * 280:AUE_OPENAT_RWT:openat(2) - read,write,trunc:fd,fw,fr,fa,fm
43c41bbc0aSAlan Somers  * 281:AUE_OPENAT_RWTC:openat(2) - read,write,creat,trunc:fc,fd,fw,fr,fa,fm
44c41bbc0aSAlan Somers  */
45c41bbc0aSAlan Somers 
46c41bbc0aSAlan Somers #include <sys/syscall.h>
47c41bbc0aSAlan Somers 
48c41bbc0aSAlan Somers #include <atf-c.h>
49c41bbc0aSAlan Somers #include <fcntl.h>
50c41bbc0aSAlan Somers 
51c41bbc0aSAlan Somers #include "utils.h"
52c41bbc0aSAlan Somers 
53c41bbc0aSAlan Somers static struct pollfd fds[1];
54c41bbc0aSAlan Somers static mode_t o_mode = 0777;
55*b13a70d5SAlan Somers static int filedesc;
56c41bbc0aSAlan Somers static char extregex[80];
57c41bbc0aSAlan Somers static const char *path = "fileforaudit";
58c41bbc0aSAlan Somers static const char *errpath = "adirhasnoname/fileforaudit";
59c41bbc0aSAlan Somers 
60c41bbc0aSAlan Somers /*
61c41bbc0aSAlan Somers  * Define test-cases for success and failure modes of both open(2) and openat(2)
62c41bbc0aSAlan Somers  */
63c41bbc0aSAlan Somers #define OPEN_AT_TC_DEFINE(mode, regex, flag, class) \
64c41bbc0aSAlan Somers ATF_TC_WITH_CLEANUP(open_ ## mode ## _success); \
65c41bbc0aSAlan Somers ATF_TC_HEAD(open_ ## mode ## _success, tc) \
66c41bbc0aSAlan Somers { \
67c41bbc0aSAlan Somers 	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful " \
68c41bbc0aSAlan Somers 				"open(2) call with flags = %s", #flag); \
69c41bbc0aSAlan Somers } \
70c41bbc0aSAlan Somers ATF_TC_BODY(open_ ## mode ## _success, tc) \
71c41bbc0aSAlan Somers { \
72c41bbc0aSAlan Somers 	snprintf(extregex, sizeof(extregex), \
73c41bbc0aSAlan Somers 		"open.*%s.*fileforaudit.*return,success", regex); \
74c41bbc0aSAlan Somers 	/* File needs to exist for successful open(2) invocation */ \
75*b13a70d5SAlan Somers 	ATF_REQUIRE((filedesc = open(path, O_CREAT, o_mode)) != -1); \
76c41bbc0aSAlan Somers 	FILE *pipefd = setup(fds, class); \
77c41bbc0aSAlan Somers 	ATF_REQUIRE(syscall(SYS_open, path, flag) != -1); \
78c41bbc0aSAlan Somers 	check_audit(fds, extregex, pipefd); \
79*b13a70d5SAlan Somers 	close(filedesc); \
80c41bbc0aSAlan Somers } \
81c41bbc0aSAlan Somers ATF_TC_CLEANUP(open_ ## mode ## _success, tc) \
82c41bbc0aSAlan Somers { \
83c41bbc0aSAlan Somers 	cleanup(); \
84c41bbc0aSAlan Somers } \
85c41bbc0aSAlan Somers ATF_TC_WITH_CLEANUP(open_ ## mode ## _failure); \
86c41bbc0aSAlan Somers ATF_TC_HEAD(open_ ## mode ## _failure, tc) \
87c41bbc0aSAlan Somers { \
88c41bbc0aSAlan Somers 	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful " \
89c41bbc0aSAlan Somers 				"open(2) call with flags = %s", #flag); \
90c41bbc0aSAlan Somers } \
91c41bbc0aSAlan Somers ATF_TC_BODY(open_ ## mode ## _failure, tc) \
92c41bbc0aSAlan Somers { \
93c41bbc0aSAlan Somers 	snprintf(extregex, sizeof(extregex), \
94c41bbc0aSAlan Somers 		"open.*%s.*fileforaudit.*return,failure", regex); \
95c41bbc0aSAlan Somers 	FILE *pipefd = setup(fds, class); \
96c41bbc0aSAlan Somers 	ATF_REQUIRE_EQ(-1, syscall(SYS_open, errpath, flag)); \
97c41bbc0aSAlan Somers 	check_audit(fds, extregex, pipefd); \
98c41bbc0aSAlan Somers } \
99c41bbc0aSAlan Somers ATF_TC_CLEANUP(open_ ## mode ## _failure, tc) \
100c41bbc0aSAlan Somers { \
101c41bbc0aSAlan Somers 	cleanup(); \
102c41bbc0aSAlan Somers } \
103c41bbc0aSAlan Somers ATF_TC_WITH_CLEANUP(openat_ ## mode ## _success); \
104c41bbc0aSAlan Somers ATF_TC_HEAD(openat_ ## mode ## _success, tc) \
105c41bbc0aSAlan Somers { \
106c41bbc0aSAlan Somers 	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful " \
107c41bbc0aSAlan Somers 				"openat(2) call with flags = %s", #flag); \
108c41bbc0aSAlan Somers } \
109c41bbc0aSAlan Somers ATF_TC_BODY(openat_ ## mode ## _success, tc) \
110c41bbc0aSAlan Somers { \
111*b13a70d5SAlan Somers 	int filedesc2; \
112c41bbc0aSAlan Somers 	snprintf(extregex, sizeof(extregex), \
113c41bbc0aSAlan Somers 		"openat.*%s.*fileforaudit.*return,success", regex); \
114c41bbc0aSAlan Somers 	/* File needs to exist for successful openat(2) invocation */ \
115*b13a70d5SAlan Somers 	ATF_REQUIRE((filedesc = open(path, O_CREAT, o_mode)) != -1); \
116c41bbc0aSAlan Somers 	FILE *pipefd = setup(fds, class); \
117*b13a70d5SAlan Somers 	ATF_REQUIRE((filedesc2 = openat(AT_FDCWD, path, flag)) != -1); \
118c41bbc0aSAlan Somers 	check_audit(fds, extregex, pipefd); \
119*b13a70d5SAlan Somers 	close(filedesc2); \
120*b13a70d5SAlan Somers 	close(filedesc); \
121c41bbc0aSAlan Somers } \
122c41bbc0aSAlan Somers ATF_TC_CLEANUP(openat_ ## mode ## _success, tc) \
123c41bbc0aSAlan Somers { \
124c41bbc0aSAlan Somers 	cleanup(); \
125c41bbc0aSAlan Somers } \
126c41bbc0aSAlan Somers ATF_TC_WITH_CLEANUP(openat_ ## mode ## _failure); \
127c41bbc0aSAlan Somers ATF_TC_HEAD(openat_ ## mode ## _failure, tc) \
128c41bbc0aSAlan Somers { \
129c41bbc0aSAlan Somers 	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful " \
130c41bbc0aSAlan Somers 				"openat(2) call with flags = %s", #flag); \
131c41bbc0aSAlan Somers } \
132c41bbc0aSAlan Somers ATF_TC_BODY(openat_ ## mode ## _failure, tc) \
133c41bbc0aSAlan Somers { \
134c41bbc0aSAlan Somers 	snprintf(extregex, sizeof(extregex), \
135c41bbc0aSAlan Somers 		"openat.*%s.*fileforaudit.*return,failure", regex); \
136c41bbc0aSAlan Somers 	FILE *pipefd = setup(fds, class); \
137c41bbc0aSAlan Somers 	ATF_REQUIRE_EQ(-1, openat(AT_FDCWD, errpath, flag)); \
138c41bbc0aSAlan Somers 	check_audit(fds, extregex, pipefd); \
139c41bbc0aSAlan Somers } \
140c41bbc0aSAlan Somers ATF_TC_CLEANUP(openat_ ## mode ## _failure, tc) \
141c41bbc0aSAlan Somers { \
142c41bbc0aSAlan Somers 	cleanup(); \
143c41bbc0aSAlan Somers }
144c41bbc0aSAlan Somers 
145c41bbc0aSAlan Somers /*
146c41bbc0aSAlan Somers  * Add both success and failure modes of open(2) and openat(2)
147c41bbc0aSAlan Somers  */
148c41bbc0aSAlan Somers #define OPEN_AT_TC_ADD(tp, mode) \
149c41bbc0aSAlan Somers do { \
150c41bbc0aSAlan Somers 	ATF_TP_ADD_TC(tp, open_ ## mode ## _success); \
151c41bbc0aSAlan Somers 	ATF_TP_ADD_TC(tp, open_ ## mode ## _failure); \
152c41bbc0aSAlan Somers 	ATF_TP_ADD_TC(tp, openat_ ## mode ## _success); \
153c41bbc0aSAlan Somers 	ATF_TP_ADD_TC(tp, openat_ ## mode ## _failure); \
154c41bbc0aSAlan Somers } while (0)
155c41bbc0aSAlan Somers 
156c41bbc0aSAlan Somers 
157c41bbc0aSAlan Somers /*
158c41bbc0aSAlan Somers  * Each of the 12 OPEN_AT_TC_DEFINE statement is a group of 4 test-cases
159c41bbc0aSAlan Somers  * corresponding to separate audit events for open(2) and openat(2)
160c41bbc0aSAlan Somers  */
161c41bbc0aSAlan Somers OPEN_AT_TC_DEFINE(read, "read", O_RDONLY, "fr")
162c41bbc0aSAlan Somers OPEN_AT_TC_DEFINE(read_creat, "read,creat", O_RDONLY | O_CREAT, "fr")
163c41bbc0aSAlan Somers OPEN_AT_TC_DEFINE(read_trunc, "read,trunc", O_RDONLY | O_TRUNC, "fr")
164c41bbc0aSAlan Somers OPEN_AT_TC_DEFINE(read_creat_trunc, "read,creat,trunc", O_RDONLY | O_CREAT
165c41bbc0aSAlan Somers 	| O_TRUNC, "fr")
166c41bbc0aSAlan Somers OPEN_AT_TC_DEFINE(write, "write", O_WRONLY, "fw")
167c41bbc0aSAlan Somers OPEN_AT_TC_DEFINE(write_creat, "write,creat", O_WRONLY | O_CREAT, "fw")
168c41bbc0aSAlan Somers OPEN_AT_TC_DEFINE(write_trunc, "write,trunc", O_WRONLY | O_TRUNC, "fw")
169c41bbc0aSAlan Somers OPEN_AT_TC_DEFINE(write_creat_trunc, "write,creat,trunc", O_WRONLY | O_CREAT
170c41bbc0aSAlan Somers 	| O_TRUNC, "fw")
171c41bbc0aSAlan Somers OPEN_AT_TC_DEFINE(read_write, "read,write", O_RDWR, "fr")
172c41bbc0aSAlan Somers OPEN_AT_TC_DEFINE(read_write_creat, "read,write,creat", O_RDWR | O_CREAT, "fw")
173c41bbc0aSAlan Somers OPEN_AT_TC_DEFINE(read_write_trunc, "read,write,trunc", O_RDWR | O_TRUNC, "fr")
174c41bbc0aSAlan Somers OPEN_AT_TC_DEFINE(read_write_creat_trunc, "read,write,creat,trunc", O_RDWR |
175c41bbc0aSAlan Somers 	O_CREAT | O_TRUNC, "fw")
176c41bbc0aSAlan Somers 
177c41bbc0aSAlan Somers 
178c41bbc0aSAlan Somers ATF_TP_ADD_TCS(tp)
179c41bbc0aSAlan Somers {
180c41bbc0aSAlan Somers 	OPEN_AT_TC_ADD(tp, read);
181c41bbc0aSAlan Somers 	OPEN_AT_TC_ADD(tp, read_creat);
182c41bbc0aSAlan Somers 	OPEN_AT_TC_ADD(tp, read_trunc);
183c41bbc0aSAlan Somers 	OPEN_AT_TC_ADD(tp, read_creat_trunc);
184c41bbc0aSAlan Somers 
185c41bbc0aSAlan Somers 	OPEN_AT_TC_ADD(tp, write);
186c41bbc0aSAlan Somers 	OPEN_AT_TC_ADD(tp, write_creat);
187c41bbc0aSAlan Somers 	OPEN_AT_TC_ADD(tp, write_trunc);
188c41bbc0aSAlan Somers 	OPEN_AT_TC_ADD(tp, write_creat_trunc);
189c41bbc0aSAlan Somers 
190c41bbc0aSAlan Somers 	OPEN_AT_TC_ADD(tp, read_write);
191c41bbc0aSAlan Somers 	OPEN_AT_TC_ADD(tp, read_write_creat);
192c41bbc0aSAlan Somers 	OPEN_AT_TC_ADD(tp, read_write_trunc);
193c41bbc0aSAlan Somers 	OPEN_AT_TC_ADD(tp, read_write_creat_trunc);
194c41bbc0aSAlan Somers 
195c41bbc0aSAlan Somers 	return (atf_no_error());
196c41bbc0aSAlan Somers }
197