• 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 }
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