priv_vfs_read_write.c revision 162271
1/*-
2 * Copyright (c) 2006 nCircle Network Security, Inc.
3 * All rights reserved.
4 *
5 * This software was developed by Robert N. M. Watson for the TrustedBSD
6 * Project under contract to nCircle Network Security, Inc.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR, NCIRCLE NETWORK SECURITY,
21 * INC., OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
23 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * $FreeBSD: head/tools/regression/priv/priv_vfs_read_write.c 162271 2006-09-13 09:05:39Z rwatson $
30 */
31
32/*
33 * This is a joint test of both the read and write privileges with respect to
34 * discretionary file system access control (permissions).  Only permissions,
35 * not ACL semantics, and only privilege-related checks are performed.
36 */
37
38#include <sys/types.h>
39#include <sys/stat.h>
40
41#include <err.h>
42#include <errno.h>
43#include <fcntl.h>
44#include <stdlib.h>
45#include <string.h>
46#include <unistd.h>
47
48#include "main.h"
49
50struct test_arguments {
51	int	open_flags;
52	uid_t	proc_uid;
53	gid_t	proc_gid;
54	uid_t	file_uid;
55	gid_t	file_gid;
56};
57
58/*
59 * Rather special-purpose, don't reuse.  Will need updating if anything other
60 * than O_RDONLY and O_WRONLY are to be used in tests.
61 */
62static const char *
63flags_to_string(int flags)
64{
65
66	switch (flags) {
67	case O_RDONLY:
68		return ("O_RDONLY");
69
70	case O_WRONLY:
71		return ("O_WRONLY");
72
73	default:
74		return ("unknown");
75	}
76}
77
78static void
79test_perm(struct test_arguments ta, mode_t file_mode, int expected)
80{
81	uid_t proc_uid, file_uid;
82	gid_t proc_gid, file_gid;
83	int fd, open_flags;
84	char fpath[1024];
85
86	proc_uid = ta.proc_uid;
87	proc_gid = ta.proc_gid;
88	file_uid = ta.file_uid;
89	file_gid = ta.file_gid;
90	open_flags = ta.open_flags;
91
92	setup_file(fpath, file_uid, file_gid, file_mode);
93	set_creds(proc_uid, proc_gid);
94
95	fd = open(fpath, open_flags);
96
97	if (expected == 0) {
98		if (fd <= 0) {
99			warn("test_perm(%s, %d, %d, %d, %d, %04o, %d) "
100			    "returned %d instead of %d",
101			    flags_to_string(open_flags), proc_uid, proc_gid,
102			    file_uid, file_gid, file_mode, expected,
103			    errno, expected);
104			restore_creds();
105			(void)unlink(fpath);
106			exit(-1);
107		}
108		close(fd);
109	} else {
110		if (fd >= 0) {
111			warnx("test_perm(%s, %d, %d, %d, %d, %04o, %d)"
112			    " returned 0 instead of %d",
113			    flags_to_string(open_flags), proc_uid, proc_gid,
114			    file_uid, file_gid, file_mode, expected,
115			    expected);
116			close(fd);
117			restore_creds();
118			(void)unlink(fpath);
119			exit(-1);
120		} else if (errno != expected) {
121			warn("test_perm(%s, %d, %d, %d, %d, %04o, %d)"
122			    " returned %d instead of %d",
123			    flags_to_string(open_flags), proc_uid, proc_gid,
124			    file_uid, file_gid, file_mode, expected,
125			    errno, expected);
126			restore_creds();
127			(void)unlink(fpath);
128			exit(-1);
129		}
130	}
131
132	restore_creds();
133	(void)unlink(fpath);
134}
135
136static const gid_t gidset[] = { GID_WHEEL };
137
138static void
139preamble(void)
140{
141
142	if (getuid() != UID_ROOT)
143		errx(-1, "must be run as root");
144	if (setgroups(1, gidset) < 0)
145		err(-1, "setgroups(1, {%d})", GID_WHEEL);
146}
147
148void
149priv_vfs_read(void)
150{
151	struct test_arguments ta;
152
153	preamble();
154
155	ta.open_flags = O_RDONLY;
156
157	/*
158	 * Privileged user and file owner.  All tests should pass.
159	 */
160	ta.proc_uid = UID_ROOT;
161	ta.proc_gid = GID_WHEEL;
162	ta.file_uid = UID_ROOT;
163	ta.file_gid = GID_WHEEL;
164
165	test_perm(ta, 0000, 0);
166	test_perm(ta, 0100, 0);
167	test_perm(ta, 0200, 0);
168	test_perm(ta, 0300, 0);
169	test_perm(ta, 0400, 0);
170	test_perm(ta, 0500, 0);
171	test_perm(ta, 0600, 0);
172	test_perm(ta, 0700, 0);
173
174	/*
175	 * Privileged user and file group.  All tests should pass.
176	 */
177	ta.proc_uid = UID_ROOT;
178	ta.proc_gid = GID_WHEEL;
179	ta.file_uid = UID_OWNER;
180	ta.file_gid = GID_WHEEL;
181
182	test_perm(ta, 0000, 0);
183	test_perm(ta, 0010, 0);
184	test_perm(ta, 0020, 0);
185	test_perm(ta, 0030, 0);
186	test_perm(ta, 0040, 0);
187	test_perm(ta, 0050, 0);
188	test_perm(ta, 0060, 0);
189	test_perm(ta, 0070, 0);
190
191	/*
192	 * Privileged user and file other.  All tests should pass.
193	 */
194	ta.proc_uid = UID_ROOT;
195	ta.proc_gid = GID_WHEEL;
196	ta.file_uid = UID_OWNER;
197	ta.file_gid = GID_OWNER;
198
199	test_perm(ta, 0000, 0);
200	test_perm(ta, 0001, 0);
201	test_perm(ta, 0002, 0);
202	test_perm(ta, 0003, 0);
203	test_perm(ta, 0004, 0);
204	test_perm(ta, 0005, 0);
205	test_perm(ta, 0006, 0);
206	test_perm(ta, 0007, 0);
207
208	/*
209	 * Unprivileged user and file owner.  Various DAC failures.
210	 */
211	ta.proc_uid = UID_OWNER;
212	ta.proc_gid = GID_OWNER;
213	ta.file_uid = UID_OWNER;
214	ta.file_gid = GID_OWNER;
215
216	test_perm(ta, 0000, EACCES);
217	test_perm(ta, 0100, EACCES);
218	test_perm(ta, 0200, EACCES);
219	test_perm(ta, 0300, EACCES);
220	test_perm(ta, 0400, 0);
221	test_perm(ta, 0500, 0);
222	test_perm(ta, 0600, 0);
223	test_perm(ta, 0700, 0);
224
225	/*
226	 * Unprivileged user and file group.  Various DAC failures.
227	 */
228	ta.proc_uid = UID_OTHER;
229	ta.proc_gid = GID_OWNER;
230	ta.file_uid = UID_OWNER;
231	ta.file_gid = GID_OWNER;
232
233	test_perm(ta, 0000, EACCES);
234	test_perm(ta, 0010, EACCES);
235	test_perm(ta, 0020, EACCES);
236	test_perm(ta, 0030, EACCES);
237	test_perm(ta, 0040, 0);
238	test_perm(ta, 0050, 0);
239	test_perm(ta, 0060, 0);
240	test_perm(ta, 0070, 0);
241
242	/*
243	 * Unprivileged user and file other.  Various DAC failures.
244	 */
245	ta.proc_uid = UID_OTHER;
246	ta.proc_gid = GID_OTHER;
247	ta.file_uid = UID_OWNER;
248	ta.file_gid = GID_OWNER;
249
250	test_perm(ta, 0000, EACCES);
251	test_perm(ta, 0001, EACCES);
252	test_perm(ta, 0002, EACCES);
253	test_perm(ta, 0003, EACCES);
254	test_perm(ta, 0004, 0);
255	test_perm(ta, 0005, 0);
256	test_perm(ta, 0006, 0);
257	test_perm(ta, 0007, 0);
258}
259
260void
261priv_vfs_write(void)
262{
263	struct test_arguments ta;
264
265	preamble();
266
267	ta.open_flags = O_WRONLY;
268
269	/*
270	 * Privileged user and file owner.  All tests should pass.
271	 */
272	ta.proc_uid = UID_ROOT;
273	ta.proc_gid = GID_WHEEL;
274	ta.file_uid = UID_ROOT;
275	ta.file_gid = GID_WHEEL;
276
277	test_perm(ta, 0000, 0);
278	test_perm(ta, 0100, 0);
279	test_perm(ta, 0200, 0);
280	test_perm(ta, 0300, 0);
281	test_perm(ta, 0400, 0);
282	test_perm(ta, 0500, 0);
283	test_perm(ta, 0600, 0);
284	test_perm(ta, 0700, 0);
285
286	/*
287	 * Privileged user and file group.  All tests should pass.
288	 */
289	ta.proc_uid = UID_ROOT;
290	ta.proc_gid = GID_WHEEL;
291	ta.file_uid = UID_OWNER;
292	ta.file_gid = GID_WHEEL;
293
294	test_perm(ta, 0000, 0);
295	test_perm(ta, 0010, 0);
296	test_perm(ta, 0020, 0);
297	test_perm(ta, 0030, 0);
298	test_perm(ta, 0040, 0);
299	test_perm(ta, 0050, 0);
300	test_perm(ta, 0060, 0);
301	test_perm(ta, 0070, 0);
302
303	/*
304	 * Privileged user and file other.  All tests should pass.
305	 */
306	ta.proc_uid = UID_ROOT;
307	ta.proc_gid = GID_WHEEL;
308	ta.file_uid = UID_OWNER;
309	ta.file_gid = GID_OWNER;
310
311	test_perm(ta, 0000, 0);
312	test_perm(ta, 0001, 0);
313	test_perm(ta, 0002, 0);
314	test_perm(ta, 0003, 0);
315	test_perm(ta, 0004, 0);
316	test_perm(ta, 0005, 0);
317	test_perm(ta, 0006, 0);
318	test_perm(ta, 0007, 0);
319
320	/*
321	 * Unprivileged user and file owner.  Various DAC failures.
322	 */
323	ta.proc_uid = UID_OWNER;
324	ta.proc_gid = GID_OWNER;
325	ta.file_uid = UID_OWNER;
326	ta.file_gid = GID_OWNER;
327
328	test_perm(ta, 0000, EACCES);
329	test_perm(ta, 0100, EACCES);
330	test_perm(ta, 0200, 0);
331	test_perm(ta, 0300, 0);
332	test_perm(ta, 0400, EACCES);
333	test_perm(ta, 0500, EACCES);
334	test_perm(ta, 0600, 0);
335	test_perm(ta, 0700, 0);
336
337	/*
338	 * Unprivileged user and file group.  Various DAC failures.
339	 */
340	ta.proc_uid = UID_OTHER;
341	ta.proc_gid = GID_OWNER;
342	ta.file_uid = UID_OWNER;
343	ta.file_gid = GID_OWNER;
344
345	test_perm(ta, 0000, EACCES);
346	test_perm(ta, 0010, EACCES);
347	test_perm(ta, 0020, 0);
348	test_perm(ta, 0030, 0);
349	test_perm(ta, 0040, EACCES);
350	test_perm(ta, 0050, EACCES);
351	test_perm(ta, 0060, 0);
352	test_perm(ta, 0070, 0);
353
354	/*
355	 * Unprivileged user and file other.  Various DAC failures.
356	 */
357	ta.proc_uid = UID_OTHER;
358	ta.proc_gid = GID_OTHER;
359	ta.file_uid = UID_OWNER;
360	ta.file_gid = GID_OWNER;
361
362	test_perm(ta, 0000, EACCES);
363	test_perm(ta, 0001, EACCES);
364	test_perm(ta, 0002, 0);
365	test_perm(ta, 0003, 0);
366	test_perm(ta, 0004, EACCES);
367	test_perm(ta, 0005, EACCES);
368	test_perm(ta, 0006, 0);
369	test_perm(ta, 0007, 0);
370}
371