1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "sandbox/linux/syscall_broker/broker_file_permission.h"
10 #include <sys/types.h>
13 #include "base/logging.h"
14 #include "base/macros.h"
15 #include "sandbox/linux/tests/test_utils.h"
16 #include "sandbox/linux/tests/unit_tests.h"
17 #include "testing/gtest/include/gtest/gtest.h"
21 namespace syscall_broker
{
23 class BrokerFilePermissionTester
{
25 static bool ValidatePath(const char* path
) {
26 return BrokerFilePermission::ValidatePath(path
);
28 static const char* GetErrorMessage() {
29 return BrokerFilePermission::GetErrorMessageForTests();
33 DISALLOW_COPY_AND_ASSIGN(BrokerFilePermissionTester
);
38 // Creation tests are DEATH tests as a bad permission causes termination.
39 SANDBOX_TEST(BrokerFilePermission
, CreateGood
) {
40 const char kPath
[] = "/tmp/good";
41 BrokerFilePermission perm
= BrokerFilePermission::ReadOnly(kPath
);
44 SANDBOX_TEST(BrokerFilePermission
, CreateGoodRecursive
) {
45 const char kPath
[] = "/tmp/good/";
46 BrokerFilePermission perm
= BrokerFilePermission::ReadOnlyRecursive(kPath
);
52 DEATH_MESSAGE(BrokerFilePermissionTester::GetErrorMessage())) {
53 const char kPath
[] = "/tmp/bad/";
54 BrokerFilePermission perm
= BrokerFilePermission::ReadOnly(kPath
);
60 DEATH_MESSAGE(BrokerFilePermissionTester::GetErrorMessage())) {
61 const char kPath
[] = "/tmp/bad";
62 BrokerFilePermission perm
= BrokerFilePermission::ReadOnlyRecursive(kPath
);
68 DEATH_MESSAGE(BrokerFilePermissionTester::GetErrorMessage())) {
69 const char kPath
[] = "tmp/bad";
70 BrokerFilePermission perm
= BrokerFilePermission::ReadOnly(kPath
);
76 DEATH_MESSAGE(BrokerFilePermissionTester::GetErrorMessage())) {
77 const char kPath
[] = "";
78 BrokerFilePermission perm
= BrokerFilePermission::ReadOnly(kPath
);
81 // CheckPerm tests |path| against |perm| given |access_flags|.
82 // If |create| is true then file creation is tested for success.
83 void CheckPerm(const BrokerFilePermission
& perm
,
87 const char* file_to_open
= NULL
;
89 ASSERT_FALSE(perm
.CheckAccess(path
, X_OK
, NULL
));
90 ASSERT_TRUE(perm
.CheckAccess(path
, F_OK
, NULL
));
92 switch (access_flags
) {
94 ASSERT_TRUE(perm
.CheckOpen(path
, O_RDONLY
, &file_to_open
, NULL
));
95 ASSERT_FALSE(perm
.CheckOpen(path
, O_WRONLY
, &file_to_open
, NULL
));
96 ASSERT_FALSE(perm
.CheckOpen(path
, O_RDWR
, &file_to_open
, NULL
));
97 ASSERT_TRUE(perm
.CheckAccess(path
, R_OK
, NULL
));
98 ASSERT_FALSE(perm
.CheckAccess(path
, W_OK
, NULL
));
101 ASSERT_FALSE(perm
.CheckOpen(path
, O_RDONLY
, &file_to_open
, NULL
));
102 ASSERT_TRUE(perm
.CheckOpen(path
, O_WRONLY
, &file_to_open
, NULL
));
103 ASSERT_FALSE(perm
.CheckOpen(path
, O_RDWR
, &file_to_open
, NULL
));
104 ASSERT_FALSE(perm
.CheckAccess(path
, R_OK
, NULL
));
105 ASSERT_TRUE(perm
.CheckAccess(path
, W_OK
, NULL
));
108 ASSERT_TRUE(perm
.CheckOpen(path
, O_RDONLY
, &file_to_open
, NULL
));
109 ASSERT_TRUE(perm
.CheckOpen(path
, O_WRONLY
, &file_to_open
, NULL
));
110 ASSERT_TRUE(perm
.CheckOpen(path
, O_RDWR
, &file_to_open
, NULL
));
111 ASSERT_TRUE(perm
.CheckAccess(path
, R_OK
, NULL
));
112 ASSERT_TRUE(perm
.CheckAccess(path
, W_OK
, NULL
));
119 // O_SYNC can be defined as (__O_SYNC|O_DSYNC)
121 const int kSyncFlag
= O_SYNC
& ~O_DSYNC
;
123 const int kSyncFlag
= O_SYNC
;
126 const int kNumberOfBitsInOAccMode
= 2;
127 static_assert(O_ACCMODE
== ((1 << kNumberOfBitsInOAccMode
) - 1),
128 "incorrect number of bits");
129 // check every possible flag and act accordingly.
130 // Skipping AccMode bits as they are present in every case.
131 for (int i
= kNumberOfBitsInOAccMode
; i
< 32; i
++) {
147 #if (O_NONBLOCK != O_NDELAY)
153 perm
.CheckOpen(path
, access_flags
| flag
, &file_to_open
, NULL
));
159 perm
.CheckOpen(path
, access_flags
| flag
, &file_to_open
, NULL
));
164 ASSERT_TRUE(perm
.CheckOpen(path
, O_CREAT
| O_EXCL
| access_flags
,
165 &file_to_open
, &unlink
));
166 ASSERT_FALSE(unlink
);
168 ASSERT_FALSE(perm
.CheckOpen(path
, O_CREAT
| O_EXCL
| access_flags
,
169 &file_to_open
, NULL
));
173 TEST(BrokerFilePermission
, ReadOnly
) {
174 const char kPath
[] = "/tmp/good";
175 BrokerFilePermission perm
= BrokerFilePermission::ReadOnly(kPath
);
176 CheckPerm(perm
, kPath
, O_RDONLY
, false);
177 // Don't do anything here, so that ASSERT works in the subfunction as
181 TEST(BrokerFilePermission
, ReadOnlyRecursive
) {
182 const char kPath
[] = "/tmp/good/";
183 const char kPathFile
[] = "/tmp/good/file";
184 BrokerFilePermission perm
= BrokerFilePermission::ReadOnlyRecursive(kPath
);
185 CheckPerm(perm
, kPathFile
, O_RDONLY
, false);
186 // Don't do anything here, so that ASSERT works in the subfunction as
190 TEST(BrokerFilePermission
, WriteOnly
) {
191 const char kPath
[] = "/tmp/good";
192 BrokerFilePermission perm
= BrokerFilePermission::WriteOnly(kPath
);
193 CheckPerm(perm
, kPath
, O_WRONLY
, false);
194 // Don't do anything here, so that ASSERT works in the subfunction as
198 TEST(BrokerFilePermission
, ReadWrite
) {
199 const char kPath
[] = "/tmp/good";
200 BrokerFilePermission perm
= BrokerFilePermission::ReadWrite(kPath
);
201 CheckPerm(perm
, kPath
, O_RDWR
, false);
202 // Don't do anything here, so that ASSERT works in the subfunction as
206 TEST(BrokerFilePermission
, ReadWriteCreate
) {
207 const char kPath
[] = "/tmp/good";
208 BrokerFilePermission perm
= BrokerFilePermission::ReadWriteCreate(kPath
);
209 CheckPerm(perm
, kPath
, O_RDWR
, true);
210 // Don't do anything here, so that ASSERT works in the subfunction as
214 void CheckUnlink(BrokerFilePermission
& perm
,
218 ASSERT_FALSE(perm
.CheckOpen(path
, access_flags
, NULL
, &unlink
));
219 ASSERT_FALSE(perm
.CheckOpen(path
, access_flags
| O_CREAT
, NULL
, &unlink
));
221 perm
.CheckOpen(path
, access_flags
| O_CREAT
| O_EXCL
, NULL
, &unlink
));
225 TEST(BrokerFilePermission
, ReadWriteCreateUnlink
) {
226 const char kPath
[] = "/tmp/good";
227 BrokerFilePermission perm
=
228 BrokerFilePermission::ReadWriteCreateUnlink(kPath
);
229 CheckUnlink(perm
, kPath
, O_RDWR
);
230 // Don't do anything here, so that ASSERT works in the subfunction as
234 TEST(BrokerFilePermission
, ReadWriteCreateUnlinkRecursive
) {
235 const char kPath
[] = "/tmp/good/";
236 const char kPathFile
[] = "/tmp/good/file";
237 BrokerFilePermission perm
=
238 BrokerFilePermission::ReadWriteCreateUnlinkRecursive(kPath
);
239 CheckUnlink(perm
, kPathFile
, O_RDWR
);
240 // Don't do anything here, so that ASSERT works in the subfunction as
244 TEST(BrokerFilePermission
, ValidatePath
) {
245 EXPECT_TRUE(BrokerFilePermissionTester::ValidatePath("/path"));
246 EXPECT_TRUE(BrokerFilePermissionTester::ValidatePath("/"));
247 EXPECT_TRUE(BrokerFilePermissionTester::ValidatePath("/..path"));
249 EXPECT_FALSE(BrokerFilePermissionTester::ValidatePath(""));
250 EXPECT_FALSE(BrokerFilePermissionTester::ValidatePath("bad"));
251 EXPECT_FALSE(BrokerFilePermissionTester::ValidatePath("/bad/"));
252 EXPECT_FALSE(BrokerFilePermissionTester::ValidatePath("bad/"));
253 EXPECT_FALSE(BrokerFilePermissionTester::ValidatePath("/bad/.."));
254 EXPECT_FALSE(BrokerFilePermissionTester::ValidatePath("/bad/../bad"));
255 EXPECT_FALSE(BrokerFilePermissionTester::ValidatePath("/../bad"));
260 } // namespace syscall_broker
262 } // namespace sandbox