1 /*
2 * Copyright (c) 2024-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
16 #include <sys/mount.h>
17 #include <sys/stat.h>
18 #include <sys/wait.h>
19 #include "securec.h"
20 #include "init_utils.h"
21 #include "fs_dm.h"
22 #include "fs_manager/fs_manager.h"
23 #include "erofs_remount_overlay.h"
24
GetRemountResult(void)25 int GetRemountResult(void)
26 {
27 int fd = open(REMOUNT_RESULT_FLAG, O_RDONLY);
28 if (fd >= 0) {
29 char buff[1];
30 int ret = read(fd, buff, 1);
31 if (ret < 0) {
32 BEGET_LOGE("read remount.result.done failed errno %d", errno);
33 close(fd);
34 return REMOUNT_FAIL;
35 }
36 close(fd);
37 if (buff[0] == '0' + REMOUNT_SUCC) {
38 return REMOUNT_SUCC;
39 }
40 }
41 return REMOUNT_FAIL;
42 }
43
SetRemountResultFlag()44 void SetRemountResultFlag()
45 {
46 struct stat st;
47 int ret;
48
49 int statRet = stat(REMOUNT_RESULT_PATH, &st);
50 if (statRet != 0) {
51 ret = mkdir(REMOUNT_RESULT_PATH, MODE_MKDIR);
52 if (ret < 0 && errno != EEXIST) {
53 BEGET_LOGE("mkdir remount path failed errno %d", errno);
54 return;
55 }
56 }
57
58 int fd = open(REMOUNT_RESULT_FLAG, O_WRONLY | O_CREAT, 0644);
59 if (fd < 0) {
60 BEGET_LOGE("open remount.result.done failed errno %d", errno);
61 return;
62 }
63
64 char buff[1];
65 buff[0] = '0' + REMOUNT_SUCC;
66
67 ret = write(fd, buff, 1);
68 if (ret < 0) {
69 BEGET_LOGE("write buff failed errno %d", errno);
70 }
71 close(fd);
72 BEGET_LOGI("set remount result flag successfully");
73 }
74
Modem2Exchange(const char * modemPath,const char * exchangePath)75 INIT_STATIC int Modem2Exchange(const char *modemPath, const char *exchangePath)
76 {
77 int ret;
78 ret = mkdir(exchangePath, MODE_MKDIR);
79 if (ret) {
80 BEGET_LOGE("mkdir %s failed.", exchangePath);
81 } else {
82 BEGET_LOGI("mkdir %s succeed.", exchangePath);
83 }
84
85 ret = mount(modemPath, exchangePath, NULL, MS_BIND | MS_RDONLY, NULL);
86 if (ret) {
87 BEGET_LOGE("bind %s to %s failed.", modemPath, exchangePath);
88 } else {
89 BEGET_LOGI("bind %s to %s succeed.", modemPath, exchangePath);
90 }
91
92 return ret;
93 }
94
Exchange2Modem(const char * modemPath,const char * exchangePath)95 INIT_STATIC int Exchange2Modem(const char *modemPath, const char *exchangePath)
96 {
97 int ret;
98 struct stat statInfo;
99 if (lstat(exchangePath, &statInfo)) {
100 BEGET_LOGE("no exchangePath %s.", exchangePath);
101 return 0;
102 }
103
104 ret = mount(exchangePath, modemPath, NULL, MS_BIND | MS_RDONLY, NULL);
105 if (ret) {
106 BEGET_LOGE("bind %s to %s failed.", exchangePath, modemPath);
107 } else {
108 BEGET_LOGI("bind %s to %s succeed.", exchangePath, modemPath);
109 }
110
111 ret = umount(exchangePath);
112 if (ret) {
113 BEGET_LOGE("umount %s failed.", exchangePath);
114 } else {
115 BEGET_LOGI("umount %s succeed.", exchangePath);
116 }
117
118 ret = remove(exchangePath);
119 if (ret) {
120 BEGET_LOGE("remove %s failed.", exchangePath);
121 } else {
122 BEGET_LOGI("remove %s succeed.", exchangePath);
123 }
124
125 return ret;
126 }
127
OverlayRemountVendorPre(void)128 void OverlayRemountVendorPre(void)
129 {
130 struct stat statInfo;
131
132 if (!stat(MODEM_DRIVER_MNT_PATH, &statInfo)) {
133 Modem2Exchange(MODEM_DRIVER_MNT_PATH, MODEM_DRIVER_EXCHANGE_PATH);
134 }
135
136 if (!stat(MODEM_VENDOR_MNT_PATH, &statInfo)) {
137 Modem2Exchange(MODEM_VENDOR_MNT_PATH, MODEM_VENDOR_EXCHANGE_PATH);
138 }
139
140 if (!stat(MODEM_FW_MNT_PATH, &statInfo)) {
141 Modem2Exchange(MODEM_FW_MNT_PATH, MODEM_FW_EXCHANGE_PATH);
142 }
143 }
144
OverlayRemountVendorPost()145 void OverlayRemountVendorPost()
146 {
147 Exchange2Modem(MODEM_DRIVER_MNT_PATH, MODEM_DRIVER_EXCHANGE_PATH);
148 Exchange2Modem(MODEM_VENDOR_MNT_PATH, MODEM_VENDOR_EXCHANGE_PATH);
149 Exchange2Modem(MODEM_FW_MNT_PATH, MODEM_FW_EXCHANGE_PATH);
150 }
151
MountOverlayOne(const char * mnt)152 int MountOverlayOne(const char *mnt)
153 {
154 if ((strcmp(mnt, MODEM_DRIVER_MNT_PATH) == 0) || (strcmp(mnt, MODEM_VENDOR_MNT_PATH) == 0)) {
155 return 0;
156 }
157 char dirLower[MAX_BUFFER_LEN] = {0};
158 char dirUpper[MAX_BUFFER_LEN] = {0};
159 char dirWork[MAX_BUFFER_LEN] = {0};
160 char mntOpt[MAX_BUFFER_LEN] = {0};
161
162 if (strcmp(mnt, "/usr") == 0) {
163 if (snprintf_s(dirLower, MAX_BUFFER_LEN, MAX_BUFFER_LEN - 1, "%s", "/system") < 0) {
164 BEGET_LOGE("copy system dirLower failed. errno %d", errno);
165 return -1;
166 }
167 } else {
168 if (snprintf_s(dirLower, MAX_BUFFER_LEN, MAX_BUFFER_LEN - 1, "%s%s", PREFIX_LOWER, mnt) < 0) {
169 BEGET_LOGE("copy dirLower failed. errno %d", errno);
170 return -1;
171 }
172 }
173
174 if (snprintf_s(dirUpper, MAX_BUFFER_LEN, MAX_BUFFER_LEN - 1, "%s%s%s", PREFIX_OVERLAY, mnt, PREFIX_UPPER) < 0) {
175 BEGET_LOGE("copy dirUpper failed. errno %d", errno);
176 return -1;
177 }
178
179 if (snprintf_s(dirWork, MAX_BUFFER_LEN, MAX_BUFFER_LEN - 1, "%s%s%s", PREFIX_OVERLAY, mnt, PREFIX_WORK) < 0) {
180 BEGET_LOGE("copy dirWork failed. errno %d", errno);
181 return -1;
182 }
183
184 if (snprintf_s(mntOpt, MAX_BUFFER_LEN, MAX_BUFFER_LEN - 1,
185 "upperdir=%s,lowerdir=%s,workdir=%s,override_creds=off", dirUpper, dirLower, dirWork) < 0) {
186 BEGET_LOGE("copy mntOpt failed. errno %d", errno);
187 return -1;
188 }
189
190 if (strcmp(mnt, "/usr") == 0) {
191 if (mount("overlay", "/system", "overlay", 0, mntOpt)) {
192 BEGET_LOGE("mount system overlay failed. errno %d", errno);
193 return -1;
194 }
195 } else {
196 if (mount("overlay", mnt, "overlay", 0, mntOpt)) {
197 BEGET_LOGE("mount overlay fs failed. errno %d", errno);
198 return -1;
199 }
200 }
201 BEGET_LOGI("mount overlay fs success on mnt:%s", mnt);
202 return 0;
203 }
204
RemountOverlay(void)205 int RemountOverlay(void)
206 {
207 char *remountPath[] = {
208 "/usr", "/vendor", "/sys_prod", "/chip_prod", "/preload", "/cust", "/version", "/patch_hw"
209 };
210 for (size_t i = 0; i < ARRAY_LENGTH(remountPath); i++) {
211 struct stat statInfo;
212 char dirMnt[MAX_BUFFER_LEN] = {0};
213 if (snprintf_s(dirMnt, MAX_BUFFER_LEN, MAX_BUFFER_LEN - 1, "/mnt/overlay%s/upper", remountPath[i]) < 0) {
214 BEGET_LOGE("copy dirMnt [%s] failed.", dirMnt);
215 return -1;
216 }
217
218 if (lstat(dirMnt, &statInfo)) {
219 BEGET_LOGW("dirMnt [%s] not exist.", dirMnt);
220 continue;
221 }
222
223 if (strcmp(remountPath[i], "/vendor") == 0) {
224 OverlayRemountVendorPre();
225 }
226
227 if (MountOverlayOne(remountPath[i])) {
228 BEGET_LOGE("mount overlay failed on mnt [%s].", dirMnt);
229 return -1;
230 }
231
232 if (strcmp(remountPath[i], "/vendor") == 0) {
233 OverlayRemountVendorPost();
234 }
235 }
236 return 0;
237 }