xref: /xnu-12377.41.6/tests/vfs/sandbox_fstat.c (revision bbb1b6f9e71b8cdde6e5cd6f4841f207dee3d828)
1 /*
2  * Copyright (c) 2024 Apple Computer, Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 
29 /* compile: xcrun -sdk macosx.internal clang -ldarwintest -lsandbox -o sandbox_fstat sandbox_fstat.c -g -Weverything */
30 
31 #include <sys/paths.h>
32 #include <sys/xattr.h>
33 #include <sandbox/libsandbox.h>
34 #include <TargetConditionals.h>
35 
36 #include <darwintest.h>
37 #include <darwintest/utils.h>
38 
39 #define RUN_TEST     TARGET_OS_OSX
40 
41 static char template[MAXPATHLEN];
42 static char *testdir = NULL;
43 static char file[PATH_MAX], file_rsrcfork[PATH_MAX];
44 static sandbox_params_t params = NULL;
45 static sandbox_profile_t profile = NULL;
46 
47 T_GLOBAL_META(
48 	T_META_NAMESPACE("xnu.vfs"),
49 	T_META_RADAR_COMPONENT_NAME("xnu"),
50 	T_META_RADAR_COMPONENT_VERSION("vfs"),
51 	T_META_ASROOT(false),
52 	T_META_ENABLED(RUN_TEST),
53 	T_META_CHECK_LEAKS(false));
54 
55 static void
cleanup(void)56 cleanup(void)
57 {
58 	if (profile) {
59 		sandbox_free_profile(profile);
60 	}
61 	if (params) {
62 		sandbox_free_params(params);
63 	}
64 	if (file[0] != '\0') {
65 		unlink(file);
66 	}
67 	if (testdir) {
68 		rmdir(testdir);
69 	}
70 }
71 
72 static void
create_profile_string(char * buff,size_t size)73 create_profile_string(char *buff, size_t size)
74 {
75 	snprintf(buff, size, "(version 1) \n\
76                           (allow default) \n\
77                           (import \"system.sb\") \n\
78                           (deny file-read-metadata (path \"%s\")) \n",
79 	    file);
80 }
81 static void
do_test(int expected_error)82 do_test(int expected_error)
83 {
84 	int fd;
85 	struct stat sb;
86 
87 	/* Test stat() */
88 	if (expected_error) {
89 		T_EXPECT_POSIX_FAILURE(stat(file, &sb), expected_error, "Calling stat() should FAIL with '%s'", strerror(expected_error));
90 	} else {
91 		T_EXPECT_POSIX_SUCCESS(stat(file, &sb), "Calling stat() for the file should PASS");
92 	}
93 
94 	/* Test fstat() while the file is open with the O_CREAT | O_WRONLY flags  */
95 	T_EXPECT_POSIX_SUCCESS(fd = open(file, O_CREAT | O_WRONLY, 0666), "Opening with the O_CREAT | O_WRONLY flags");
96 	if (fd != -1) {
97 		if (expected_error) {
98 			T_EXPECT_POSIX_FAILURE(fstat(fd, &sb), expected_error, "Calling fstat() should FAIL with '%s'", strerror(expected_error));
99 		} else {
100 			T_EXPECT_POSIX_SUCCESS(fstat(fd, &sb), "Calling fstat() for the test file should PASS");
101 		}
102 		close(fd);
103 	}
104 
105 	T_EXPECT_POSIX_SUCCESS(fd = open(file_rsrcfork, O_CREAT | O_WRONLY, 0666), "Opening rsrcfork with the O_CREAT | O_WRONLY flags");
106 	if (fd != -1) {
107 		T_EXPECT_POSIX_SUCCESS(fstat(fd, &sb), "Calling fstat() for the rsrcfork should PASS");
108 		close(fd);
109 	}
110 }
111 
112 T_DECL(sandbox_fstat,
113     "Prevent the information disclosure on files opened with O_WRONLY while sandbox profile denies 'file-read-metadata'")
114 {
115 #if (!RUN_TEST)
116 	T_SKIP("Not macOS");
117 #endif
118 
119 	int fd;
120 	char *sberror = NULL;
121 	char profile_string[1000];
122 	char testdir_path[MAXPATHLEN];
123 
124 	file[0] = '\0';
125 
126 	T_ATEND(cleanup);
127 	T_SETUPBEGIN;
128 
129 	/* Create test root dir */
130 	snprintf(template, sizeof(template), "%s/sandbox_fstat-XXXXXX", dt_tmpdir());
131 	T_ASSERT_POSIX_NOTNULL((testdir = mkdtemp(template)), "Creating test root dir");
132 	T_ASSERT_POSIX_SUCCESS((fd = open(testdir, O_SEARCH, 0777)), "Opening test root directory '%s'", testdir);
133 	T_ASSERT_POSIX_SUCCESS(fcntl(fd, F_GETPATH, testdir_path), "Calling fcntl() to get the path");
134 	T_ASSERT_POSIX_SUCCESS(close(fd), "Closing %s", testdir_path);
135 
136 	/* Setup file names */
137 	snprintf(file, sizeof(file), "%s/%s", testdir_path, "file");
138 	snprintf(file_rsrcfork, sizeof(file_rsrcfork), "%s/%s", file, _PATH_RSRCFORKSPEC);
139 
140 	/* Create the test file */
141 	T_ASSERT_POSIX_SUCCESS((fd = open(file, O_CREAT | O_RDWR, 0777)), "Creating '%s'", file);
142 	T_ASSERT_POSIX_SUCCESS(close(fd), "Closing '%s'", file);
143 
144 	/* Create sandbox variables */
145 	T_ASSERT_POSIX_NOTNULL(params = sandbox_create_params(), "Creating Sandbox params object");
146 	create_profile_string(profile_string, sizeof(profile_string));
147 	T_ASSERT_POSIX_NOTNULL(profile = sandbox_compile_string(profile_string, params, &sberror), "Creating Sandbox profile object");
148 
149 	T_SETUPEND;
150 
151 	/* Test stat()/fstat() */
152 	do_test(0);
153 
154 	/* Apply sandbox profile */
155 	T_ASSERT_POSIX_SUCCESS(sandbox_apply(profile), "Applying Sandbox profile");
156 
157 	/* Test stat()/fstat() */
158 	do_test(EPERM);
159 }
160