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