• 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 <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 (service == NULL) {
38         INIT_LOGE("Request hold fds with invalid service");
39         return -1;
40     }
41 
42     if (fds == NULL || fdCount == 0 || fdCount > MAX_HOLD_FDS) {
43         INIT_LOGE("Service %s request hold fds with invalid fds", service->name);
44         return -1;
45     }
46 
47     INIT_LOGI("Hold service \' %s \' fds:", service->name);
48     for (size_t i = 0; i < fdCount; i++) {
49         INIT_LOGI("fd = %d", fds[i]);
50     }
51     if (UpdaterServiceFds(service, fds, fdCount) < 0) {
52         INIT_LOGE("Failed to update service \' %s \' fds", service->name);
53         return -1;
54     }
55 
56     if (strcmp(pollStr, WITHPOLL) == 0) {
57         // poll service fds if service asked for
58         INIT_LOGI("Service \' %s \' asked init to poll fds, not implement yet.", service->name);
59     }
60     return 0;
61 }
62 
SendErrorInfo(int sock,const char * errInfo,const char * serviceName)63 static void SendErrorInfo(int sock, const char *errInfo, const char *serviceName)
64 {
65     int ret = 0;
66     char errBuffer[MAX_FD_HOLDER_BUFFER] = {};
67     if (UNLIKELY(errInfo == NULL)) { // Should not happen.
68         char *defaultError = "Unknonw error";
69         ret = strncpy_s(errBuffer, MAX_FD_HOLDER_BUFFER, defaultError, strlen(defaultError));
70     } else {
71         ret = strncpy_s(errBuffer, MAX_FD_HOLDER_BUFFER, errInfo, strlen(errInfo));
72     }
73     if (ret != 0) {
74         INIT_LOGE("Failed to copy, err = %d", errno);
75         return;
76     }
77 
78     struct iovec iovec = {
79         .iov_base = errBuffer,
80         .iov_len = strlen(errBuffer),
81     };
82 
83     struct msghdr msghdr = {
84         .msg_iov = &iovec,
85         .msg_iovlen = 1,
86         .msg_control = NULL,
87         .msg_controllen = 0,
88         .msg_flags = 0,
89     };
90 
91     if (TEMP_FAILURE_RETRY(sendmsg(sock, &msghdr, MSG_NOSIGNAL)) < 0) {
92         INIT_LOGE("Failed to send err info to service \' %s \', err = %d", serviceName, errno);
93     }
94 }
95 
SendFdsInfo(int sock,Service * service)96 static void SendFdsInfo(int sock, Service *service)
97 {
98     // Sanity check
99     if (sock < 0 || service == NULL) {
100         INIT_LOGE("Try to send fd with invalid parameter");
101         return;
102     }
103     char sendBuffer[MAX_FD_HOLDER_BUFFER] = {};
104     if (strncpy_s(sendBuffer, MAX_FD_HOLDER_BUFFER, "send done", strlen("send done")) != 0) {
105         INIT_LOGE("Failed to copy, err = %d", errno);
106         return;
107     }
108     struct iovec iovec = {
109         .iov_base = sendBuffer,
110         .iov_len = strlen(sendBuffer),
111     };
112 
113     struct msghdr msghdr = {
114         .msg_iov = &iovec,
115         .msg_iovlen = 1,
116     };
117 
118     if (BuildControlMessage(&msghdr, service->fds, service->fdCount, false) < 0) {
119         SendErrorInfo(sock, "Failed to build send message", service->name);
120     } else {
121         if (TEMP_FAILURE_RETRY(sendmsg(sock, &msghdr, MSG_NOSIGNAL)) < 0) {
122             INIT_LOGE("Failed to send fd info to service \' %s \', err = %d", service->name, errno);
123         } else {
124             // Send fd to service OK, need to close fds in init.
125             CloseServiceFds(service, true);
126         }
127     }
128 
129     if (msghdr.msg_control != NULL) {
130         free(msghdr.msg_control);
131         msghdr.msg_control = NULL;
132         msghdr.msg_controllen = 0;
133     }
134 }
135 
HandlerGetFds(int sock,Service * service)136 static void HandlerGetFds(int sock, Service *service)
137 {
138     if (sock < 0 || service == NULL) {
139         INIT_LOGE("Get fd from init with invalid parameter");
140         SendErrorInfo(sock, "Invalid parameter", "");
141         return;
142     }
143 
144     if (service->fds == NULL || service->fdCount == 0) {
145         INIT_LOGE("Service \' %s \' does not have any held fds", service->name);
146         SendErrorInfo(sock, "Service without any fds", service->name);
147         return;
148     }
149 
150     // Send fds back to service
151     SendFdsInfo(sock, service);
152 }
153 
CheckFdHolderPermission(Service * service,pid_t requestPid)154 static int CheckFdHolderPermission(Service *service, pid_t requestPid)
155 {
156     if (service == NULL) {
157         INIT_LOGE("Invalid service");
158         return -1;
159     }
160 
161     INIT_LOGI("received service pid = %d", requestPid);
162     if (service->pid < 0 || requestPid != service->pid) {
163         INIT_LOGE("Service \' %s \'(pid = %d) is not valid or request with unexpected process(pid = %d)",
164             service->name, service->pid, requestPid);
165         return -1;
166     }
167     INIT_LOGI("CheckFdHolderPermission done");
168     return 0;
169 }
170 
CloseFds(int * fds,size_t fdCount)171 static inline void CloseFds(int *fds, size_t fdCount)
172 {
173     for (size_t i = 0; i < fdCount; i++) {
174         close(fds[i]);
175     }
176 }
177 
HandlerFdHolder(int sock)178 static void HandlerFdHolder(int sock)
179 {
180     char buffer[MAX_FD_HOLDER_BUFFER + 1] = {};
181     size_t fdCount = 0;
182     pid_t requestPid = -1;
183     struct iovec iovec = {
184         .iov_base = buffer,
185         .iov_len = MAX_FD_HOLDER_BUFFER,
186     };
187     int *fds = ReceiveFds(sock, iovec, &fdCount, true, &requestPid);
188     // Check what client want, is it want init to hold fds or return fds.
189     INIT_LOGI("Received buffer: [%s]", buffer);
190     int msgCount = 0;
191     int maxMsgCount = 3;
192     char **msg = SplitStringExt(buffer, "|", &msgCount, maxMsgCount);
193     if (msg == NULL || msgCount != maxMsgCount) {
194         INIT_LOGE("Invalid message received: %s", buffer);
195         CloseFds(fds, fdCount);
196         FreeFds(fds);
197         return;
198     }
199     char *serviceName = msg[0];
200     char *action = msg[1];
201     char *pollStr = msg[MSG_ARRAY_INDEX];
202 
203     Service *service = GetServiceByName(serviceName);
204     if (CheckFdHolderPermission(service, requestPid) < 0) {
205         // Permission check failed.
206         // But fds may already dup to init, so close them.
207         CloseFds(fds, fdCount);
208         FreeFds(fds);
209         FreeStringVector(msg, msgCount);
210         return;
211     }
212     if (strcmp(action, ACTION_HOLD) == 0) {
213         INIT_LOGI("Service \' %s \' request init to %s fds", serviceName, action);
214         if (HandlerHoldFds(service, fds, fdCount, pollStr) < 0) {
215             CloseFds(fds, fdCount);
216         }
217     } else if (strcmp(action, ACTION_GET) == 0) {
218         // In this case, ignore fds, just close them if fd passed to init
219         CloseFds(fds, fdCount);
220         HandlerGetFds(sock, service);
221     } else {
222         INIT_LOGE("Unexpected action: %s", action);
223         CloseFds(fds, fdCount);
224     }
225     FreeFds(fds);
226     FreeStringVector(msg, msgCount);
227 }
228 
ProcessFdHoldEvent(const WatcherHandle taskHandle,int fd,uint32_t * events,const void * context)229 static void ProcessFdHoldEvent(const WatcherHandle taskHandle, int fd, uint32_t *events, const void *context)
230 {
231     HandlerFdHolder(fd);
232     *events = Event_Read;
233 }
234 
RegisterFdHoldWatcher(int sock)235 void RegisterFdHoldWatcher(int sock)
236 {
237     if (sock < 0) {
238         INIT_LOGE("Invalid fd holder socket");
239         return;
240     }
241 
242     WatcherHandle watcher = NULL;
243     LE_WatchInfo info = {};
244     info.fd = sock;
245     info.flags = 0; // WATCHER_ONCE;
246     info.events = Event_Read;
247     info.processEvent = ProcessFdHoldEvent;
248     LE_StartWatcher(LE_GetDefaultLoop(), &watcher, &info, NULL);
249 }
250