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