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 "dlp_link_file.h"
17
18 #include <securec.h>
19 #include "dlp_fuse_utils.h"
20 #include "dlp_permission.h"
21 #include "dlp_permission_log.h"
22 #include "fuse_daemon.h"
23
24 namespace OHOS {
25 namespace Security {
26 namespace DlpPermission {
27 namespace {
28 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_DLP_PERMISSION, "DlpLinkFile"};
29 static const int DEFAULT_INODE_RO_ACCESS = 0440;
30 static const int DEFAULT_INODE_RW_ACCESS = 0640;
31 } // namespace
32
DlpLinkFile(const std::string & dlpLinkName,const std::shared_ptr<DlpFile> & dlpFile)33 DlpLinkFile::DlpLinkFile(const std::string& dlpLinkName, const std::shared_ptr<DlpFile>& dlpFile)
34 : dlpLinkName_(dlpLinkName), dlpFile_(dlpFile), refcount_(1), stopLinkFlag_(false), hasRead_(false)
35 {
36 (void)memset_s(&fileStat_, sizeof(fileStat_), 0, sizeof(fileStat_));
37 fileStat_.st_ino = static_cast<fuse_ino_t>(reinterpret_cast<uintptr_t>(this));
38 if (dlpFile != nullptr) {
39 uint32_t fileMode =
40 (dlpFile->GetAuthPerm() == DLPFileAccess::READ_ONLY) ? DEFAULT_INODE_RO_ACCESS : DEFAULT_INODE_RW_ACCESS;
41 fileStat_.st_mode = S_IFREG | fileMode;
42 } else {
43 fileStat_.st_mode = 0;
44 }
45 fileStat_.st_nlink = 1;
46 fileStat_.st_uid = getuid();
47 fileStat_.st_gid = getgid();
48
49 DlpFuseUtils::UpdateCurrTimeStat(&fileStat_.st_atim);
50 DlpFuseUtils::UpdateCurrTimeStat(&fileStat_.st_mtim);
51 DlpFuseUtils::UpdateCurrTimeStat(&fileStat_.st_ctim);
52 }
53
~DlpLinkFile()54 DlpLinkFile::~DlpLinkFile()
55 {
56 }
57
SubAndCheckZeroRef(int ref)58 bool DlpLinkFile::SubAndCheckZeroRef(int ref)
59 {
60 if (ref <= 0) {
61 DLP_LOG_WARN(LABEL, "Need sub reference %{public}d is error", ref);
62 return false;
63 }
64 std::lock_guard<std::mutex> lock(refLock_);
65 if (refcount_ < ref) {
66 DLP_LOG_WARN(LABEL, "Need sub reference %{public}d is larger than refcount %{public}d",
67 ref, static_cast<int>(refcount_));
68 return true;
69 }
70 refcount_ -= ref;
71 return (refcount_ <= 0);
72 }
73
IncreaseRef()74 void DlpLinkFile::IncreaseRef()
75 {
76 std::lock_guard<std::mutex> lock(refLock_);
77 if (refcount_ <= 0) {
78 DLP_LOG_WARN(LABEL, "refcount <= 0, can not increase");
79 return;
80 }
81 refcount_++;
82 }
83
GetLinkStat()84 struct stat DlpLinkFile::GetLinkStat()
85 {
86 if (dlpFile_ == nullptr) {
87 DLP_LOG_ERROR(LABEL, "Get link file stat fail, dlpFile is null");
88 return fileStat_;
89 }
90
91 uint64_t res = dlpFile_->GetFsContentSize();
92 if (res != INVALID_FILE_SIZE) {
93 fileStat_.st_size = static_cast<off_t>(res);
94 }
95 return fileStat_;
96 }
97
Truncate(uint64_t modifySize)98 int32_t DlpLinkFile::Truncate(uint64_t modifySize)
99 {
100 if (stopLinkFlag_) {
101 DLP_LOG_INFO(LABEL, "linkFile is stopping link");
102 return DLP_LINK_FILE_NOT_ALLOW_OPERATE;
103 }
104
105 if (modifySize >= DLP_MAX_CONTENT_SIZE) {
106 DLP_LOG_ERROR(LABEL, "Truncate fail, modify size %{public}s is invalid", std::to_string(modifySize).c_str());
107 return DLP_FUSE_ERROR_VALUE_INVALID;
108 }
109
110 if (dlpFile_ == nullptr) {
111 DLP_LOG_ERROR(LABEL, "Truncate link file fail, dlp file is null");
112 return DLP_FUSE_ERROR_DLP_FILE_NULL;
113 }
114 int32_t res = dlpFile_->Truncate(modifySize);
115 if (res < 0) {
116 DLP_LOG_ERROR(LABEL, "Truncate %{public}s file fail, res=%{public}d", std::to_string(modifySize).c_str(), res);
117 } else {
118 DLP_LOG_INFO(LABEL, "Truncate %{public}s in link file succ", std::to_string(modifySize).c_str());
119 }
120 UpdateMtimeStat();
121 return res;
122 }
123
UpdateAtimeStat()124 void DlpLinkFile::UpdateAtimeStat()
125 {
126 DlpFuseUtils::UpdateCurrTimeStat(&fileStat_.st_atim);
127 }
128
UpdateMtimeStat()129 void DlpLinkFile::UpdateMtimeStat()
130 {
131 DlpFuseUtils::UpdateCurrTimeStat(&fileStat_.st_mtim);
132 }
133
Write(uint64_t offset,void * buf,uint32_t size)134 int32_t DlpLinkFile::Write(uint64_t offset, void* buf, uint32_t size)
135 {
136 if (stopLinkFlag_) {
137 DLP_LOG_INFO(LABEL, "linkFile is stopping link");
138 return DLP_LINK_FILE_NOT_ALLOW_OPERATE;
139 }
140
141 if (dlpFile_ == nullptr) {
142 DLP_LOG_ERROR(LABEL, "Write link file fail, dlp file is null");
143 return DLP_FUSE_ERROR_DLP_FILE_NULL;
144 }
145 int32_t res = dlpFile_->DlpFileWrite(offset, buf, size);
146 if (res < 0) {
147 DLP_LOG_ERROR(LABEL, "Write link file fail, err=%{public}d.", res);
148 }
149 UpdateMtimeStat();
150 return res;
151 }
152
Read(uint64_t offset,void * buf,uint32_t size,uint32_t uid)153 int32_t DlpLinkFile::Read(uint64_t offset, void* buf, uint32_t size, uint32_t uid)
154 {
155 if (stopLinkFlag_) {
156 DLP_LOG_INFO(LABEL, "linkFile is stopping link");
157 return DLP_LINK_FILE_NOT_ALLOW_OPERATE;
158 }
159
160 if (dlpFile_ == nullptr) {
161 DLP_LOG_ERROR(LABEL, "Read link file fail, dlp file is null");
162 return DLP_FUSE_ERROR_DLP_FILE_NULL;
163 }
164 UpdateAtimeStat();
165 int32_t res = dlpFile_->DlpFileRead(offset, buf, size, hasRead_, uid);
166 if (res < 0) {
167 DLP_LOG_ERROR(LABEL, "Read link file failed, res %{public}d.", res);
168 }
169 return res;
170 }
171 } // namespace DlpPermission
172 } // namespace Security
173 } // namespace OHOS
174