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