• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 
16 #include "user/mount_manager.h"
17 #include <cstdlib>
18 #include <fcntl.h>
19 #include <sys/mount.h>
20 #include <sys/types.h>
21 #include <unistd.h>
22 #include "ipc/istorage_daemon.h"
23 #include "parameter.h"
24 #include "storage_service_errno.h"
25 #include "storage_service_log.h"
26 #include "utils/file_utils.h"
27 #include "utils/mount_argument_utils.h"
28 #include "utils/string_utils.h"
29 #include "system_ability_definition.h"
30 #include "cloud_daemon_manager.h"
31 
32 
33 namespace OHOS {
34 namespace StorageDaemon {
35 using namespace std;
36 using namespace OHOS::FileManagement::CloudFile;
37 constexpr int32_t UMOUNT_RETRY_TIMES = 3;
38 std::shared_ptr<MountManager> MountManager::instance_ = nullptr;
39 
40 const std::string HMDFS_SYS_CAP = "const.distributed_file_property.enabled";
41 const int32_t HMDFS_VAL_LEN = 6;
42 const int32_t HMDFS_TRUE_LEN = 5;
MountManager()43 MountManager::MountManager()
44     : hmdfsDirVec_{{"/data/service/el2/%d/share", 0711, OID_SYSTEM, OID_SYSTEM},
45                    {"/data/service/el2/%d/hmdfs", 0711, OID_SYSTEM, OID_SYSTEM},
46                    {"/data/service/el2/%d/hmdfs/fuse", 0771, OID_DFS, OID_DFS},
47                    {"/data/service/el2/%d/hmdfs/account", 0711, OID_SYSTEM, OID_SYSTEM},
48                    {"/data/service/el2/%d/hmdfs/account/files", 02771, OID_USER_DATA_RW, OID_USER_DATA_RW},
49                    {"/data/service/el2/%d/hmdfs/account/data", 0711, OID_SYSTEM, OID_SYSTEM},
50                    {"/data/service/el2/%d/hmdfs/non_account", 0711, OID_SYSTEM, OID_SYSTEM},
51                    {"/data/service/el2/%d/hmdfs/non_account/files", 0711, OID_USER_DATA_RW, OID_USER_DATA_RW},
52                    {"/data/service/el2/%d/hmdfs/non_account/data", 0711, OID_SYSTEM, OID_SYSTEM},
53                    {"/data/service/el2/%d/hmdfs/cache", 0711, OID_DFS, OID_DFS},
54                    {"/data/service/el2/%d/hmdfs/cache/account_cache", 0711, OID_DFS, OID_DFS},
55                    {"/data/service/el2/%d/hmdfs/cache/non_account_cache", 0711, OID_DFS, OID_DFS},
56                    {"/data/service/el2/%d/hmdfs/account/services", 0771, OID_DFS_SHARE, OID_DFS_SHARE}},
57       virtualDir_{{"/storage/media/%d", 0711, OID_USER_DATA_RW, OID_USER_DATA_RW},
58                   {"/storage/media/%d/local", 0711, OID_USER_DATA_RW, OID_USER_DATA_RW},
59                   {"/storage/cloud", 0711, OID_ROOT, OID_ROOT},
60                   {"/storage/cloud/%d", 0711, OID_USER_DATA_RW, OID_USER_DATA_RW},
61                   {"/mnt/share/", 0711, OID_ROOT, OID_ROOT},
62                   {"/mnt/share/%d/", 0711, OID_ROOT, OID_ROOT},
63                   {"/mnt/data/%d/", 0711, OID_ROOT, OID_ROOT},
64                   {"/mnt/hmdfs/", 0711, OID_ROOT, OID_ROOT},
65                   {"/mnt/hmdfs/%d/", 0711, OID_ROOT, OID_ROOT},
66                   {"/mnt/hmdfs/%d/account", 0711, OID_ROOT, OID_ROOT},
67                   {"/mnt/hmdfs/%d/non_account", 0711, OID_ROOT, OID_ROOT},
68                   {"/mnt/hmdfs/%d/cloud", 0711, OID_ROOT, OID_ROOT}},
69       fileManagerDir_{{"/data/service/el2/%d/hmdfs/account/files/Documents", 02771, OID_FILE_MANAGER, OID_FILE_MANAGER},
70                    {"/data/service/el2/%d/hmdfs/account/files/Download", 02771, OID_FILE_MANAGER, OID_FILE_MANAGER},
71                    {"/data/service/el2/%d/hmdfs/account/files/Desktop", 02771, OID_FILE_MANAGER, OID_FILE_MANAGER},
72                    {"/data/service/el2/%d/hmdfs/account/files/Docs", 02771, OID_FILE_MANAGER, OID_FILE_MANAGER},
73                    {"/data/service/el2/%d/hmdfs/account/files/.Recent", 02771, OID_FILE_MANAGER, OID_FILE_MANAGER},
74                    {"/data/service/el2/%d/hmdfs/account/files/.Trash", 02771, OID_FILE_MANAGER, OID_FILE_MANAGER}}
75 {
76 }
77 
GetInstance()78 std::shared_ptr<MountManager> MountManager::GetInstance()
79 {
80     static std::once_flag onceFlag;
81     std::call_once(onceFlag, [&]() { instance_ = std::make_shared<MountManager>(); });
82 
83     return instance_;
84 }
85 
HmdfsTwiceMount(int32_t userId,std::string relativePath)86 int32_t MountManager::HmdfsTwiceMount(int32_t userId, std::string relativePath)
87 {
88     int32_t ret = HmdfsMount(userId, relativePath);
89 
90     // bind mount
91     Utils::MountArgument hmdfsMntArgs(Utils::MountArgumentDescriptors::Alpha(userId, relativePath));
92     ret += Mount(hmdfsMntArgs.GetFullDst() + "/device_view/", hmdfsMntArgs.GetCommFullPath(),
93                  nullptr, MS_BIND, nullptr);
94     if (ret != 0 && errno != EEXIST && errno != EBUSY) {
95         LOGE("failed to bind mount device_view, err %{public}d", errno);
96         return E_MOUNT;
97     }
98     ret += Mount(hmdfsMntArgs.GetFullDst() + "/cloud_merge_view/", hmdfsMntArgs.GetCloudFullPath(),
99                  nullptr, MS_BIND, nullptr);
100     if (ret != 0 && errno != EEXIST && errno != EBUSY) {
101         LOGE("failed to bind mount cloud_merge_view, err %{public}d", errno);
102         return E_MOUNT;
103     }
104     return E_OK;
105 }
106 
SharefsMount(int32_t userId)107 int32_t MountManager::SharefsMount(int32_t userId)
108 {
109     Utils::MountArgument sharefsMntArgs(Utils::MountArgumentDescriptors::Alpha(userId, ""));
110     int ret = Mount(sharefsMntArgs.GetShareSrc(), sharefsMntArgs.GetShareDst(), "sharefs",
111                     sharefsMntArgs.GetFlags(), sharefsMntArgs.GetUserIdPara().c_str());
112     if (ret != 0 && errno != EEXIST && errno != EBUSY) {
113         LOGE("failed to mount sharefs, err %{public}d", errno);
114         return E_MOUNT;
115     }
116     return E_OK;
117 }
118 
SharefsUMount(int32_t userId)119 int32_t MountManager::SharefsUMount(int32_t userId)
120 {
121     Utils::MountArgument sharefsMntArgs(Utils::MountArgumentDescriptors::Alpha(userId, ""));
122     int32_t ret = UMount2(sharefsMntArgs.GetShareDst().c_str(), MNT_DETACH);
123     if (ret != E_OK) {
124         LOGE("umount sharefs, errno %{public}d, sharefs dst %{public}s", errno,
125              sharefsMntArgs.GetShareDst().c_str());
126         return E_UMOUNT;
127     }
128     return E_OK;
129 }
130 
HmdfsMount(int32_t userId,std::string relativePath)131 int32_t MountManager::HmdfsMount(int32_t userId, std::string relativePath)
132 {
133     Utils::MountArgument hmdfsMntArgs(Utils::MountArgumentDescriptors::Alpha(userId, relativePath));
134     int ret = Mount(hmdfsMntArgs.GetFullSrc(), hmdfsMntArgs.GetFullDst(), "hmdfs",
135                     hmdfsMntArgs.GetFlags(), hmdfsMntArgs.OptionsToString().c_str());
136     if (ret != 0 && errno != EEXIST && errno != EBUSY) {
137         LOGE("failed to mount hmdfs, err %{public}d", errno);
138         return E_MOUNT;
139     }
140 
141     ret = chown(hmdfsMntArgs.GetCtrlPath().c_str(), OID_DFS, OID_SYSTEM);
142     if (ret != 0) {
143         LOGE("failed to chown hmdfs sysfs node, err %{public}d", errno);
144     }
145 
146     return E_OK;
147 }
148 
149 
CloudMount(int32_t userId)150 int32_t MountManager::CloudMount(int32_t userId)
151 {
152     int fd = -1;
153     string opt;
154     int ret;
155     Utils::MountArgument cloudMntArgs(Utils::MountArgumentDescriptors::Alpha(userId, ""));
156     const string path = cloudMntArgs.GetFullCloud();
157     if (!cloudReady_) {
158         LOGI("Cloud Service has not started");
159         return E_MOUNT;
160     }
161 
162     fd = open("/dev/fuse", O_RDWR);
163     if (fd < 0) {
164         LOGE("open /dev/fuse fail");
165         return E_MOUNT;
166     }
167 
168     opt = StringPrintf("fd=%i,"
169         "rootmode=40000,"
170         "default_permissions,"
171         "allow_other,"
172         "user_id=0,group_id=0,"
173         "context=\"u:object_r:hmdfs:s0\","
174         "fscontext=u:object_r:hmdfs:s0",
175         fd);
176     ret = Mount("/dev/fuse", path.c_str(), "fuse", MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_NOATIME, opt.c_str());
177     if (ret) {
178         LOGE("failed to mount fuse, err %{public}d %{public}d %{public}s", errno, ret, path.c_str());
179         close(fd);
180         return ret;
181     }
182 
183     ret = CloudDaemonManager::GetInstance().StartFuse(userId, fd, path);
184     if (ret) {
185         LOGE("failed to connect fuse, err %{public}d %{public}d %{public}s", errno, ret, path.c_str());
186         UMount(path.c_str());
187     }
188     LOGI("mount %{public}s success", path.c_str());
189     close(fd);
190     return ret;
191 }
192 
HmdfsMount(int32_t userId)193 int32_t MountManager::HmdfsMount(int32_t userId)
194 {
195     int32_t ret = HmdfsTwiceMount(userId, "account");
196 
197     ret += HmdfsMount(userId, "non_account");
198     if (ret != E_OK) {
199         return E_MOUNT;
200     }
201 
202     mountMutex_.lock();
203     ret = CloudMount(userId);
204     if (ret == E_OK) {
205         fuseMountedUsers_.push_back(userId);
206     } else {
207         fuseToMountUsers_.push_back(userId);
208     }
209     mountMutex_.unlock();
210 
211     return E_OK;
212 }
213 
MountCloudForUsers(void)214 void MountManager::MountCloudForUsers(void)
215 {
216     for (auto it = fuseToMountUsers_.begin(); it != fuseToMountUsers_.end();) {
217         int32_t res = CloudMount(*it);
218         if (res == E_OK) {
219             fuseMountedUsers_.push_back(*it);
220             it = fuseToMountUsers_.erase(it);
221         } else {
222             it++;
223         }
224     }
225 }
226 
UMountCloudForUsers(void)227 void MountManager::UMountCloudForUsers(void)
228 {
229     for (auto it = fuseMountedUsers_.begin(); it != fuseMountedUsers_.end();) {
230         int32_t res = CloudUMount(*it);
231         if (res == E_OK) {
232             fuseToMountUsers_.push_back(*it);
233             it = fuseMountedUsers_.erase(it);
234         } else {
235             it++;
236         }
237     }
238 }
239 
SetCloudState(bool active)240 void MountManager::SetCloudState(bool active)
241 {
242     mountMutex_.lock();
243     cloudReady_ = active;
244     if (cloudReady_) {
245         MountCloudForUsers();
246     } else {
247         UMountCloudForUsers();
248     }
249     mountMutex_.unlock();
250 }
251 
HmdfsTwiceUMount(int32_t userId,std::string relativePath)252 int32_t MountManager::HmdfsTwiceUMount(int32_t userId, std::string relativePath)
253 {
254     int32_t err = E_OK;
255     // un bind mount
256     Utils::MountArgument hmdfsMntArgs(Utils::MountArgumentDescriptors::Alpha(userId, relativePath));
257     err = UMount(hmdfsMntArgs.GetCommFullPath());
258     if (err != E_OK) {
259         LOGE("failed to un bind mount, errno %{public}d, ComDataDir_ dst %{public}s", errno,
260              hmdfsMntArgs.GetCommFullPath().c_str());
261     }
262     err = UMount(hmdfsMntArgs.GetCloudFullPath());
263     if (err != E_OK) {
264         LOGE("failed to un bind mount, errno %{public}d, CloudDataDir dst %{public}s", errno,
265              hmdfsMntArgs.GetCloudFullPath().c_str());
266     }
267 
268     err = UMount2(hmdfsMntArgs.GetFullDst().c_str(), MNT_DETACH);
269     if (err != E_OK) {
270         LOGE("identical account hmdfs umount failed, errno %{public}d, hmdfs dst %{public}s", errno,
271              hmdfsMntArgs.GetFullDst().c_str());
272         return E_UMOUNT;
273     }
274     return E_OK;
275 }
276 
HmdfsUMount(int32_t userId,std::string relativePath)277 int32_t MountManager::HmdfsUMount(int32_t userId, std::string relativePath)
278 {
279     Utils::MountArgument hmdfsAuthMntArgs(Utils::MountArgumentDescriptors::Alpha(userId, relativePath));
280     int32_t ret = UMount2(hmdfsAuthMntArgs.GetFullDst().c_str(), MNT_DETACH);
281     if (ret != E_OK) {
282         LOGE("umount auth hmdfs, errno %{public}d, auth hmdfs dst %{public}s", errno,
283              hmdfsAuthMntArgs.GetFullDst().c_str());
284         return E_UMOUNT;
285     }
286     return E_OK;
287 }
288 
CloudUMount(int32_t userId)289 int32_t MountManager::CloudUMount(int32_t userId)
290 {
291     int32_t err = E_OK;
292     Utils::MountArgument cloudMntArgs(Utils::MountArgumentDescriptors::Alpha(userId, ""));
293     const string path = cloudMntArgs.GetFullCloud();
294 
295     err = UMount(path);
296     if (err != E_OK) {
297         LOGE("fuse umount failed, errno %{public}d, fuse dst %{public}s", errno, path.c_str());
298         return E_UMOUNT;
299     }
300     LOGI("umount %{public}s success", path.c_str());
301     return E_OK;
302 }
303 
HmdfsUMount(int32_t userId)304 int32_t MountManager::HmdfsUMount(int32_t userId)
305 {
306     int32_t ret = HmdfsTwiceUMount(userId, "account");
307     ret += HmdfsUMount(userId, "non_account");
308     if (ret != E_OK) {
309         return E_UMOUNT;
310     }
311     CloudUMount(userId);
312     return E_OK;
313 }
314 
SupportHmdfs()315 bool MountManager::SupportHmdfs()
316 {
317     char hmdfsEnable[HMDFS_VAL_LEN + 1] = {"false"};
318     int ret = GetParameter(HMDFS_SYS_CAP.c_str(), "", hmdfsEnable, HMDFS_VAL_LEN);
319     LOGI("GetParameter hmdfsEnable %{public}s, ret %{public}d", hmdfsEnable, ret);
320     if (strncmp(hmdfsEnable, "true", HMDFS_TRUE_LEN) == 0) {
321         return true;
322     }
323     return false;
324 }
325 
LocalMount(int32_t userId)326 int32_t MountManager::LocalMount(int32_t userId)
327 {
328     Utils::MountArgument LocalMntArgs(Utils::MountArgumentDescriptors::Alpha(userId, "account"));
329     if (Mount(LocalMntArgs.GetFullSrc(), LocalMntArgs.GetCommFullPath() + "local/",
330               nullptr, MS_BIND, nullptr)) {
331         LOGE("failed to bind mount, err %{public}d", errno);
332         return E_MOUNT;
333     }
334     if (Mount(LocalMntArgs.GetFullSrc(), LocalMntArgs.GetCloudFullPath(),
335               nullptr, MS_BIND, nullptr)) {
336         LOGE("failed to bind mount, err %{public}d", errno);
337         return E_MOUNT;
338     }
339     return E_OK;
340 }
341 
MountByUser(int32_t userId)342 int32_t MountManager::MountByUser(int32_t userId)
343 {
344     int ret = E_OK;
345     // The Documnets and Download directories are managed by the File access framework,
346     // and the UID GID is changed to filemanager
347     PrepareFileManagerDir(userId);
348     if (CreateVirtualDirs(userId) != E_OK) {
349         LOGE("create hmdfs virtual dir error");
350         return E_PREPARE_DIR;
351     }
352 
353     if (!SupportHmdfs()) {
354         ret = LocalMount(userId);
355     } else {
356         ret = HmdfsMount(userId);
357     }
358 
359     if (ret != E_OK) {
360         LOGE("hmdfs mount error");
361         return ret;
362     }
363 
364     ret = SharefsMount(userId);
365     if (ret != E_OK) {
366         LOGE("sharefs mount error");
367         return ret;
368     }
369     return E_OK;
370 }
371 
PrepareFileManagerDir(int32_t userId)372 void MountManager::PrepareFileManagerDir(int32_t userId)
373 {
374     for (const DirInfo &dir : fileManagerDir_) {
375         std::string path = StringPrintf(dir.path.c_str(), userId);
376         int ret = IsSameGidUid(path, dir.uid, dir.gid);
377         LOGE("prepareDir %{public}s ret %{public}d", path.c_str(), ret);
378         // Dir exist and same uid, gid
379         if (ret == E_OK) {
380             continue;
381         }
382         // system error
383         if (ret == E_SYS_ERR) {
384             LOGE("system err %{public}s ", path.c_str());
385             continue;
386         }
387         // Dir exist and different uid, gid
388         if (ret == E_DIFF_UID_GID) {
389             ChownRecursion(path, OID_FILE_MANAGER, OID_FILE_MANAGER);
390             continue;
391         }
392         // Dir not exist
393         if (ret == E_NON_EXIST && !PrepareDir(path, dir.mode, dir.uid, dir.gid)) {
394             LOGE("failed to prepareDir %{public}s ", path.c_str());
395         }
396     }
397 }
398 
LocalUMount(int32_t userId)399 int32_t MountManager::LocalUMount(int32_t userId)
400 {
401     Utils::MountArgument LocalMntArgs(Utils::MountArgumentDescriptors::Alpha(userId, "account"));
402     int err = UMount(LocalMntArgs.GetCommFullPath() + "local/");
403     if (err != E_OK) {
404         LOGE("failed to un bind mount, errno %{public}d, ComDataDir dst %{public}s", errno,
405              LocalMntArgs.GetCommFullPath().c_str());
406     }
407     err = UMount(LocalMntArgs.GetCloudFullPath());
408     if (err != E_OK) {
409         LOGE("failed to un bind mount, errno %{public}d, CloudDataDir dst %{public}s", errno,
410              LocalMntArgs.GetCloudFullPath().c_str());
411     }
412     return err;
413 }
414 
UmountByUser(int32_t userId)415 int32_t MountManager::UmountByUser(int32_t userId)
416 {
417     int32_t count = 0;
418     while (count < UMOUNT_RETRY_TIMES) {
419         int32_t err = E_OK;
420         err = SharefsUMount(userId);
421         if (err != E_OK) {
422             LOGE("failed to umount sharefs, errno %{public}d", errno);
423         }
424         if (!SupportHmdfs()) {
425             err = LocalUMount(userId);
426         } else {
427             err = HmdfsUMount(userId);
428         }
429         if (err == E_OK) {
430             break;
431         } else if (errno == EBUSY) {
432             count++;
433             continue;
434         }
435         LOGE("failed to umount hmdfs, errno %{public}d", errno);
436         return E_UMOUNT;
437     }
438     return E_OK;
439 }
440 
PrepareHmdfsDirs(int32_t userId)441 int32_t MountManager::PrepareHmdfsDirs(int32_t userId)
442 {
443     for (const DirInfo &dir : hmdfsDirVec_) {
444         if (!PrepareDir(StringPrintf(dir.path.c_str(), userId), dir.mode, dir.uid, dir.gid)) {
445             return E_PREPARE_DIR;
446         }
447     }
448 
449     return E_OK;
450 }
451 
PrepareFileManagerDirs(int32_t userId)452 int32_t MountManager::PrepareFileManagerDirs(int32_t userId)
453 {
454     for (const DirInfo &dir : fileManagerDir_) {
455         if (!PrepareDir(StringPrintf(dir.path.c_str(), userId), dir.mode, dir.uid, dir.gid)) {
456             return E_PREPARE_DIR;
457         }
458     }
459 
460     return E_OK;
461 }
462 
CreateVirtualDirs(int32_t userId)463 int32_t MountManager::CreateVirtualDirs(int32_t userId)
464 {
465     for (const DirInfo &dir : virtualDir_) {
466         if (!PrepareDir(StringPrintf(dir.path.c_str(), userId), dir.mode, dir.uid, dir.gid)) {
467             return E_PREPARE_DIR;
468         }
469     }
470 
471     return E_OK;
472 }
473 
DestroyHmdfsDirs(int32_t userId)474 int32_t MountManager::DestroyHmdfsDirs(int32_t userId)
475 {
476     bool err = true;
477 
478     for (const DirInfo &dir : hmdfsDirVec_) {
479         if (IsEndWith(dir.path.c_str(), "%d")) {
480             err = RmDirRecurse(StringPrintf(dir.path.c_str(), userId));
481         }
482     }
483 
484     return err ? E_OK : E_DESTROY_DIR;
485 }
486 
487 
DestroyFileManagerDirs(int32_t userId)488 int32_t MountManager::DestroyFileManagerDirs(int32_t userId)
489 {
490     bool err = true;
491 
492     for (const DirInfo &dir : fileManagerDir_) {
493         if (IsEndWith(dir.path.c_str(), "%d")) {
494             err = RmDirRecurse(StringPrintf(dir.path.c_str(), userId));
495         }
496     }
497 
498     return err ? E_OK : E_DESTROY_DIR;
499 }
500 
501 } // namespace StorageDaemon
502 } // namespace OHOS
503