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 <cstdlib>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <unistd.h>
19 #include <fcntl.h>
20 #include <sys/mount.h>
21 #include <securec.h>
22 #include <sys/wait.h>
23
24 #include "log.h"
25 #include "mount.h"
26
27 using namespace Hdc;
28
FindMountDeviceByPath(const char *toQuery, char *dev)29 bool FindMountDeviceByPath(const char *toQuery, char *dev)
30 {
31 int ret = false;
32 int len = BUF_SIZE_DEFAULT2;
33 char buf[BUF_SIZE_DEFAULT2];
34
35 FILE *fp = fopen("/proc/mounts", "r");
36 if (fp == nullptr) {
37 WRITE_LOG(LOG_FATAL, "fopen /proc/mounts error:%d", errno);
38 return false;
39 }
40
41 while (fgets(buf, len, fp) != nullptr) {
42 char dir[BUF_SIZE_SMALL] = "";
43 int freq;
44 int passnno;
45 int res = 0;
46 // clang-format off
47 res = sscanf_s(buf, "%255s %255s %*s %*s %d %d\n", dev, BUF_SIZE_SMALL - 1,
48 dir, BUF_SIZE_SMALL - 1, &freq, &passnno);
49 // clang-format on
50 dev[BUF_SIZE_SMALL - 1] = '\0';
51 dir[BUF_SIZE_SMALL - 1] = '\0';
52 if (res == 4 && (strcmp(toQuery, dir) == 0)) { // 4 : The correct number of parameters
53 WRITE_LOG(LOG_DEBUG, "FindMountDeviceByPath dev:%s dir:%s", dev, dir);
54 ret = true;
55 break;
56 }
57 }
58 int rc = fclose(fp);
59 if (rc != 0) {
60 WRITE_LOG(LOG_WARN, "fclose rc:%d error:%d", rc, errno);
61 }
62 if (!ret) {
63 WRITE_LOG(LOG_FATAL, "FindMountDeviceByPath not found %s", toQuery);
64 }
65 return ret;
66 }
67
RemountPartition(const char *dir)68 bool RemountPartition(const char *dir)
69 {
70 int fd;
71 int off = 0;
72 int ret = 0;
73 char dev[BUF_SIZE_SMALL] = "";
74
75 if (!FindMountDeviceByPath(dir, dev) || strlen(dev) < 4) { // 4 : file count
76 WRITE_LOG(LOG_FATAL, "FindMountDeviceByPath dir:%s failed", dir);
77 return false;
78 }
79
80 if ((fd = open(dev, O_RDONLY | O_CLOEXEC)) < 0) {
81 WRITE_LOG(LOG_FATAL, "open dev:%s failed, error:%d", dev, errno);
82 return false;
83 }
84 ioctl(fd, BLKROSET, &off);
85 close(fd);
86
87 ret = mount(dev, dir, "none", MS_REMOUNT, nullptr);
88 if (ret < 0) {
89 WRITE_LOG(LOG_FATAL, "mount %s failed, reason is %s", dev, strerror(errno));
90 return false;
91 }
92 return true;
93 }
94
RemountDevice()95 bool RemountDevice()
96 {
97 if (getuid() != 0) {
98 return false;
99 }
100 struct stat info;
101 if (!lstat("/vendor", &info) && (info.st_mode & S_IFMT) == S_IFDIR) {
102 if (!RemountPartition("/vendor")) {
103 WRITE_LOG(LOG_FATAL, "Mount failed /vendor (via mount)");
104 }
105 }
106 if (!lstat("/system", &info) && (info.st_mode & S_IFMT) == S_IFDIR) {
107 if (!RemountPartition("/")) {
108 WRITE_LOG(LOG_FATAL, "Mount failed /system (via mount)");
109 }
110 }
111
112 int exitStatus = system("/bin/remount");
113 if (exitStatus == -1) {
114 WRITE_LOG(LOG_FATAL, "Failed to execute /bin/remount: %s", strerror(errno));
115 return false;
116 } else if (WIFEXITED(exitStatus) && WEXITSTATUS(exitStatus) != 0) {
117 WRITE_LOG(LOG_FATAL, "Remount failed with exit code: %d", WEXITSTATUS(exitStatus));
118 return false;
119 }
120 return true;
121 }