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 <sys/socket.h>
16 #include <sys/un.h>
17
18 #include "fd_holder_internal.h"
19 #include "init_log.h"
20 #include "init_service.h"
21 #include "init_service_manager.h"
22 #include "init_utils.h"
23 #include "loop_event.h"
24 #include "securec.h"
25
26 #define MSG_ARRAY_INDEX 2
27
FreeFds(int * fds)28 static void FreeFds(int *fds)
29 {
30 if (fds != NULL) {
31 free(fds);
32 }
33 }
34
HandlerHoldFds(Service * service,int * fds,size_t fdCount,const char * pollStr)35 static int HandlerHoldFds(Service *service, int *fds, size_t fdCount, const char *pollStr)
36 {
37 if (fds == NULL || fdCount == 0 || fdCount > MAX_HOLD_FDS) {
38 INIT_LOGE("Service %s request hold fds with invalid fds", service->name);
39 return -1;
40 }
41
42 INIT_LOGI("Hold service \' %s \' fds:", service->name);
43 for (size_t i = 0; i < fdCount; i++) {
44 INIT_LOGI("fd = %d", fds[i]);
45 }
46 if (UpdaterServiceFds(service, fds, fdCount) < 0) {
47 INIT_LOGE("Failed to update service \' %s \' fds", service->name);
48 return -1;
49 }
50
51 if (strcmp(pollStr, WITHPOLL) == 0) {
52 // poll service fds if service asked for
53 INIT_LOGI("Service \' %s \' asked init to poll fds, not implement yet.", service->name);
54 }
55 return 0;
56 }
57
SendErrorInfo(int sock,const char * errInfo,const char * serviceName)58 static void SendErrorInfo(int sock, const char *errInfo, const char *serviceName)
59 {
60 int ret = 0;
61 char errBuffer[MAX_FD_HOLDER_BUFFER] = {};
62 if (UNLIKELY(errInfo == NULL)) { // Should not happen.
63 char *defaultError = "Unknonw error";
64 ret = strncpy_s(errBuffer, MAX_FD_HOLDER_BUFFER, defaultError, strlen(defaultError));
65 } else {
66 ret = strncpy_s(errBuffer, MAX_FD_HOLDER_BUFFER, errInfo, strlen(errInfo));
67 }
68 if (ret != 0) {
69 INIT_LOGE("Failed to copy, err = %d", errno);
70 return;
71 }
72
73 struct iovec iovec = {
74 .iov_base = errBuffer,
75 .iov_len = strlen(errBuffer),
76 };
77
78 struct msghdr msghdr = {
79 .msg_iov = &iovec,
80 .msg_iovlen = 1,
81 .msg_control = NULL,
82 .msg_controllen = 0,
83 .msg_flags = 0,
84 };
85
86 if (TEMP_FAILURE_RETRY(sendmsg(sock, &msghdr, MSG_NOSIGNAL)) < 0) {
87 INIT_LOGE("Failed to send err info to service \' %s \', err = %d", serviceName, errno);
88 }
89 }
90
CheckFdHolderPermission(Service * service,pid_t requestPid)91 static int CheckFdHolderPermission(Service *service, pid_t requestPid)
92 {
93 if (service == NULL) {
94 INIT_LOGE("Invalid service");
95 return -1;
96 }
97
98 INIT_LOGI("received service pid = %d", requestPid);
99 if (service->pid < 0 || requestPid != service->pid) {
100 INIT_LOGE("Service \' %s \'(pid = %d) is not valid or request with unexpected process(pid = %d)",
101 service->name, service->pid, requestPid);
102 return -1;
103 }
104 INIT_LOGI("CheckFdHolderPermission done");
105 return 0;
106 }
107
CloseFds(int * fds,size_t fdCount)108 static inline void CloseFds(int *fds, size_t fdCount)
109 {
110 if (fds == NULL) {
111 return;
112 }
113 for (size_t i = 0; i < fdCount; i++) {
114 close(fds[i]);
115 }
116 }
117
HandlerFdHolder(int sock)118 static void HandlerFdHolder(int sock)
119 {
120 char buffer[MAX_FD_HOLDER_BUFFER + 1] = {0};
121 size_t fdCount = 0;
122 pid_t requestPid = -1;
123 struct iovec iovec = {
124 .iov_base = buffer,
125 .iov_len = MAX_FD_HOLDER_BUFFER,
126 };
127 int *fds = ReceiveFds(sock, iovec, &fdCount, true, &requestPid);
128 // Check what client want, is it want init to hold fds or return fds.
129 INIT_LOGI("Received buffer: [%s]", buffer);
130 int msgCount = 0;
131 int maxMsgCount = 3;
132 char **msg = SplitStringExt(buffer, "|", &msgCount, maxMsgCount);
133 if (msg == NULL || msgCount != maxMsgCount) {
134 INIT_LOGE("Invalid message received: %s", buffer);
135 CloseFds(fds, fdCount);
136 FreeFds(fds);
137 return;
138 }
139 char *serviceName = msg[0];
140 char *action = msg[1];
141 char *pollStr = msg[MSG_ARRAY_INDEX];
142
143 Service *service = GetServiceByName(serviceName);
144 if (CheckFdHolderPermission(service, requestPid) < 0) {
145 SendErrorInfo(sock, "Invalid service", serviceName);
146 // Permission check failed.
147 // But fds may already dup to init, so close them.
148 CloseFds(fds, fdCount);
149 FreeFds(fds);
150 FreeStringVector(msg, msgCount);
151 return;
152 }
153 if (strcmp(action, ACTION_HOLD) == 0) {
154 INIT_LOGI("Service \' %s \' request init to %s fds", serviceName, action);
155 if (HandlerHoldFds(service, fds, fdCount, pollStr) < 0) {
156 CloseFds(fds, fdCount);
157 }
158 } else {
159 INIT_LOGE("Unexpected action: %s", action);
160 CloseFds(fds, fdCount);
161 }
162 FreeFds(fds);
163 FreeStringVector(msg, msgCount);
164 }
165
ProcessFdHoldEvent(const WatcherHandle taskHandle,int fd,uint32_t * events,const void * context)166 void ProcessFdHoldEvent(const WatcherHandle taskHandle, int fd, uint32_t *events, const void *context)
167 {
168 HandlerFdHolder(fd);
169 *events = EVENT_READ;
170 }
171
RegisterFdHoldWatcher(int sock)172 void RegisterFdHoldWatcher(int sock)
173 {
174 if (sock < 0) {
175 INIT_LOGE("Invalid fd holder socket");
176 return;
177 }
178
179 WatcherHandle watcher = NULL;
180 LE_WatchInfo info = {};
181 info.fd = sock;
182 info.flags = 0; // WATCHER_ONCE;
183 info.events = EVENT_READ;
184 info.processEvent = ProcessFdHoldEvent;
185 LE_StartWatcher(LE_GetDefaultLoop(), &watcher, &info, NULL);
186 }
187