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 #include "dlp_link_manager.h"
16
17 #include "dlp_file.h"
18 #include "dlp_fuse_fd.h"
19 #include "dlp_permission.h"
20 #include "dlp_permission_log.h"
21
22 namespace OHOS {
23 namespace Security {
24 namespace DlpPermission {
25 namespace {
26 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_DLP_PERMISSION, "DlpLinkManager"};
27 static const int MAX_FILE_NAME_LEN = 256;
28 static constexpr uint32_t MAX_DLP_LINK_SIZE = 1000; // max open link file
29 std::mutex g_instanceMutex;
30 }
31
DlpLinkManager()32 DlpLinkManager::DlpLinkManager()
33 {}
34
~DlpLinkManager()35 DlpLinkManager::~DlpLinkManager()
36 {
37 Utils::UniqueWriteGuard<Utils::RWLock> infoGuard(dlpLinkMapLock_);
38 for (auto iter = dlpLinkFileNameMap_.begin(); iter != dlpLinkFileNameMap_.end();) {
39 DlpLinkFile* tmp = iter->second;
40 if (tmp != nullptr) {
41 iter = dlpLinkFileNameMap_.erase(iter);
42 delete tmp;
43 } else {
44 iter++;
45 }
46 }
47 CloseDlpFuseFd();
48 }
49
IsLinkNameValid(const std::string & linkName)50 static bool IsLinkNameValid(const std::string& linkName)
51 {
52 size_t size = linkName.size();
53 return !(size == 0 || size > MAX_FILE_NAME_LEN);
54 }
55
AddDlpLinkFile(const std::shared_ptr<DlpFile> & filePtr,const std::string & dlpLinkName)56 int32_t DlpLinkManager::AddDlpLinkFile(const std::shared_ptr<DlpFile>& filePtr, const std::string& dlpLinkName)
57 {
58 if (filePtr == nullptr) {
59 DLP_LOG_ERROR(LABEL, "Add link file fail, dlp file is null");
60 return DLP_FUSE_ERROR_DLP_FILE_NULL;
61 }
62 if (!IsLinkNameValid(dlpLinkName)) {
63 DLP_LOG_ERROR(LABEL, "Add link file fail, link file name %{public}s invalid", dlpLinkName.c_str());
64 return DLP_FUSE_ERROR_VALUE_INVALID;
65 }
66
67 Utils::UniqueWriteGuard<Utils::RWLock> infoGuard(dlpLinkMapLock_);
68 if (dlpLinkFileNameMap_.size() >= MAX_DLP_LINK_SIZE) {
69 DLP_LOG_ERROR(LABEL, "Add link file fail, too many links");
70 return DLP_FUSE_ERROR_TOO_MANY_LINK_FILE;
71 }
72
73 auto iter = dlpLinkFileNameMap_.find(dlpLinkName);
74 if (iter != dlpLinkFileNameMap_.end()) {
75 DLP_LOG_ERROR(LABEL, "Add link file fail, link file %{public}s exist", dlpLinkName.c_str());
76 return DLP_FUSE_ERROR_LINKFILE_EXIST;
77 }
78
79 for (auto it = dlpLinkFileNameMap_.begin(); it != dlpLinkFileNameMap_.end(); it++) {
80 DlpLinkFile* linkFileNode = it->second;
81 if ((linkFileNode != nullptr) && (filePtr == linkFileNode->GetDlpFilePtr())) {
82 DLP_LOG_ERROR(LABEL, "Add link file fail, this dlp file already has link file");
83 return DLP_FUSE_ERROR_LINKFILE_EXIST;
84 }
85 }
86
87 DlpLinkFile *node = new (std::nothrow) DlpLinkFile(dlpLinkName, filePtr);
88 if (node == nullptr) {
89 DLP_LOG_ERROR(LABEL, "Add link file fail, alloc link file %{public}s fail", dlpLinkName.c_str());
90 return DLP_FUSE_ERROR_MEMORY_OPERATE_FAIL;
91 }
92
93 DLP_LOG_INFO(LABEL, "Add link file succ, file name %{public}s", dlpLinkName.c_str());
94 dlpLinkFileNameMap_[dlpLinkName] = node;
95 filePtr->SetLinkStatus();
96 return DLP_OK;
97 }
98
StopDlpLinkFile(const std::shared_ptr<DlpFile> & filePtr)99 int32_t DlpLinkManager::StopDlpLinkFile(const std::shared_ptr<DlpFile>& filePtr)
100 {
101 if (filePtr == nullptr) {
102 DLP_LOG_ERROR(LABEL, "Stop link file fail, dlp file is null");
103 return DLP_FUSE_ERROR_DLP_FILE_NULL;
104 }
105
106 Utils::UniqueWriteGuard<Utils::RWLock> infoGuard(dlpLinkMapLock_);
107 for (auto iter = dlpLinkFileNameMap_.begin(); iter != dlpLinkFileNameMap_.end(); iter++) {
108 DlpLinkFile* node = iter->second;
109 if (node == nullptr) {
110 DLP_LOG_ERROR(LABEL, "Stop link file fail, file ptr is null");
111 return DLP_FUSE_ERROR_DLP_FILE_NULL;
112 }
113 if (filePtr == node->GetDlpFilePtr()) {
114 node->stopLink();
115 filePtr->RemoveLinkStatus();
116 DLP_LOG_INFO(LABEL, "Stop link file success, file name %{public}s", node->GetLinkName().c_str());
117 return DLP_OK;
118 }
119 }
120 DLP_LOG_ERROR(LABEL, "Stop link file fail, link file not exist");
121 return DLP_FUSE_ERROR_LINKFILE_NOT_EXIST;
122 }
123
RestartDlpLinkFile(const std::shared_ptr<DlpFile> & filePtr)124 int32_t DlpLinkManager::RestartDlpLinkFile(const std::shared_ptr<DlpFile>& filePtr)
125 {
126 if (filePtr == nullptr) {
127 DLP_LOG_ERROR(LABEL, "Restart link file fail, dlp file is null");
128 return DLP_FUSE_ERROR_DLP_FILE_NULL;
129 }
130
131 Utils::UniqueWriteGuard<Utils::RWLock> infoGuard(dlpLinkMapLock_);
132 for (auto iter = dlpLinkFileNameMap_.begin(); iter != dlpLinkFileNameMap_.end(); iter++) {
133 DlpLinkFile* node = iter->second;
134 if (node == nullptr) {
135 DLP_LOG_ERROR(LABEL, "Restart link file fail, file ptr is null");
136 return DLP_FUSE_ERROR_DLP_FILE_NULL;
137 }
138 if (filePtr == node->GetDlpFilePtr()) {
139 node->restartLink();
140 filePtr->SetLinkStatus();
141 DLP_LOG_INFO(LABEL, "Restart link file success, file name %{public}s", node->GetLinkName().c_str());
142 return DLP_OK;
143 }
144 }
145 DLP_LOG_ERROR(LABEL, "Restart link file fail, link file not exist");
146 return DLP_FUSE_ERROR_LINKFILE_NOT_EXIST;
147 }
148
ReplaceDlpLinkFile(const std::shared_ptr<DlpFile> & filePtr,const std::string & dlpLinkName)149 int32_t DlpLinkManager::ReplaceDlpLinkFile(const std::shared_ptr<DlpFile>& filePtr, const std::string& dlpLinkName)
150 {
151 if (filePtr == nullptr) {
152 DLP_LOG_ERROR(LABEL, "Replace link file fail, dlp file is null");
153 return DLP_FUSE_ERROR_DLP_FILE_NULL;
154 }
155 if (!IsLinkNameValid(dlpLinkName)) {
156 DLP_LOG_ERROR(LABEL, "Replace link file fail, link file name %{public}s invalid", dlpLinkName.c_str());
157 return DLP_FUSE_ERROR_VALUE_INVALID;
158 }
159
160 Utils::UniqueWriteGuard<Utils::RWLock> infoGuard(dlpLinkMapLock_);
161 for (auto iter = dlpLinkFileNameMap_.begin(); iter != dlpLinkFileNameMap_.end(); iter++) {
162 if (dlpLinkName == iter->first) {
163 DlpLinkFile *node = iter->second;
164 if (node == nullptr) {
165 DLP_LOG_ERROR(
166 LABEL, "Replace link file fail, file %{public}s found but file ptr is null", dlpLinkName.c_str());
167 return DLP_FUSE_ERROR_DLP_FILE_NULL;
168 }
169 node->setDlpFilePtr(filePtr);
170 DLP_LOG_INFO(LABEL, "Replace link file success, file name %{public}s", dlpLinkName.c_str());
171 return DLP_OK;
172 }
173 }
174 DLP_LOG_ERROR(LABEL, "Replace link file fail, file %{public}s not exist", dlpLinkName.c_str());
175 return DLP_FUSE_ERROR_LINKFILE_NOT_EXIST;
176 }
177
DeleteDlpLinkFile(const std::shared_ptr<DlpFile> & filePtr)178 int32_t DlpLinkManager::DeleteDlpLinkFile(const std::shared_ptr<DlpFile>& filePtr)
179 {
180 if (filePtr == nullptr) {
181 return DLP_FUSE_ERROR_DLP_FILE_NULL;
182 }
183
184 Utils::UniqueWriteGuard<Utils::RWLock> infoGuard(dlpLinkMapLock_);
185 for (auto iter = dlpLinkFileNameMap_.begin(); iter != dlpLinkFileNameMap_.end(); iter++) {
186 DlpLinkFile* tmp = iter->second;
187 if (tmp != nullptr && filePtr == tmp->GetDlpFilePtr()) {
188 filePtr->RemoveLinkStatus();
189 dlpLinkFileNameMap_.erase(iter);
190 if (tmp->SubAndCheckZeroRef(1)) {
191 DLP_LOG_INFO(LABEL, "Delete link file %{private}s ok", tmp->GetLinkName().c_str());
192 delete tmp;
193 } else {
194 DLP_LOG_INFO(LABEL, "Link file %{private}s is still referenced by kernel, only remove it from map",
195 tmp->GetLinkName().c_str());
196 }
197 return DLP_OK;
198 }
199 }
200 DLP_LOG_ERROR(LABEL, "Delete link file fail, it does not exist.");
201 return DLP_FUSE_ERROR_LINKFILE_NOT_EXIST;
202 }
203
LookUpDlpLinkFile(const std::string & dlpLinkName)204 DlpLinkFile* DlpLinkManager::LookUpDlpLinkFile(const std::string& dlpLinkName)
205 {
206 Utils::UniqueReadGuard<Utils::RWLock> infoGuard(dlpLinkMapLock_);
207 for (auto iter = dlpLinkFileNameMap_.begin(); iter != dlpLinkFileNameMap_.end(); ++iter) {
208 if (dlpLinkName == iter->first) {
209 DlpLinkFile* node = iter->second;
210 if (node == nullptr) {
211 DLP_LOG_ERROR(LABEL, "Look up link file fail, file %{public}s found but file ptr is null",
212 dlpLinkName.c_str());
213 return nullptr;
214 }
215 node->IncreaseRef();
216 return node;
217 }
218 }
219 DLP_LOG_ERROR(LABEL, "Look up link file fail, file %{public}s not exist", dlpLinkName.c_str());
220 return nullptr;
221 }
222
DumpDlpLinkFile(std::vector<DlpLinkFileInfo> & linkList)223 void DlpLinkManager::DumpDlpLinkFile(std::vector<DlpLinkFileInfo>& linkList)
224 {
225 Utils::UniqueReadGuard<Utils::RWLock> infoGuard(dlpLinkMapLock_);
226 for (auto iter = dlpLinkFileNameMap_.begin(); iter != dlpLinkFileNameMap_.end(); iter++) {
227 DlpLinkFile* filePtr = iter->second;
228 if (filePtr == nullptr) {
229 continue;
230 }
231 DlpLinkFileInfo info;
232 info.dlpLinkName = filePtr->GetLinkName();
233 info.fileStat = filePtr->GetLinkStat();
234 linkList.emplace_back(info);
235 }
236 }
237
GetInstance()238 DlpLinkManager* DlpLinkManager::GetInstance()
239 {
240 static DlpLinkManager* instance = nullptr;
241 if (instance == nullptr) {
242 std::lock_guard<std::mutex> lock(g_instanceMutex);
243 if (instance == nullptr) {
244 instance = new DlpLinkManager();
245 }
246 }
247 return instance;
248 }
249 } // namespace DlpPermission
250 } // namespace Security
251 } // namespace OHOS
252