• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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