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