1 /*
2 * Copyright (c) 2023-2024 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
16 #include "fuse_daemon.h"
17
18 #include <pthread.h>
19 #include <securec.h>
20 #include <sys/stat.h>
21 #include <sys/types.h>
22 #include <unistd.h>
23 #include <vector>
24 #include "dlp_fuse_fd.h"
25 #include "dlp_fuse_helper.h"
26 #include "dlp_fuse_utils.h"
27 #include "dlp_link_file.h"
28 #include "dlp_permission.h"
29 #include "dlp_permission_log.h"
30
31 namespace OHOS {
32 namespace Security {
33 namespace DlpPermission {
34 namespace {
35 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_DLP_PERMISSION, "FuseDaemon"};
36 static constexpr int ROOT_INODE = 1;
37 static constexpr int DEFAULT_ATTR_TIMEOUT = 10000;
38 static constexpr int MAX_FILE_NAME_LEN = 256;
39 static constexpr int ROOT_INODE_ACCESS = 0711;
40 static constexpr uint32_t MAX_READ_DIR_BUF_SIZE = 100 * 1024; // 100K
41 static constexpr const char* CUR_DIR = ".";
42 static constexpr const char* UPPER_DIR = "..";
43 static constexpr const char* THREAD_OS_DLP_FUSE = "OS_DLP_FUSE";
44 } // namespace
45
46 std::condition_variable FuseDaemon::daemonEnableCv_;
47 enum DaemonStatus FuseDaemon::daemonStatus_;
48 std::mutex FuseDaemon::daemonEnableMtx_;
49 struct stat FuseDaemon::rootFileStat_;
50 bool FuseDaemon::init_ = false;
51 std::mutex FuseDaemon::initMutex_;
52
53 // caller need to check ino == ROOT_INODE
GetFileNode(fuse_ino_t ino)54 static DlpLinkFile* GetFileNode(fuse_ino_t ino)
55 {
56 return reinterpret_cast<DlpLinkFile*>(static_cast<uintptr_t>(ino));
57 }
58
GetFileInode(DlpLinkFile * node)59 fuse_ino_t GetFileInode(DlpLinkFile* node)
60 {
61 return static_cast<fuse_ino_t>(reinterpret_cast<uintptr_t>(node));
62 }
63
FuseDaemonLookup(fuse_req_t req,fuse_ino_t parent,const char * name)64 static void FuseDaemonLookup(fuse_req_t req, fuse_ino_t parent, const char* name)
65 {
66 if (name == nullptr) {
67 DLP_LOG_ERROR(LABEL, "Look up link file fail, name is null");
68 fuse_reply_err(req, ENOENT);
69 return;
70 }
71 DLP_LOG_DEBUG(LABEL, "Look up link file, name=%{private}s", name);
72
73 if (parent != ROOT_INODE) {
74 DLP_LOG_ERROR(LABEL, "Look up link file fail, parent is not root inode");
75 fuse_reply_err(req, ENOENT);
76 return;
77 }
78
79 struct fuse_entry_param fep;
80 (void)memset_s(&fep, sizeof(struct fuse_entry_param), 0, sizeof(struct fuse_entry_param));
81 if (!strcmp(name, ".") || !strcmp(name, "..")) {
82 fep.ino = ROOT_INODE;
83 fep.attr = *(FuseDaemon::GetRootFileStat());
84 fuse_reply_entry(req, &fep);
85 return;
86 }
87
88 DlpLinkManager* manager = DlpFuseHelper::GetDlpLinkManagerInstance();
89 if (!manager) {
90 DLP_LOG_ERROR(LABEL, "Get instance failed.");
91 fuse_reply_err(req, ENOENT);
92 return;
93 }
94
95 std::string nameStr = name;
96 DlpLinkFile* node = manager->LookUpDlpLinkFile(nameStr);
97 if (node == nullptr) {
98 DLP_LOG_ERROR(LABEL, "Look up link file fail, file %{public}s can not found", name);
99 fuse_reply_err(req, ENOENT);
100 } else {
101 DLP_LOG_DEBUG(LABEL, "Look up link file succ, file %{public}s found", name);
102 fep.ino = GetFileInode(node);
103 fep.attr = node->GetLinkStat();
104 fuse_reply_entry(req, &fep);
105 }
106 }
107
FuseDaemonGetattr(fuse_req_t req,fuse_ino_t ino,struct fuse_file_info * fi)108 static void FuseDaemonGetattr(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi)
109 {
110 (void)fi;
111
112 if (ino == ROOT_INODE) {
113 struct stat* fileStat = FuseDaemon::GetRootFileStat();
114 fuse_reply_attr(req, fileStat, DEFAULT_ATTR_TIMEOUT);
115 return;
116 }
117
118 DlpLinkFile* dlp = GetFileNode(ino);
119 if (dlp == nullptr) {
120 DLP_LOG_ERROR(LABEL, "Get link file attr fail, wrong ino");
121 fuse_reply_err(req, ENOENT);
122 return;
123 }
124
125 struct stat fileStat = dlp->GetLinkStat();
126 fuse_reply_attr(req, &fileStat, DEFAULT_ATTR_TIMEOUT);
127 }
128
129 // we will handle open flag later
FuseDaemonOpen(fuse_req_t req,fuse_ino_t ino,struct fuse_file_info * fi)130 static void FuseDaemonOpen(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi)
131 {
132 if (ino == ROOT_INODE) {
133 DLP_LOG_ERROR(LABEL, "Open link file fail, can not open root dir");
134 fuse_reply_err(req, ENOENT);
135 return;
136 }
137
138 DlpLinkFile* dlp = GetFileNode(ino);
139 if (dlp == nullptr) {
140 DLP_LOG_ERROR(LABEL, "Open link file fail, wrong ino");
141 fuse_reply_err(req, ENOENT);
142 return;
143 }
144 if ((fi != nullptr) && (static_cast<uint32_t>(fi->flags) & O_TRUNC) != 0) {
145 int32_t ret = dlp->Truncate(0);
146 if (ret != DLP_OK) {
147 DLP_LOG_ERROR(LABEL, "Open link file with truncate fail, ret=%{public}d", ret);
148 fuse_reply_err(req, EINVAL);
149 return;
150 }
151 DLP_LOG_INFO(LABEL, "Open link file with truncate succ");
152 }
153
154 fuse_reply_open(req, fi);
155 dlp->UpdateAtimeStat();
156 }
157
GetValidFileNode(fuse_req_t req,fuse_ino_t ino)158 static DlpLinkFile* GetValidFileNode(fuse_req_t req, fuse_ino_t ino)
159 {
160 if (ino == ROOT_INODE) {
161 fuse_reply_err(req, ENOENT);
162 return nullptr;
163 }
164 DlpLinkFile* dlp = GetFileNode(ino);
165 if (dlp == nullptr) {
166 fuse_reply_err(req, EBADF);
167 return nullptr;
168 }
169 return dlp;
170 }
171
FuseDaemonRead(fuse_req_t req,fuse_ino_t ino,size_t size,off_t offset,struct fuse_file_info * fi)172 static void FuseDaemonRead(fuse_req_t req, fuse_ino_t ino, size_t size, off_t offset, struct fuse_file_info* fi)
173 {
174 (void)fi;
175 if (req == nullptr) {
176 DLP_LOG_ERROR(LABEL, "Fuse_req_t is nullptr");
177 fuse_reply_err(req, EINVAL);
178 return;
179 }
180 if (offset < 0 || offset > static_cast<off_t>(DLP_MAX_CONTENT_SIZE)) {
181 fuse_reply_err(req, EINVAL);
182 return;
183 }
184 if (size > DLP_FUSE_MAX_BUFFLEN) {
185 DLP_LOG_ERROR(LABEL, "Read link file fail, read size %{public}zu too large", size);
186 fuse_reply_err(req, EINVAL);
187 return;
188 }
189 DlpLinkFile* dlp = GetValidFileNode(req, ino);
190 if (dlp == nullptr) {
191 DLP_LOG_ERROR(LABEL, "Read link file fail, wrong ino");
192 return;
193 }
194
195 char* buf = reinterpret_cast<char*>(malloc(size));
196 if (buf == nullptr) {
197 DLP_LOG_ERROR(LABEL, "Read link file fail, malloc %{public}zu buff fail", size);
198 fuse_reply_err(req, EINVAL);
199 return;
200 }
201 (void)memset_s(buf, size, 0, size);
202 int32_t res = dlp->Read(static_cast<uint32_t>(offset), buf, static_cast<uint32_t>(size), req->ctx.uid);
203 if (res < 0) {
204 fuse_reply_err(req, EIO);
205 } else {
206 fuse_reply_buf(req, buf, static_cast<size_t>(res));
207 }
208 DLP_LOG_DEBUG(LABEL, "Read file name %{private}s offset %{public}u size %{public}u res %{public}d",
209 dlp->GetLinkName().c_str(), static_cast<uint32_t>(offset), static_cast<uint32_t>(size), res);
210 free(buf);
211 }
212
FuseDaemonWrite(fuse_req_t req,fuse_ino_t ino,const char * buf,size_t size,off_t off,struct fuse_file_info * fi)213 static void FuseDaemonWrite(
214 fuse_req_t req, fuse_ino_t ino, const char* buf, size_t size, off_t off, struct fuse_file_info* fi)
215 {
216 (void)fi;
217 if (off < 0 || off > static_cast<off_t>(DLP_MAX_CONTENT_SIZE)) {
218 fuse_reply_err(req, EINVAL);
219 return;
220 }
221 if (size > DLP_FUSE_MAX_BUFFLEN) {
222 DLP_LOG_ERROR(LABEL, "Write link file fail, write size %{public}zu too large", size);
223 fuse_reply_err(req, EINVAL);
224 return;
225 }
226 DlpLinkFile* dlp = GetValidFileNode(req, ino);
227 if (dlp == nullptr) {
228 DLP_LOG_ERROR(LABEL, "Write link file fail, wrong ino");
229 return;
230 }
231 int32_t res = dlp->Write(static_cast<uint32_t>(off),
232 const_cast<void *>(static_cast<const void *>(buf)), static_cast<uint32_t>(size));
233 if (res < 0) {
234 fuse_reply_err(req, EIO);
235 } else {
236 fuse_reply_write(req, static_cast<size_t>(res));
237 }
238 DLP_LOG_DEBUG(LABEL, "Write file name %{private}s offset %{public}u size %{public}u res %{public}d",
239 dlp->GetLinkName().c_str(), static_cast<uint32_t>(off), static_cast<uint32_t>(size), res);
240 }
241
FuseDaemonForget(fuse_req_t req,fuse_ino_t ino,uint64_t nlookup)242 static void FuseDaemonForget(fuse_req_t req, fuse_ino_t ino, uint64_t nlookup)
243 {
244 if (ino == ROOT_INODE) {
245 DLP_LOG_WARN(LABEL, "Forget root dir is forbidden");
246 fuse_reply_err(req, ENOENT);
247 return;
248 }
249
250 DlpLinkFile* dlp = GetFileNode(ino);
251 if (dlp == nullptr) {
252 DLP_LOG_ERROR(LABEL, "Forgot link file fail, wrong ino");
253 fuse_reply_err(req, EBADF);
254 return;
255 }
256 DLP_LOG_DEBUG(LABEL, "Forget link file name %{private}s nlookup %{public}u",
257 dlp->GetLinkName().c_str(), static_cast<uint32_t>(nlookup));
258 if (dlp->SubAndCheckZeroRef(nlookup)) {
259 DLP_LOG_INFO(LABEL, "Link file reference is less than 0, delete link file ok");
260 delete dlp;
261 }
262 }
263
AddDirentry(DirAddParams & param)264 static int AddDirentry(DirAddParams& param)
265 {
266 size_t shouldSize = fuse_add_direntry(param.req, nullptr, 0, param.entryName.c_str(), nullptr, 0);
267 if (shouldSize > param.bufLen) {
268 return DLP_FUSE_ERROR_VALUE_INVALID;
269 }
270 param.curOff = param.nextOff;
271 size_t addSize = fuse_add_direntry(param.req, param.directBuf, param.bufLen,
272 param.entryName.c_str(), param.entryStat, param.curOff);
273 param.directBuf += addSize;
274 param.bufLen -= addSize;
275 param.nextOff += static_cast<int>(addSize);
276 return DLP_OK;
277 }
278
AddRootDirentry(DirAddParams & params)279 static int AddRootDirentry(DirAddParams& params)
280 {
281 struct stat* rootStat = FuseDaemon::GetRootFileStat();
282 params.entryName = CUR_DIR;
283 params.entryStat = rootStat;
284
285 if (AddDirentry(params) != DLP_OK) {
286 fuse_reply_err(params.req, EINVAL);
287 return DLP_FUSE_ERROR_VALUE_INVALID;
288 }
289
290 params.entryName = UPPER_DIR;
291 if (AddDirentry(params) != DLP_OK) {
292 fuse_reply_err(params.req, EINVAL);
293 return DLP_FUSE_ERROR_VALUE_INVALID;
294 }
295 return DLP_OK;
296 }
297
AddLinkFilesDirentry(DirAddParams & params)298 static int AddLinkFilesDirentry(DirAddParams& params)
299 {
300 std::vector<DlpLinkFileInfo> linkList;
301 DlpLinkManager* manager = DlpFuseHelper::GetDlpLinkManagerInstance();
302 if (!manager) {
303 fuse_reply_err(params.req, EINVAL);
304 return DLP_FUSE_ERROR_VALUE_INVALID;
305 }
306 manager->DumpDlpLinkFile(linkList);
307 int listSize = static_cast<int>(linkList.size());
308 for (int i = 0; i < listSize; i++) {
309 params.entryName = linkList[i].dlpLinkName;
310 params.entryStat = &linkList[i].fileStat;
311 if (AddDirentry(params) != DLP_OK) {
312 fuse_reply_err(params.req, EINVAL);
313 return DLP_FUSE_ERROR_VALUE_INVALID;
314 }
315 }
316 return DLP_OK;
317 }
318
FuseDaemonReadDir(fuse_req_t req,fuse_ino_t ino,size_t size,off_t off,struct fuse_file_info * fi)319 static void FuseDaemonReadDir(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi)
320 {
321 (void)fi;
322 if (off < 0 || off > static_cast<off_t>(DLP_MAX_CONTENT_SIZE)) {
323 fuse_reply_err(req, ENOTDIR);
324 return;
325 }
326
327 if (ino != ROOT_INODE) {
328 fuse_reply_err(req, ENOTDIR);
329 return;
330 }
331 if (size > MAX_READ_DIR_BUF_SIZE) {
332 fuse_reply_err(req, EINVAL);
333 return;
334 }
335
336 char* readBuf = reinterpret_cast<char*>(malloc(size));
337 if (readBuf == nullptr) {
338 fuse_reply_err(req, EFAULT);
339 return;
340 }
341 (void)memset_s(readBuf, size, 0, size);
342
343 struct DirAddParams params;
344 params.req = req;
345 params.directBuf = readBuf;
346 params.bufLen = size;
347 params.nextOff = 0;
348
349 if (AddRootDirentry(params) != DLP_OK) {
350 free(readBuf);
351 return;
352 }
353
354 if (AddLinkFilesDirentry(params) != DLP_OK) {
355 free(readBuf);
356 return;
357 }
358
359 if (params.curOff <= off) {
360 fuse_reply_buf(req, nullptr, 0);
361 } else {
362 fuse_reply_buf(req, readBuf + off, params.nextOff - off);
363 }
364 free(readBuf);
365 }
366
FuseDaemonUpdateTime(fuse_req_t req,int toSet,DlpLinkFile * dlpLink)367 bool FuseDaemonUpdateTime(fuse_req_t req, int toSet, DlpLinkFile* dlpLink)
368 {
369 DLP_LOG_DEBUG(LABEL, "Set link file update time, type %{public}d", toSet);
370 bool isUpdateTime = false;
371 struct stat fileStat = dlpLink->GetFileStat();
372 if ((static_cast<uint32_t>(toSet) & FUSE_SET_ATTR_MTIME) != 0) {
373 DlpFuseUtils::UpdateCurrTimeStat(&fileStat.st_mtim);
374 isUpdateTime = true;
375 }
376 if ((static_cast<uint32_t>(toSet) & FUSE_SET_ATTR_CTIME) != 0) {
377 DlpFuseUtils::UpdateCurrTimeStat(&fileStat.st_ctim);
378 isUpdateTime = true;
379 }
380 if ((static_cast<uint32_t>(toSet) & FUSE_SET_ATTR_ATIME) != 0) {
381 DlpFuseUtils::UpdateCurrTimeStat(&fileStat.st_atim);
382 isUpdateTime = true;
383 }
384 if (isUpdateTime && (static_cast<uint32_t>(toSet) & FUSE_SET_ATTR_SIZE) == 0) {
385 fuse_reply_attr(req, &fileStat, DEFAULT_ATTR_TIMEOUT);
386 return false;
387 }
388 return true;
389 }
390
FuseDaemonSetAttr(fuse_req_t req,fuse_ino_t ino,struct stat * attr,int toSet,struct fuse_file_info * fi)391 void FuseDaemonSetAttr(fuse_req_t req, fuse_ino_t ino, struct stat *attr, int toSet, struct fuse_file_info *fi)
392 {
393 (void)fi;
394 if (attr == nullptr) {
395 DLP_LOG_ERROR(LABEL, "Set link file attr fail, attr invalid");
396 fuse_reply_err(req, EINVAL);
397 return;
398 }
399
400 if (ino == ROOT_INODE) {
401 DLP_LOG_ERROR(LABEL, "Set link file attr fail, cannot set attr on root inode");
402 fuse_reply_err(req, EACCES);
403 return;
404 }
405
406 DlpLinkFile* dlpLink = GetFileNode(ino);
407 if (dlpLink == nullptr) {
408 DLP_LOG_ERROR(LABEL, "Set link file attr fail, wrong ino");
409 fuse_reply_err(req, ENOENT);
410 return;
411 }
412
413 if (!FuseDaemonUpdateTime(req, toSet, dlpLink)) {
414 return;
415 }
416
417 if ((static_cast<uint32_t>(toSet) & FUSE_SET_ATTR_SIZE) == 0) {
418 DLP_LOG_ERROR(LABEL, "Set link file attr fail, type %{public}d not support", toSet);
419 fuse_reply_err(req, EACCES);
420 return;
421 }
422
423 if (attr->st_size < 0 || attr->st_size > static_cast<off_t>(DLP_MAX_CONTENT_SIZE)) {
424 DLP_LOG_ERROR(LABEL, "Set link file attr fail, file size too large");
425 fuse_reply_err(req, EINVAL);
426 return;
427 }
428 int32_t ret = dlpLink->Truncate(static_cast<uint32_t>(attr->st_size));
429 if (ret != DLP_OK) {
430 DLP_LOG_ERROR(LABEL, "Set link file attr fail, errno is %{public}d", ret);
431 fuse_reply_err(req, EINVAL);
432 return;
433 }
434
435 DLP_LOG_INFO(LABEL, "Set link file attr succ");
436 struct stat fileStat = dlpLink->GetLinkStat();
437 fuse_reply_attr(req, &fileStat, DEFAULT_ATTR_TIMEOUT);
438 }
439
FuseDaemonInit(void * userdata,struct fuse_conn_info * conn)440 static void FuseDaemonInit(void *userdata, struct fuse_conn_info *conn)
441 {
442 (void)userdata;
443 if (conn == nullptr) {
444 DLP_LOG_ERROR(LABEL, "Fuse init, fuse conn info is null");
445 return;
446 }
447 conn->want |= FUSE_CAP_WRITEBACK_CACHE;
448 }
449
450 struct fuse_lowlevel_ops FuseDaemon::fuseDaemonOper_ = {
451 .init = FuseDaemonInit,
452 .lookup = FuseDaemonLookup,
453 .forget = FuseDaemonForget,
454 .getattr = FuseDaemonGetattr,
455 .setattr = FuseDaemonSetAttr,
456 .open = FuseDaemonOpen,
457 .read = FuseDaemonRead,
458 .write = FuseDaemonWrite,
459 .readdir = FuseDaemonReadDir,
460 };
461
GetRootFileStat()462 struct stat* FuseDaemon::GetRootFileStat()
463 {
464 return &FuseDaemon::rootFileStat_;
465 }
466
InitRootFileStat(void)467 void FuseDaemon::InitRootFileStat(void)
468 {
469 (void)memset_s(&rootFileStat_, sizeof(rootFileStat_), 0, sizeof(rootFileStat_));
470 rootFileStat_.st_ino = ROOT_INODE;
471 rootFileStat_.st_mode = S_IFDIR | ROOT_INODE_ACCESS;
472 rootFileStat_.st_nlink = 1;
473 rootFileStat_.st_uid = getuid();
474 rootFileStat_.st_gid = getgid();
475 DlpFuseUtils::UpdateCurrTimeStat(&rootFileStat_.st_atim);
476 DlpFuseUtils::UpdateCurrTimeStat(&rootFileStat_.st_mtim);
477 DlpFuseUtils::UpdateCurrTimeStat(&rootFileStat_.st_ctim);
478 }
479
NotifyDaemonEnable(void)480 void FuseDaemon::NotifyDaemonEnable(void)
481 {
482 std::unique_lock<std::mutex> lck(daemonEnableMtx_);
483 daemonStatus_ = DAEMON_ENABLE;
484 daemonEnableCv_.notify_all();
485 }
486
NotifyDaemonDisable(void)487 void FuseDaemon::NotifyDaemonDisable(void)
488 {
489 std::unique_lock<std::mutex> lck(daemonEnableMtx_);
490 daemonStatus_ = DAEMON_DISABLE;
491 daemonEnableCv_.notify_all();
492 }
493
WaitDaemonEnable(void)494 int FuseDaemon::WaitDaemonEnable(void)
495 {
496 DLP_LOG_INFO(LABEL, "Wait fuse fs daemon enable");
497 std::unique_lock<std::mutex> lck(daemonEnableMtx_);
498 if (daemonStatus_ == DAEMON_UNDEF) {
499 daemonEnableCv_.wait_for(lck, std::chrono::seconds(1));
500 }
501
502 if (daemonStatus_ == DAEMON_ENABLE) {
503 DLP_LOG_INFO(LABEL, "Wait fuse fs daemon enable succ");
504 init_ = true;
505 return DLP_OK;
506 }
507
508 DLP_LOG_INFO(LABEL, "Wait fuse fs daemon enable fail, time out");
509 return DLP_FUSE_ERROR_OPERATE_FAIL;
510 }
511
FuseFsDaemonThread(int fuseFd)512 void FuseDaemon::FuseFsDaemonThread(int fuseFd)
513 {
514 struct stat fileStat;
515 if (fstat(fuseFd, &fileStat) < 0) {
516 DLP_LOG_ERROR(LABEL, "Fuse fs daemon exit, %{public}d is wrong fd, errno %{public}d", fuseFd, errno);
517 NotifyDaemonDisable();
518 return;
519 }
520
521 char mountPoint[MAX_FILE_NAME_LEN] = {0};
522 int ret = snprintf_s(mountPoint, sizeof(mountPoint), MAX_FILE_NAME_LEN, "/dev/fd/%d", fuseFd);
523 if (ret <= 0) {
524 DLP_LOG_ERROR(LABEL, "Fuse fs daemon exit, snprintf_s fail");
525 NotifyDaemonDisable();
526 return;
527 }
528
529 struct fuse_args args = FUSE_ARGS_INIT(0, nullptr);
530 fuse_opt_add_arg(&args, mountPoint);
531
532 struct fuse_session* se = fuse_session_new(&args, &fuseDaemonOper_, sizeof(fuseDaemonOper_), nullptr);
533 if (se == nullptr) {
534 DLP_LOG_ERROR(LABEL, "Fuse fs daemon exit, create fuse session fail");
535 NotifyDaemonDisable();
536 fuse_opt_free_args(&args);
537 return;
538 }
539
540 if (fuse_session_mount(se, mountPoint) != 0) {
541 DLP_LOG_ERROR(LABEL, "Fuse fs daemon exit, mount fuse session fail");
542 NotifyDaemonDisable();
543 fuse_session_destroy(se);
544 fuse_opt_free_args(&args);
545 return;
546 }
547
548 InitRootFileStat();
549 NotifyDaemonEnable();
550
551 if (fuse_session_loop(se) != 0) {
552 DLP_LOG_ERROR(LABEL, "Fuse fs daemon exit, fuse session loop end");
553 }
554
555 fuse_session_destroy(se);
556 fuse_opt_free_args(&args);
557 }
558
InitFuseFs()559 int FuseDaemon::InitFuseFs()
560 {
561 if (init_) {
562 DLP_LOG_INFO(LABEL, "Fuse fs has init already!");
563 return DLP_OK;
564 }
565
566 std::lock_guard<std::mutex> lock(initMutex_);
567 if (init_) {
568 DLP_LOG_INFO(LABEL, "Double check fuse fs has init already!");
569 return DLP_OK;
570 }
571
572 int fuseDevFd = GetDlpFuseFd();
573 if (fuseDevFd < 0) {
574 DLP_LOG_ERROR(LABEL, "Init fuse fs fail: dev fd is error");
575 return DLP_PARSE_ERROR_FD_ERROR;
576 }
577 daemonStatus_ = DAEMON_UNDEF;
578
579 std::thread daemonThread([fuseDevFd] { FuseFsDaemonThread(fuseDevFd); });
580 pthread_setname_np(daemonThread.native_handle(), THREAD_OS_DLP_FUSE);
581 daemonThread.detach();
582 return WaitDaemonEnable();
583 }
584 } // namespace DlpPermission
585 } // namespace Security
586 } // namespace OHOS
587