• 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 #include "init.h"
16 
17 #include <errno.h>
18 #include <poll.h>
19 #include <stdlib.h>
20 #include <signal.h>
21 #include <sys/sysmacros.h>
22 #include <sys/stat.h>
23 #include <sys/types.h>
24 #include <sys/socket.h>
25 #include <linux/major.h>
26 #include "device.h"
27 #include "fd_holder_service.h"
28 #include "fs_manager/fs_manager.h"
29 #include "init_log.h"
30 #include "init_mount.h"
31 #include "init_group_manager.h"
32 #include "init_param.h"
33 #include "init_service.h"
34 #include "init_service_manager.h"
35 #include "init_utils.h"
36 #include "securec.h"
37 #include "switch_root.h"
38 #include "ueventd.h"
39 #include "ueventd_socket.h"
40 #include "fd_holder_internal.h"
41 #ifdef WITH_SELINUX
42 #include <policycoreutils.h>
43 #include <selinux/selinux.h>
44 #endif // WITH_SELINUX
45 
FdHolderSockInit(void)46 static int FdHolderSockInit(void)
47 {
48     int sock = -1;
49     int on = 1;
50     int fdHolderBufferSize = FD_HOLDER_BUFFER_SIZE; // 4KiB
51     sock = socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
52     if (sock < 0) {
53         INIT_LOGE("Failed to create fd holder socket, err = %d", errno);
54         return -1;
55     }
56 
57     setsockopt(sock, SOL_SOCKET, SO_RCVBUFFORCE, &fdHolderBufferSize, sizeof(fdHolderBufferSize));
58     setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
59 
60     if (access(INIT_HOLDER_SOCKET_PATH, F_OK) == 0) {
61         INIT_LOGI("%s exist, remove it", INIT_HOLDER_SOCKET_PATH);
62         unlink(INIT_HOLDER_SOCKET_PATH);
63     }
64     struct sockaddr_un addr;
65     addr.sun_family = AF_UNIX;
66     if (strncpy_s(addr.sun_path, sizeof(addr.sun_path),
67         INIT_HOLDER_SOCKET_PATH, strlen(INIT_HOLDER_SOCKET_PATH)) != 0) {
68         INIT_LOGE("Faild to copy fd hoder socket path");
69         close(sock);
70         return -1;
71     }
72     socklen_t len = (socklen_t)(offsetof(struct sockaddr_un, sun_path) + strlen(addr.sun_path) + 1);
73     if (bind(sock, (struct sockaddr *)&addr, len) < 0) {
74         INIT_LOGE("Failed to binder fd folder socket %d", errno);
75         close(sock);
76         return -1;
77     }
78 
79     // Owned by root
80     if (lchown(addr.sun_path, 0, 0)) {
81         INIT_LOGW("Failed to change owner of fd holder socket, err = %d", errno);
82     }
83     mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
84     if (fchmodat(AT_FDCWD, addr.sun_path, mode, AT_SYMLINK_NOFOLLOW)) {
85         INIT_LOGW("Failed to change mode of fd holder socket, err = %d", errno);
86     }
87     INIT_LOGI("Init fd holder socket done");
88     return sock;
89 }
90 
SystemInit(void)91 void SystemInit(void)
92 {
93     SignalInit();
94     // umask call always succeeds and return the previous mask value which is not needed here
95     (void)umask(DEFAULT_UMASK_INIT);
96     MakeDirRecursive("/dev/unix/socket", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
97     int sock = FdHolderSockInit();
98     if (sock >= 0) {
99         RegisterFdHoldWatcher(sock);
100     }
101 }
102 
EnableDevKmsg(void)103 static void EnableDevKmsg(void)
104 {
105     /* printk_devkmsg default value is ratelimit, We need to set "on" and remove the restrictions */
106     int fd = open("/proc/sys/kernel/printk_devkmsg", O_WRONLY | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IRGRP);
107     if (fd < 0) {
108         return;
109     }
110     char *kmsgStatus = "on";
111     write(fd, kmsgStatus, strlen(kmsgStatus) + 1);
112     close(fd);
113     fd = -1;
114     return;
115 }
116 
LogInit(void)117 void LogInit(void)
118 {
119     CloseStdio();
120     int ret = mknod("/dev/kmsg", S_IFCHR | S_IWUSR | S_IRUSR,
121         makedev(MEM_MAJOR, DEV_KMSG_MINOR));
122     if (ret == 0) {
123         OpenLogDevice();
124     }
125 }
126 
GetRequiredDevices(Fstab fstab,int * requiredNum)127 static char **GetRequiredDevices(Fstab fstab, int *requiredNum)
128 {
129     int num = 0;
130     FstabItem *item = fstab.head;
131     while (item != NULL) {
132         if (FM_MANAGER_REQUIRED_ENABLED(item->fsManagerFlags)) {
133             num++;
134         }
135         item = item->next;
136     }
137     char **devices = (char **)calloc(num, sizeof(char *));
138     INIT_ERROR_CHECK(devices != NULL, return NULL, "Failed calloc err=%d", errno);
139 
140     int i = 0;
141     item = fstab.head;
142     while (item != NULL) {
143         if (FM_MANAGER_REQUIRED_ENABLED(item->fsManagerFlags)) {
144             devices[i] = strdup(item->deviceName);
145             INIT_ERROR_CHECK(devices[i] != NULL, FreeStringVector(devices, num); return NULL,
146                 "Failed strdup err=%d", errno);
147             i++;
148         }
149         item = item->next;
150     }
151     *requiredNum = num;
152     return devices;
153 }
154 
StartUeventd(char ** requiredDevices,int num)155 static int StartUeventd(char **requiredDevices, int num)
156 {
157     INIT_ERROR_CHECK(requiredDevices != NULL && num > 0, return -1, "Failed parameters");
158     int ueventSockFd = UeventdSocketInit();
159     if (ueventSockFd < 0) {
160         INIT_LOGE("Failed to create uevent socket");
161         return -1;
162     }
163     RetriggerUevent(ueventSockFd, requiredDevices, num);
164     close(ueventSockFd);
165     return 0;
166 }
167 
StartInitSecondStage(void)168 static void StartInitSecondStage(void)
169 {
170     const char *fstabFile = "/etc/fstab.required";
171     Fstab *fstab = NULL;
172     if (access(fstabFile, F_OK) != 0) {
173         fstabFile = "/system/etc/fstab.required";
174     }
175     INIT_ERROR_CHECK(access(fstabFile, F_OK) == 0, abort(), "Failed get fstab.required");
176     fstab = ReadFstabFromFile(fstabFile, false);
177     INIT_ERROR_CHECK(fstab != NULL, abort(), "Read fstab file \" %s \" failed\n", fstabFile);
178 
179     int requiredNum = 0;
180     char **devices = GetRequiredDevices(*fstab, &requiredNum);
181     if (devices != NULL && requiredNum > 0) {
182         int ret = StartUeventd(devices, requiredNum);
183         if (ret == 0) {
184             ret = MountRequriedPartitions(fstab);
185         }
186         FreeStringVector(devices, requiredNum);
187         devices = NULL;
188         ReleaseFstab(fstab);
189         fstab = NULL;
190         if (ret < 0) {
191             // If mount required partitions failure.
192             // There is no necessary to continue.
193             // Just abort
194             INIT_LOGE("Mount requried partitions failed; please check fstab file");
195             // Execute sh for debugging
196             execv("/bin/sh", NULL);
197             abort();
198         }
199     }
200 #ifndef DISABLE_INIT_TWO_STAGES
201     SwitchRoot("/usr");
202     // Execute init second stage
203     char * const args[] = {
204         "/bin/init",
205         "--second-stage",
206         NULL,
207     };
208     if (execv("/bin/init", args) != 0) {
209         INIT_LOGE("Failed to exec \"/bin/init\", err = %d", errno);
210         exit(-1);
211     }
212 #endif
213 }
214 
SystemPrepare(void)215 void SystemPrepare(void)
216 {
217     MountBasicFs();
218     LogInit();
219     // Make sure init log always output to /dev/kmsg.
220     EnableDevKmsg();
221     CreateDeviceNode();
222     // Only ohos normal system support
223     // two stages of init.
224     // If we are in updater mode, only one stage of init,
225     INIT_LOGI("DISABLE_INIT_TWO_STAGES not defined");
226     if (InUpdaterMode() == 0) {
227         StartInitSecondStage();
228     }
229 }
230 
SystemLoadSelinux(void)231 void SystemLoadSelinux(void)
232 {
233 #ifdef WITH_SELINUX
234     // load selinux policy and context
235     if (LoadPolicy() < 0) {
236         INIT_LOGE("main, load_policy failed.");
237     } else {
238         INIT_LOGI("main, load_policy success.");
239     }
240 
241     setcon("u:r:init:s0");
242     (void)RestoreconRecurse("/dev");
243 #endif // WITH_SELINUX
244 }
245 
BootStateChange(const char * content)246 static void BootStateChange(const char *content)
247 {
248     INIT_LOGI("boot start %s finish.", content);
249     if (strcmp("init", content) == 0) {
250         StartAllServices(START_MODE_BOOT);
251         return;
252     }
253     if (strcmp("post-init", content) == 0) {
254         StartAllServices(START_MODE_NARMAL);
255         return;
256     }
257 }
258 
259 #if defined(OHOS_SERVICE_DUMP)
SystemDump(int id,const char * name,int argc,const char ** argv)260 static int SystemDump(int id, const char *name, int argc, const char **argv)
261 {
262     INIT_ERROR_CHECK(argv != NULL && argc >= 1, return 0, "Invalid install parameter");
263     INIT_LOGI("Dump system info %s", argv[0]);
264     DumpAllServices();
265     DumpParametersAndTriggers();
266     return 0;
267 }
268 #endif
269 
SystemConfig(void)270 void SystemConfig(void)
271 {
272     InitServiceSpace();
273     InitParseGroupCfg();
274     PluginManagerInit();
275 
276     InitParamService();
277     RegisterBootStateChange(BootStateChange);
278 
279     // load SELinux context and policy
280     // Do not move position!
281     SystemLoadSelinux();
282 
283     // parse parameters
284     LoadDefaultParams("/system/etc/param/ohos_const", LOAD_PARAM_NORMAL);
285     LoadDefaultParams("/vendor/etc/param", LOAD_PARAM_NORMAL);
286     LoadDefaultParams("/system/etc/param", LOAD_PARAM_ONLY_ADD);
287     // read config
288     ReadConfig();
289     INIT_LOGI("Parse init config file done.");
290 
291     // dump config
292 #if defined(OHOS_SERVICE_DUMP)
293     AddCmdExecutor("display", SystemDump);
294     (void)AddCompleteJob("param:ohos.servicectrl.display", "ohos.servicectrl.display=*", "display system");
295 #endif
296 
297     // execute init
298     PostTrigger(EVENT_TRIGGER_BOOT, "pre-init", strlen("pre-init"));
299     PostTrigger(EVENT_TRIGGER_BOOT, "init", strlen("init"));
300     PostTrigger(EVENT_TRIGGER_BOOT, "post-init", strlen("post-init"));
301 }
302 
SystemRun(void)303 void SystemRun(void)
304 {
305     StartParamService();
306 }
307