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