• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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