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