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