1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include <cerrno>
16 #include <chrono>
17 #include <gtest/gtest.h>
18 #include <securec.h>
19 #include <sys/stat.h>
20 #include <sys/types.h>
21 #include <thread>
22
23 #include "c_mock_common.h"
24 #define private public
25 #include "dlp_link_manager.h"
26 #undef private
27 #include "dlp_fuse_helper.h"
28 #include "dlp_permission.h"
29 #include "dlp_permission_log.h"
30 #include "fuse_daemon.h"
31
32 namespace OHOS {
33 namespace Security {
34 namespace DlpPermission {
35 using namespace testing::ext;
36
37 namespace {
38 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_DLP_PERMISSION, "FuseDaemonTest"};
39
40 static const fuse_ino_t ROOT_INODE = 1;
41 static const int DEFAULT_ATTR_TIMEOUT = 10000;
42 static const uint32_t MAX_FUSE_READ_BUFF_SIZE = 10 * 1024 * 1024; // 10M
43 static const uint32_t MAX_READ_DIR_BUF_SIZE = 100 * 1024; // 100K
44
45 static int g_fuseReplyErr = 0;
46 static struct fuse_file_info g_fuseReplyOpen;
47 static struct fuse_entry_param g_fuseReplyEntry;
48 static struct stat g_fuseReplyAttr;
49 static double g_fuseReplyAttrTimeout = 0.0F;
50 static size_t g_fuseReplyBufSize = 0;
51 static int g_session;
52 static const std::string DLP_TEST_DIR = "/data/dlpTest/";
53 static DlpLinkManager* dlpLinkManager = nullptr;
54 constexpr int WAIT_SECOND = 1;
55
FuseReplyErrMock(fuse_req_t req,int err)56 static int FuseReplyErrMock(fuse_req_t req, int err)
57 {
58 (void)req;
59 g_fuseReplyErr = err;
60 return 0;
61 }
62
FuseReplyOpenMock(fuse_req_t req,const struct fuse_file_info * f)63 static int FuseReplyOpenMock(fuse_req_t req, const struct fuse_file_info *f)
64 {
65 (void)req;
66 g_fuseReplyOpen = *f;
67 return 0;
68 }
69
FuseReplyEntryMock(fuse_req_t req,const struct fuse_entry_param * e)70 int FuseReplyEntryMock(fuse_req_t req, const struct fuse_entry_param *e)
71 {
72 (void)req;
73 g_fuseReplyEntry = *e;
74 return 0;
75 }
76
FuseReplyAttrMock(fuse_req_t req,const struct stat * attr,double attr_timeout)77 int FuseReplyAttrMock(fuse_req_t req, const struct stat *attr, double attr_timeout)
78 {
79 (void)req;
80 g_fuseReplyAttr = *attr;
81 g_fuseReplyAttrTimeout = attr_timeout;
82 return 0;
83 }
84
85 static const size_t ADD_DIRENTRY_BUFF_LEN = 100;
FuseAddDirentryMockCurDirFail(fuse_req_t req,char * buf,size_t bufsize,const char * name,const struct stat * stbuf,off_t off)86 size_t FuseAddDirentryMockCurDirFail(fuse_req_t req, char *buf, size_t bufsize,
87 const char *name, const struct stat *stbuf, off_t off)
88 {
89 (void)req;
90 (void)buf;
91 (void)bufsize;
92 (void)name;
93 (void)stbuf;
94 (void)off;
95 return ADD_DIRENTRY_BUFF_LEN + 1;
96 }
97
FuseAddDirentryMockUpperDirFail(fuse_req_t req,char * buf,size_t bufsize,const char * name,const struct stat * stbuf,off_t off)98 size_t FuseAddDirentryMockUpperDirFail(fuse_req_t req, char *buf, size_t bufsize,
99 const char *name, const struct stat *stbuf, off_t off)
100 {
101 (void)req;
102 (void)buf;
103 (void)bufsize;
104 (void)stbuf;
105 (void)off;
106 if (strcmp(name, ".") == 0) {
107 return strlen(".");
108 }
109 return ADD_DIRENTRY_BUFF_LEN + 1;
110 }
111
FuseAddDirentryMockTestFileFail(fuse_req_t req,char * buf,size_t bufsize,const char * name,const struct stat * stbuf,off_t off)112 size_t FuseAddDirentryMockTestFileFail(fuse_req_t req, char *buf, size_t bufsize,
113 const char *name, const struct stat *stbuf, off_t off)
114 {
115 (void)req;
116 (void)buf;
117 (void)bufsize;
118 (void)stbuf;
119 (void)off;
120 if (strcmp(name, "test") != 0) {
121 return strlen(name);
122 }
123 return ADD_DIRENTRY_BUFF_LEN + 1;
124 }
125
FuseReplyBufMock(fuse_req_t req,const char * buf,size_t size)126 int FuseReplyBufMock(fuse_req_t req, const char *buf, size_t size)
127 {
128 (void)req;
129 (void)buf;
130 (void)size;
131 g_fuseReplyBufSize = 0;
132 return 0;
133 }
134
135
FuseSessionNewMock(struct fuse_args * args,const struct fuse_lowlevel_ops * op,size_t opSize,void * userdata)136 struct fuse_session *FuseSessionNewMock(struct fuse_args *args, const struct fuse_lowlevel_ops *op,
137 size_t opSize, void *userdata)
138 {
139 (void)args;
140 (void)op;
141 (void)opSize;
142 (void)userdata;
143 return reinterpret_cast<struct fuse_session *>(&g_session);
144 }
145
FuseSessionMountMock(struct fuse_session * se,const char * mountpoint)146 int FuseSessionMountMock(struct fuse_session *se, const char *mountpoint)
147 {
148 (void)se;
149 (void)mountpoint;
150 return 0;
151 }
152
GetDlpLinkManager(int timeout)153 static bool GetDlpLinkManager(int timeout)
154 {
155 auto start = std::chrono::system_clock::now();
156 while (std::chrono::system_clock::now() - start < std::chrono::seconds(timeout)) {
157 dlpLinkManager = DlpFuseHelper::GetDlpLinkManagerInstance();
158 if (dlpLinkManager) {
159 return true;
160 }
161 std::this_thread::yield();
162 }
163 return false;
164 }
165 }
166
167 class FuseDaemonTest : public testing::Test {
168 public:
SetUpTestCase()169 static void SetUpTestCase()
170 {
171 struct stat fstat;
172 if (stat(DLP_TEST_DIR.c_str(), &fstat) != 0) {
173 if (errno == ENOENT) {
174 int32_t ret = mkdir(DLP_TEST_DIR.c_str(), S_IRWXU | S_IRWXG | S_IRWXO);
175 if (ret < 0) {
176 DLP_LOG_ERROR(LABEL, "mkdir mount point failed errno %{public}d", errno);
177 return;
178 }
179 } else {
180 DLP_LOG_ERROR(LABEL, "get mount point failed errno %{public}d", errno);
181 return;
182 }
183 }
184
185 if (!GetDlpLinkManager(WAIT_SECOND)) {
186 DLP_LOG_ERROR(LABEL, "get dlplinkmanger instance failed");
187 return;
188 }
189 };
190
TearDownTestCase()191 static void TearDownTestCase()
192 {
193 rmdir(DLP_TEST_DIR.c_str());
194 };
195
SetUp()196 void SetUp() {};
197
TearDown()198 void TearDown() {};
199 };
200
201 /**
202 * @tc.name: FuseDaemonLookup001
203 * @tc.desc: test fuse lookup callback abnormal branch
204 * @tc.type: FUNC
205 * @tc.require:AR000GVIGC
206 */
207 HWTEST_F(FuseDaemonTest, FuseDaemonLookup001, TestSize.Level1)
208 {
209 DLP_LOG_INFO(LABEL, "FuseDaemonLookup001");
210 DlpLinkFile linkfile("test", nullptr);
211 fuse_ino_t ino = static_cast<fuse_ino_t>(reinterpret_cast<uintptr_t>(&linkfile));
212 fuse_req_t req = nullptr;
213
214 // file name null
215 DlpCMockCondition condition;
216 condition.mockSequence = { true };
217 SetMockConditions("fuse_reply_err", condition);
218 SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
219 g_fuseReplyErr = 0;
220 FuseDaemon::fuseDaemonOper_.lookup(req, ROOT_INODE, nullptr);
221 EXPECT_EQ(ENOENT, g_fuseReplyErr);
222 CleanMockConditions();
223
224 // ino != ROOT_INODE
225 condition.mockSequence = { true };
226 SetMockConditions("fuse_reply_err", condition);
227 SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
228 g_fuseReplyErr = 0;
229 FuseDaemon::fuseDaemonOper_.lookup(req, ino, "test");
230 EXPECT_EQ(ENOENT, g_fuseReplyErr);
231 CleanMockConditions();
232
233 // name = '.'
234 condition.mockSequence = { true };
235 SetMockConditions("fuse_reply_entry", condition);
236 SetMockCallback("fuse_reply_entry", reinterpret_cast<CommonMockFuncT>(FuseReplyEntryMock));
237 (void)memset_s(&g_fuseReplyEntry, sizeof(g_fuseReplyEntry), 0, sizeof(g_fuseReplyEntry));
238 FuseDaemon::fuseDaemonOper_.lookup(req, ROOT_INODE, ".");
239 EXPECT_EQ(ROOT_INODE, g_fuseReplyEntry.ino);
240 CleanMockConditions();
241
242 // name = '..'
243 condition.mockSequence = { true };
244 SetMockConditions("fuse_reply_entry", condition);
245 SetMockCallback("fuse_reply_entry", reinterpret_cast<CommonMockFuncT>(FuseReplyEntryMock));
246 (void)memset_s(&g_fuseReplyEntry, sizeof(g_fuseReplyEntry), 0, sizeof(g_fuseReplyEntry));
247 FuseDaemon::fuseDaemonOper_.lookup(req, ROOT_INODE, "..");
248 EXPECT_EQ(ROOT_INODE, g_fuseReplyEntry.ino);
249 CleanMockConditions();
250
251 // name = '..'
252 condition.mockSequence = { true };
253 SetMockConditions("fuse_reply_err", condition);
254 SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
255 g_fuseReplyErr = 0;
256 FuseDaemon::fuseDaemonOper_.lookup(req, ROOT_INODE, "test");
257 EXPECT_EQ(ENOENT, g_fuseReplyErr);
258 CleanMockConditions();
259 }
260
261 /**
262 * @tc.name: FuseDaemonGetattr001
263 * @tc.desc: test fuse getattr callback abnormal branch
264 * @tc.type: FUNC
265 * @tc.require:AR000GVIGC
266 */
267 HWTEST_F(FuseDaemonTest, FuseDaemonGetattr001, TestSize.Level1)
268 {
269 DLP_LOG_INFO(LABEL, "FuseDaemonGetattr001");
270 fuse_req_t req = nullptr;
271
272 // get ROOT_INODE attr
273 DlpCMockCondition condition;
274 condition.mockSequence = { true };
275 SetMockConditions("fuse_reply_attr", condition);
276 SetMockCallback("fuse_reply_attr", reinterpret_cast<CommonMockFuncT>(FuseReplyAttrMock));
277 (void)memset_s(&g_fuseReplyAttr, sizeof(g_fuseReplyAttr), 0, sizeof(g_fuseReplyAttr));
278 g_fuseReplyAttrTimeout = 0.0F;
279 FuseDaemon::fuseDaemonOper_.getattr(req, ROOT_INODE, nullptr);
280 EXPECT_EQ(memcmp(&FuseDaemon::rootFileStat_, &g_fuseReplyAttr, sizeof(struct stat)), 0);
281 EXPECT_EQ(DEFAULT_ATTR_TIMEOUT, g_fuseReplyAttrTimeout);
282 CleanMockConditions();
283
284 // get not exist link file
285 SetMockConditions("fuse_reply_err", condition);
286 SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
287 g_fuseReplyErr = 0;
288 FuseDaemon::fuseDaemonOper_.getattr(req, 0, nullptr);
289 EXPECT_EQ(ENOENT, g_fuseReplyErr);
290 CleanMockConditions();
291 }
292
293 /**
294 * @tc.name: FuseDaemonOpen001
295 * @tc.desc: test fuse open callback abnormal branch
296 * @tc.type: FUNC
297 * @tc.require:AR000GVIGC
298 */
299 HWTEST_F(FuseDaemonTest, FuseDaemonOpen001, TestSize.Level1)
300 {
301 DLP_LOG_INFO(LABEL, "FuseDaemonOpen001");
302 fuse_req_t req = nullptr;
303
304 // open ROOT_INODE
305 DlpCMockCondition condition;
306 condition.mockSequence = { true };
307 SetMockConditions("fuse_reply_err", condition);
308 SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
309 g_fuseReplyErr = 0;
310 FuseDaemon::fuseDaemonOper_.open(req, ROOT_INODE, nullptr);
311 EXPECT_EQ(ENOENT, g_fuseReplyErr);
312 CleanMockConditions();
313
314 // open null file
315 condition.mockSequence = { true };
316 SetMockConditions("fuse_reply_err", condition);
317 SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
318 g_fuseReplyErr = 0;
319 FuseDaemon::fuseDaemonOper_.open(req, 0, nullptr);
320 EXPECT_EQ(ENOENT, g_fuseReplyErr);
321 CleanMockConditions();
322
323 // open readonly dlp with O_TRUNC
324 std::shared_ptr<DlpFile> dlpFile = std::make_shared<DlpFile>(-1, DLP_TEST_DIR, 0, false);
325 ASSERT_NE(dlpFile, nullptr);
326 DlpLinkFile linkfile("test", dlpFile);
327 fuse_ino_t ino = static_cast<fuse_ino_t>(reinterpret_cast<uintptr_t>(&linkfile));
328 struct fuse_file_info fi;
329 fi.flags = O_TRUNC;
330
331 condition.mockSequence = { true };
332 SetMockConditions("fuse_reply_err", condition);
333 SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
334 g_fuseReplyErr = 0;
335 FuseDaemon::fuseDaemonOper_.open(req, ino, &fi);
336 EXPECT_EQ(EINVAL, g_fuseReplyErr);
337 CleanMockConditions();
338
339 fi.flags = O_RDWR;
340 condition.mockSequence = { true };
341 SetMockConditions("fuse_reply_open", condition);
342 SetMockCallback("fuse_reply_open", reinterpret_cast<CommonMockFuncT>(FuseReplyOpenMock));
343 (void)memset_s(&g_fuseReplyOpen, sizeof(g_fuseReplyOpen), 0, sizeof(g_fuseReplyOpen));
344 FuseDaemon::fuseDaemonOper_.open(req, ino, &fi);
345 EXPECT_EQ(O_RDWR, g_fuseReplyOpen.flags);
346 CleanMockConditions();
347 }
348
349 /**
350 * @tc.name: FuseDaemonRead001
351 * @tc.desc: test fuse read callback abnormal branch
352 * @tc.type: FUNC
353 * @tc.require:AR000GVIGC
354 */
355 HWTEST_F(FuseDaemonTest, FuseDaemonRead001, TestSize.Level1)
356 {
357 DLP_LOG_INFO(LABEL, "FuseDaemonRead001");
358 fuse_req req;
359 req.ctx.uid = getuid();
360
361 // offset < 0
362 DlpCMockCondition condition;
363 condition.mockSequence = { true };
364 SetMockConditions("fuse_reply_err", condition);
365 SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
366 g_fuseReplyErr = 0;
367 FuseDaemon::fuseDaemonOper_.read(&req, ROOT_INODE, 1, -1, nullptr);
368 EXPECT_EQ(EINVAL, g_fuseReplyErr);
369 CleanMockConditions();
370
371 // offset > DLP_MAX_CONTENT_SIZE
372 condition.mockSequence = { true };
373 SetMockConditions("fuse_reply_err", condition);
374 SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
375 g_fuseReplyErr = 0;
376 FuseDaemon::fuseDaemonOper_.read(&req, ROOT_INODE, 1, DLP_MAX_CONTENT_SIZE + 1, nullptr);
377 EXPECT_EQ(EINVAL, g_fuseReplyErr);
378 CleanMockConditions();
379
380 // size > MAX_FUSE_READ_BUFF_SIZE
381 condition.mockSequence = { true };
382 SetMockConditions("fuse_reply_err", condition);
383 SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
384 g_fuseReplyErr = 0;
385 FuseDaemon::fuseDaemonOper_.read(&req, ROOT_INODE, MAX_FUSE_READ_BUFF_SIZE + 1, 0, nullptr);
386 EXPECT_EQ(EINVAL, g_fuseReplyErr);
387 CleanMockConditions();
388 }
389
390 /**
391 * @tc.name: FuseDaemonRead002
392 * @tc.desc: test fuse read callback abnormal branch2
393 * @tc.type: FUNC
394 * @tc.require:AR000GVIGC
395 */
396 HWTEST_F(FuseDaemonTest, FuseDaemonRead002, TestSize.Level1)
397 {
398 DLP_LOG_INFO(LABEL, "FuseDaemonRead002");
399 fuse_req req;
400 req.ctx.uid = getuid();
401
402 // ino ROOT_INODE
403 DlpCMockCondition condition;
404 condition.mockSequence = { true };
405 SetMockConditions("fuse_reply_err", condition);
406 SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
407 g_fuseReplyErr = 0;
408 FuseDaemon::fuseDaemonOper_.read(&req, ROOT_INODE, 10, 0, nullptr);
409 EXPECT_EQ(ENOENT, g_fuseReplyErr);
410 CleanMockConditions();
411
412 // ino 0
413 condition.mockSequence = { true };
414 SetMockConditions("fuse_reply_err", condition);
415 SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
416 g_fuseReplyErr = 0;
417 FuseDaemon::fuseDaemonOper_.read(&req, 0, 10, 0, nullptr);
418 EXPECT_EQ(EBADF, g_fuseReplyErr);
419 CleanMockConditions();
420
421 // can not read dlp file
422 std::shared_ptr<DlpFile> dlpFile = std::make_shared<DlpFile>(-1, DLP_TEST_DIR, 0, false);
423 ASSERT_NE(dlpFile, nullptr);
424 DlpLinkFile linkfile("test", dlpFile);
425 fuse_ino_t ino = static_cast<fuse_ino_t>(reinterpret_cast<uintptr_t>(&linkfile));
426
427 condition.mockSequence = { true };
428 SetMockConditions("fuse_reply_err", condition);
429 SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
430 g_fuseReplyErr = 0;
431 FuseDaemon::fuseDaemonOper_.read(&req, ino, 10, 0, nullptr);
432 EXPECT_EQ(EIO, g_fuseReplyErr);
433 CleanMockConditions();
434 }
435
436 /**
437 * @tc.name: FuseDaemonWrite001
438 * @tc.desc: test fuse write callback abnormal branch
439 * @tc.type: FUNC
440 * @tc.require:AR000GVIGC
441 */
442 HWTEST_F(FuseDaemonTest, FuseDaemonWrite001, TestSize.Level1)
443 {
444 DLP_LOG_INFO(LABEL, "FuseDaemonWrite001");
445 fuse_req_t req = nullptr;
446
447 // offset < 0
448 DlpCMockCondition condition;
449 condition.mockSequence = { true };
450 SetMockConditions("fuse_reply_err", condition);
451 SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
452 g_fuseReplyErr = 0;
453 FuseDaemon::fuseDaemonOper_.write(req, ROOT_INODE, nullptr, 1, -1, nullptr);
454 EXPECT_EQ(EINVAL, g_fuseReplyErr);
455 CleanMockConditions();
456
457 // offset > DLP_MAX_CONTENT_SIZE
458 condition.mockSequence = { true };
459 SetMockConditions("fuse_reply_err", condition);
460 SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
461 g_fuseReplyErr = 0;
462 FuseDaemon::fuseDaemonOper_.write(req, ROOT_INODE, nullptr, 1, DLP_MAX_CONTENT_SIZE + 1, nullptr);
463 EXPECT_EQ(EINVAL, g_fuseReplyErr);
464 CleanMockConditions();
465
466 // size > DLP_FUSE_MAX_BUFFLEN
467 condition.mockSequence = { true };
468 SetMockConditions("fuse_reply_err", condition);
469 SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
470 g_fuseReplyErr = 0;
471 FuseDaemon::fuseDaemonOper_.write(req, ROOT_INODE, nullptr, DLP_FUSE_MAX_BUFFLEN + 1, 100, nullptr);
472 EXPECT_EQ(EINVAL, g_fuseReplyErr);
473 CleanMockConditions();
474
475 // ino ROOT_INODE
476 condition.mockSequence = { true };
477 SetMockConditions("fuse_reply_err", condition);
478 SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
479 g_fuseReplyErr = 0;
480 FuseDaemon::fuseDaemonOper_.write(req, ROOT_INODE, nullptr, 1, 0, nullptr);
481 EXPECT_EQ(ENOENT, g_fuseReplyErr);
482 CleanMockConditions();
483
484 // can not write dlp file
485 std::shared_ptr<DlpFile> dlpFile = std::make_shared<DlpFile>(-1, DLP_TEST_DIR, 0, false);
486 ASSERT_NE(dlpFile, nullptr);
487 DlpLinkFile linkfile("test", dlpFile);
488 fuse_ino_t ino = static_cast<fuse_ino_t>(reinterpret_cast<uintptr_t>(&linkfile));
489
490 condition.mockSequence = { true };
491 SetMockConditions("fuse_reply_err", condition);
492 SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
493 g_fuseReplyErr = 0;
494 FuseDaemon::fuseDaemonOper_.write(req, ino, nullptr, 1, 0, nullptr);
495 EXPECT_EQ(EIO, g_fuseReplyErr);
496 CleanMockConditions();
497 }
498
499 /**
500 * @tc.name: FuseDaemonForget001
501 * @tc.desc: test fuse forget callback abnormal branch
502 * @tc.type: FUNC
503 * @tc.require:AR000GVIGC
504 */
505 HWTEST_F(FuseDaemonTest, FuseDaemonForget001, TestSize.Level1)
506 {
507 DLP_LOG_INFO(LABEL, "FuseDaemonForget001");
508 fuse_req_t req = nullptr;
509
510 // ino ROOT_INODE
511 DlpCMockCondition condition;
512 condition.mockSequence = { true };
513 SetMockConditions("fuse_reply_err", condition);
514 SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
515 g_fuseReplyErr = 0;
516 FuseDaemon::fuseDaemonOper_.forget(req, ROOT_INODE, 1);
517 EXPECT_EQ(ENOENT, g_fuseReplyErr);
518 CleanMockConditions();
519
520 condition.mockSequence = { true };
521 SetMockConditions("fuse_reply_err", condition);
522 SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
523 g_fuseReplyErr = 0;
524 FuseDaemon::fuseDaemonOper_.forget(req, 0, 1);
525 EXPECT_EQ(EBADF, g_fuseReplyErr);
526 CleanMockConditions();
527 }
528
529 /**
530 * @tc.name: FuseDaemonReadDir001
531 * @tc.desc: test fuse read dir callback abnormal branch
532 * @tc.type: FUNC
533 * @tc.require:AR000GVIGC
534 */
535 HWTEST_F(FuseDaemonTest, FuseDaemonReadDir001, TestSize.Level1)
536 {
537 DLP_LOG_INFO(LABEL, "FuseDaemonReadDir001");
538 fuse_req_t req = nullptr;
539
540 // off < 0
541 DlpCMockCondition condition;
542 condition.mockSequence = { true };
543 SetMockConditions("fuse_reply_err", condition);
544 SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
545 g_fuseReplyErr = 0;
546 FuseDaemon::fuseDaemonOper_.readdir(req, ROOT_INODE, 10, -1, nullptr);
547 EXPECT_EQ(ENOTDIR, g_fuseReplyErr);
548
549 // off > DLP_MAX_CONTENT_SIZE
550 condition.mockSequence = { true };
551 SetMockConditions("fuse_reply_err", condition);
552 SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
553 g_fuseReplyErr = 0;
554 FuseDaemon::fuseDaemonOper_.readdir(req, ROOT_INODE, 10, DLP_MAX_CONTENT_SIZE + 1, nullptr);
555 EXPECT_EQ(ENOTDIR, g_fuseReplyErr);
556 CleanMockConditions();
557
558 // ino != ROOT_INODE
559 condition.mockSequence = { true };
560 SetMockConditions("fuse_reply_err", condition);
561 SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
562 g_fuseReplyErr = 0;
563 FuseDaemon::fuseDaemonOper_.readdir(req, 0, 10, 0, nullptr);
564 EXPECT_EQ(ENOTDIR, g_fuseReplyErr);
565 CleanMockConditions();
566
567 // size > MAX_READ_DIR_BUF_SIZE
568 condition.mockSequence = { true };
569 SetMockConditions("fuse_reply_err", condition);
570 SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
571 g_fuseReplyErr = 0;
572 FuseDaemon::fuseDaemonOper_.readdir(req, ROOT_INODE, MAX_READ_DIR_BUF_SIZE + 1, 0, nullptr);
573 EXPECT_EQ(EINVAL, g_fuseReplyErr);
574 CleanMockConditions();
575 }
576
577 /**
578 * @tc.name: FuseDaemonReadDir002
579 * @tc.desc: test fuse AddDirentry callback CUR_DIR entry too large
580 * @tc.type: FUNC
581 * @tc.require:AR000GVIGC
582 */
583 HWTEST_F(FuseDaemonTest, FuseDaemonReadDir002, TestSize.Level1)
584 {
585 DLP_LOG_INFO(LABEL, "FuseDaemonReadDir002");
586 fuse_req_t req = nullptr;
587
588 DlpCMockCondition condition;
589 condition.mockSequence = { true };
590 SetMockConditions("fuse_reply_err", condition);
591 SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
592
593 DlpCMockCondition condition1;
594 condition1.mockSequence = { true };
595 SetMockConditions("fuse_add_direntry", condition1);
596 SetMockCallback("fuse_add_direntry", reinterpret_cast<CommonMockFuncT>(FuseAddDirentryMockCurDirFail));
597
598 g_fuseReplyErr = 0;
599 FuseDaemon::fuseDaemonOper_.readdir(req, ROOT_INODE, ADD_DIRENTRY_BUFF_LEN, 0, nullptr);
600 EXPECT_EQ(EINVAL, g_fuseReplyErr);
601 CleanMockConditions();
602 }
603
604 /**
605 * @tc.name: FuseDaemonReadDir003
606 * @tc.desc: test fuse AddDirentry callback UPPER_DIR entry too large
607 * @tc.type: FUNC
608 * @tc.require:AR000GVIGC
609 */
610 HWTEST_F(FuseDaemonTest, FuseDaemonReadDir003, TestSize.Level1)
611 {
612 DLP_LOG_INFO(LABEL, "FuseDaemonReadDir003");
613 fuse_req_t req = nullptr;
614
615 DlpCMockCondition condition;
616 condition.mockSequence = { true };
617 SetMockConditions("fuse_reply_err", condition);
618 SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
619
620 DlpCMockCondition condition1;
621 condition1.mockSequence = { true, true, true };
622 SetMockConditions("fuse_add_direntry", condition1);
623 SetMockCallback("fuse_add_direntry", reinterpret_cast<CommonMockFuncT>(FuseAddDirentryMockUpperDirFail));
624
625 g_fuseReplyErr = 0;
626 FuseDaemon::fuseDaemonOper_.readdir(req, ROOT_INODE, ADD_DIRENTRY_BUFF_LEN, 0, nullptr);
627 EXPECT_EQ(EINVAL, g_fuseReplyErr);
628 CleanMockConditions();
629 }
630
631 /**
632 * @tc.name: FuseDaemonReadDir004
633 * @tc.desc: test fuse AddDirentry callback test file entry fail
634 * @tc.type: FUNC
635 * @tc.require:AR000GVIGC
636 */
637 HWTEST_F(FuseDaemonTest, FuseDaemonReadDir004, TestSize.Level1)
638 {
639 DLP_LOG_INFO(LABEL, "FuseDaemonReadDir004");
640 fuse_req_t req = nullptr;
641 std::shared_ptr<DlpFile> filePtr = std::make_shared<DlpFile>(-1, DLP_TEST_DIR, 0, false);
642 ASSERT_NE(filePtr, nullptr);
643 dlpLinkManager->dlpLinkFileNameMap_.clear();
644 dlpLinkManager->AddDlpLinkFile(filePtr, "test");
645
646 DlpCMockCondition condition;
647 condition.mockSequence = { true };
648 SetMockConditions("fuse_reply_err", condition);
649 SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
650
651 DlpCMockCondition condition1;
652 condition1.mockSequence = { true, true, true, true, true };
653 SetMockConditions("fuse_add_direntry", condition1);
654 SetMockCallback("fuse_add_direntry", reinterpret_cast<CommonMockFuncT>(FuseAddDirentryMockTestFileFail));
655 g_fuseReplyErr = 0;
656 FuseDaemon::fuseDaemonOper_.readdir(req, ROOT_INODE, ADD_DIRENTRY_BUFF_LEN, 0, nullptr);
657 EXPECT_EQ(EINVAL, g_fuseReplyErr);
658 CleanMockConditions();
659
660 dlpLinkManager->DeleteDlpLinkFile(filePtr);
661 }
662
663 /**
664 * @tc.name: FuseDaemonReadDir005
665 * @tc.desc: test fuse AddDirentry callback test file entry fail
666 * @tc.type: FUNC
667 * @tc.require:AR000GVIGC
668 */
669 HWTEST_F(FuseDaemonTest, FuseDaemonReadDir005, TestSize.Level1)
670 {
671 DLP_LOG_INFO(LABEL, "FuseDaemonReadDir005");
672 fuse_req_t req = nullptr;
673 std::shared_ptr<DlpFile> filePtr = std::make_shared<DlpFile>(-1, DLP_TEST_DIR, 0, false);
674 dlpLinkManager->AddDlpLinkFile(filePtr, "test");
675 DlpCMockCondition condition;
676 condition.mockSequence = { true };
677 SetMockConditions("fuse_reply_err", condition);
678 SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
679
680 DlpCMockCondition condition1;
681 condition1.mockSequence = { true, true, true, true, true };
682 SetMockConditions("fuse_add_direntry", condition1);
683 SetMockCallback("fuse_add_direntry", reinterpret_cast<CommonMockFuncT>(FuseAddDirentryMockTestFileFail));
684
685 DlpCMockCondition condition2;
686 condition2.mockSequence = { true };
687 SetMockConditions("fuse_reply_buf", condition2);
688 SetMockCallback("fuse_reply_buf", reinterpret_cast<CommonMockFuncT>(FuseReplyBufMock));
689
690 g_fuseReplyBufSize = 1;
691 FuseDaemon::fuseDaemonOper_.readdir(req, ROOT_INODE, ADD_DIRENTRY_BUFF_LEN, ADD_DIRENTRY_BUFF_LEN + 1, nullptr);
692 EXPECT_EQ(static_cast<size_t>(1), g_fuseReplyBufSize);
693 CleanMockConditions();
694 dlpLinkManager->DeleteDlpLinkFile(filePtr);
695 }
696
697 /**
698 * @tc.name: FuseDaemonReadDir006
699 * @tc.desc: test fuse AddDirentry callback CUR_DIR entry too large
700 * @tc.type: FUNC
701 * @tc.require:AR000GVIGC
702 */
703 HWTEST_F(FuseDaemonTest, FuseDaemonReadDir006, TestSize.Level1)
704 {
705 DLP_LOG_INFO(LABEL, "FuseDaemonReadDir006");
706 fuse_req_t req = nullptr;
707
708 DlpCMockCondition condition;
709 condition.mockSequence = { true };
710 SetMockConditions("fuse_reply_err", condition);
711 SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
712
713 DlpCMockCondition condition1;
714 condition1.mockSequence = { true };
715 SetMockConditions("fuse_add_direntry", condition1);
716 SetMockCallback("fuse_add_direntry", reinterpret_cast<CommonMockFuncT>(FuseAddDirentryMockCurDirFail));
717
718 DlpCMockCondition condition2;
719 condition2.mockSequence = { true };
720 SetMockConditions("fuse_reply_buf", condition2);
721 SetMockCallback("fuse_reply_buf", reinterpret_cast<CommonMockFuncT>(FuseReplyBufMock));
722
723 g_fuseReplyErr = 0;
724 FuseDaemon::fuseDaemonOper_.readdir(req, ROOT_INODE, ADD_DIRENTRY_BUFF_LEN + 1, DLP_MAX_CONTENT_SIZE, nullptr);
725 EXPECT_EQ(static_cast<size_t>(0), g_fuseReplyBufSize);
726 CleanMockConditions();
727 }
728
729 /**
730 * @tc.name: FuseDaemonSetAttr001
731 * @tc.desc: test fuse set attr callback abnormal test
732 * @tc.type: FUNC
733 * @tc.require:AR000GVIGC
734 */
735 HWTEST_F(FuseDaemonTest, FuseDaemonSetAttr001, TestSize.Level1)
736 {
737 DLP_LOG_INFO(LABEL, "FuseDaemonReadDir005");
738 fuse_req_t req = nullptr;
739
740 // attr = nullptr
741 DlpCMockCondition condition;
742 condition.mockSequence = { true };
743 SetMockConditions("fuse_reply_err", condition);
744 SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
745 g_fuseReplyErr = 0;
746 FuseDaemon::fuseDaemonOper_.setattr(req, 0, nullptr, 0, nullptr);
747 EXPECT_EQ(EINVAL, g_fuseReplyErr);
748 CleanMockConditions();
749
750 // ino = ROOT_INODE
751 condition.mockSequence = { true };
752 SetMockConditions("fuse_reply_err", condition);
753 SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
754 g_fuseReplyErr = 0;
755 struct stat attr;
756 FuseDaemon::fuseDaemonOper_.setattr(req, ROOT_INODE, &attr, 0, nullptr);
757 EXPECT_EQ(EACCES, g_fuseReplyErr);
758 CleanMockConditions();
759
760 // ino = 0
761 condition.mockSequence = { true };
762 SetMockConditions("fuse_reply_err", condition);
763 SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
764 g_fuseReplyErr = 0;
765 FuseDaemon::fuseDaemonOper_.setattr(req, 0, &attr, 0, nullptr);
766 EXPECT_EQ(ENOENT, g_fuseReplyErr);
767 CleanMockConditions();
768
769 // truncate fail
770 std::shared_ptr<DlpFile> dlpFile = std::make_shared<DlpFile>(-1, DLP_TEST_DIR, 0, false);
771 ASSERT_NE(dlpFile, nullptr);
772 DlpLinkFile linkfile("test", dlpFile);
773 fuse_ino_t ino = static_cast<fuse_ino_t>(reinterpret_cast<uintptr_t>(&linkfile));
774
775 condition.mockSequence = { true };
776 SetMockConditions("fuse_reply_err", condition);
777 SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
778 g_fuseReplyErr = 0;
779 attr.st_size = 0;
780 FuseDaemon::fuseDaemonOper_.setattr(req, ino, &attr, FUSE_SET_ATTR_SIZE, nullptr);
781 EXPECT_EQ(EINVAL, g_fuseReplyErr);
782 CleanMockConditions();
783 }
784
785 /**
786 * @tc.name: FuseDaemonSetAttr002
787 * @tc.desc: test fuse set attr callback abnormal test
788 * @tc.type: FUNC
789 * @tc.require:AR000GVIGC
790 */
791 HWTEST_F(FuseDaemonTest, FuseDaemonSetAttr002, TestSize.Level1)
792 {
793 DLP_LOG_INFO(LABEL, "FuseDaemonSetAttr002");
794 fuse_req_t req = nullptr;
795
796 // attr = nullptr
797 DlpCMockCondition condition;
798
799 std::shared_ptr<DlpFile> dlpFile = std::make_shared<DlpFile>(-1, DLP_TEST_DIR, 0, false);
800 ASSERT_NE(dlpFile, nullptr);
801 DlpLinkFile linkfile("test", dlpFile);
802 fuse_ino_t ino = static_cast<fuse_ino_t>(reinterpret_cast<uintptr_t>(&linkfile));
803 struct stat attr;
804 g_fuseReplyErr = 0;
805
806 condition.mockSequence = { true };
807 SetMockConditions("fuse_reply_err", condition);
808 SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
809 attr.st_size = DLP_MAX_CONTENT_SIZE + 1;
810 FuseDaemon::fuseDaemonOper_.setattr(req, ino, &attr, FUSE_SET_ATTR_SIZE, nullptr);
811 EXPECT_EQ(EINVAL, g_fuseReplyErr);
812 CleanMockConditions();
813
814 condition.mockSequence = { true };
815 SetMockConditions("fuse_reply_err", condition);
816 SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
817 attr.st_size = -1;
818 FuseDaemon::fuseDaemonOper_.setattr(req, ino, &attr, FUSE_SET_ATTR_SIZE, nullptr);
819 EXPECT_EQ(EINVAL, g_fuseReplyErr);
820 CleanMockConditions();
821 }
822
823 /**
824 * @tc.name: InitFuseFs001
825 * @tc.desc: test fuse daemon init
826 * @tc.type: FUNC
827 * @tc.require:AR000GVIGC
828 */
829 HWTEST_F(FuseDaemonTest, InitFuseFs001, TestSize.Level1)
830 {
831 DLP_LOG_INFO(LABEL, "InitFuseFs001");
832 FuseDaemon::init_ = false;
833 EXPECT_EQ(DLP_PARSE_ERROR_FD_ERROR, FuseDaemon::InitFuseFs());
834 // second init will fail whatever last init result is.
835 EXPECT_EQ(DLP_PARSE_ERROR_FD_ERROR, FuseDaemon::InitFuseFs());
836
837 // fuse fd is wrong
838 FuseDaemon::init_ = false;
839 EXPECT_EQ(DLP_PARSE_ERROR_FD_ERROR, FuseDaemon::InitFuseFs());
840 }
841
842 /**
843 * @tc.name: FuseFsDaemonThread001
844 * @tc.desc: test fuse daemon thread abnormal
845 * @tc.type: FUNC
846 * @tc.require:AR000GVIGC
847 */
848 HWTEST_F(FuseDaemonTest, FuseFsDaemonThread001, TestSize.Level1)
849 {
850 DLP_LOG_INFO(LABEL, "FuseFsDaemonThread001");
851
852 DlpCMockCondition condition;
853 condition.mockSequence = { true };
854 SetMockConditions("fuse_opt_add_arg", condition);
855 DlpCMockCondition condition1;
856 condition1.mockSequence = { true };
857 SetMockConditions("fuse_session_new", condition1);
858 DlpCMockCondition condition2;
859 condition2.mockSequence = { true };
860 SetMockConditions("fuse_opt_free_args", condition2);
861 FuseDaemon::FuseFsDaemonThread(1);
862 EXPECT_EQ(DLP_FUSE_ERROR_OPERATE_FAIL, FuseDaemon::WaitDaemonEnable());
863 CleanMockConditions();
864 }
865
866 /**
867 * @tc.name: FuseFsDaemonThread002
868 * @tc.desc: test fuse daemon thread abnormal
869 * @tc.type: FUNC
870 * @tc.require:AR000GVIGC
871 */
872 HWTEST_F(FuseDaemonTest, FuseFsDaemonThread002, TestSize.Level1)
873 {
874 DLP_LOG_INFO(LABEL, "FuseFsDaemonThread002");
875
876 DlpCMockCondition condition;
877 condition.mockSequence = { true };
878 SetMockConditions("fuse_opt_add_arg", condition);
879 DlpCMockCondition condition1;
880 condition1.mockSequence = { true };
881 SetMockConditions("fuse_session_new", condition1);
882 SetMockCallback("fuse_session_new", reinterpret_cast<CommonMockFuncT>(FuseSessionNewMock));
883 DlpCMockCondition condition2;
884 condition2.mockSequence = { true };
885 SetMockConditions("fuse_session_mount", condition2);
886 DlpCMockCondition condition3;
887 condition3.mockSequence = { true };
888 SetMockConditions("fuse_session_destroy", condition3);
889 DlpCMockCondition condition4;
890 condition4.mockSequence = { true };
891 SetMockConditions("fuse_opt_free_args", condition4);
892
893 FuseDaemon::FuseFsDaemonThread(1);
894 EXPECT_EQ(DLP_FUSE_ERROR_OPERATE_FAIL, FuseDaemon::WaitDaemonEnable());
895 CleanMockConditions();
896 }
897
898 /**
899 * @tc.name: FuseFsDaemonThread003
900 * @tc.desc: test fuse daemon thread abnormal
901 * @tc.type: FUNC
902 * @tc.require:AR000GVIGC
903 */
904 HWTEST_F(FuseDaemonTest, FuseFsDaemonThread003, TestSize.Level1)
905 {
906 DLP_LOG_INFO(LABEL, "FuseFsDaemonThread003");
907
908 DlpCMockCondition condition;
909 condition.mockSequence = { true };
910 SetMockConditions("fuse_opt_add_arg", condition);
911 DlpCMockCondition condition1;
912 condition1.mockSequence = { true };
913 SetMockConditions("fuse_session_new", condition1);
914 SetMockCallback("fuse_session_new", reinterpret_cast<CommonMockFuncT>(FuseSessionNewMock));
915 DlpCMockCondition condition2;
916 condition2.mockSequence = { true };
917 SetMockConditions("fuse_session_mount", condition2);
918 SetMockCallback("fuse_session_mount", reinterpret_cast<CommonMockFuncT>(FuseSessionMountMock));
919 DlpCMockCondition condition3;
920 condition3.mockSequence = { true };
921 SetMockConditions("fuse_session_destroy", condition3);
922 DlpCMockCondition condition4;
923 condition4.mockSequence = { true };
924 SetMockConditions("fuse_opt_free_args", condition4);
925 DlpCMockCondition condition5;
926 condition5.mockSequence = { true };
927 SetMockConditions("fuse_session_loop", condition5);
928
929 FuseDaemon::FuseFsDaemonThread(1);
930 EXPECT_EQ(0, FuseDaemon::WaitDaemonEnable());
931 CleanMockConditions();
932 }
933
934 /**
935 * @tc.name: FuseDaemonInit001
936 * @tc.desc: FuseDaemonInit
937 * @tc.type: FUNC
938 * @tc.require:AR000GVIGC
939 */
940 HWTEST_F(FuseDaemonTest, FuseDaemonInit001, TestSize.Level1)
941 {
942 DLP_LOG_INFO(LABEL, "FuseDaemonInit001");
943
944 FuseDaemon::fuseDaemonOper_.init(nullptr, nullptr);
945
946 fuse_conn_info conn = { 0 };
947 FuseDaemon::fuseDaemonOper_.init(nullptr, &conn);
948 EXPECT_EQ(FUSE_CAP_WRITEBACK_CACHE, conn.want);
949 }
950 } // namespace DlpPermission
951 } // namespace Security
952 } // namespace OHOS