1 /*
2 * Copyright (c) 2022 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 "samgr_ipc_adapter.h"
16
17 typedef struct IRegisterEpArg IRegisterEpArg;
18 struct IRegisterEpArg {
19 Endpoint *endpoint;
20 int token;
21 char *service;
22 char *feature;
23 };
24 static int Dispatch(uint32_t code, IpcIo *data, IpcIo *reply, MessageOption option);
25 static void HandleIpc(const Request *request, const Response *response);
26 static void *Receive(void *argv);
27 static int RegisterRemoteFeatures(Endpoint *endpoint);
28 static void OnSamgrServerExit(void *argv);
29 static void GetRemotePolicy(IpcIo *reply, PolicyTrans **policy, uint32 *policyNum);
30 static boolean JudgePolicy(uid_t callingUid, const PolicyTrans *policy, uint32 policyNum);
31 static boolean SearchFixedPolicy(uid_t callingUid, PolicyTrans policy);
ClientRegisterRemoteEndpoint(SvcIdentity * identity,int token,const char * service,const char * feature)32 int ClientRegisterRemoteEndpoint(SvcIdentity *identity, int token, const char *service, const char *feature)
33 {
34 IpcIo req;
35 uint8 data[MAX_DATA_LEN];
36 IpcIoInit(&req, data, MAX_DATA_LEN, 1);
37 // add samgr server token
38 WriteInt32(&req, 0);
39 WriteUint32(&req, RES_ENDPOINT);
40 WriteUint32(&req, OP_POST);
41 bool ret = WriteRemoteObject(&req, identity);
42 if (!ret) {
43 return EC_FAILURE;
44 }
45 uint32 retry = 0;
46 while (retry < MAX_RETRY_TIMES) {
47 ++retry;
48 IpcIo reply;
49 void *replyBuf = NULL;
50 MessageOption option;
51 MessageOptionInit(&option);
52 SvcIdentity *samgr = GetContextObject();
53
54 int err = SendRequest(*samgr, INVALID_INDEX, &req, &reply, option, (uintptr_t *)&replyBuf);
55 if (err == EC_SUCCESS) {
56 ret = ReadInt32(&reply, &identity->handle);
57 if (!ret || identity->handle == INVALID_INDEX) {
58 continue;
59 }
60 if (replyBuf != NULL) {
61 FreeBuffer(replyBuf);
62 }
63 return EC_SUCCESS;
64 }
65 usleep(RETRY_INTERVAL);
66 }
67 return EC_FAILURE;
68 }
69
Listen(Endpoint * endpoint,int token,const char * service,const char * feature)70 void Listen(Endpoint *endpoint, int token, const char *service, const char *feature)
71 {
72 if (endpoint->boss != NULL) {
73 return;
74 }
75 ThreadAttr attr = {endpoint->name, MAX_STACK_SIZE, PRI_ABOVE_NORMAL, 0, 0};
76 IRegisterEpArg *registerEpArg = SAMGR_Malloc(sizeof(IRegisterEpArg));
77 if (registerEpArg == NULL) {
78 HILOG_ERROR(HILOG_MODULE_SAMGR, "IRegisterEpArg Memory is not enough!");
79 return;
80 }
81 IpcObjectStub *objectStubOne = (IpcObjectStub *)calloc(1, sizeof(IpcObjectStub));
82 if (objectStubOne == NULL) {
83 HILOG_ERROR(HILOG_MODULE_SAMGR, "IpcObjectStub Memory is not enough!");
84 return;
85 }
86
87 objectStubOne->func = Dispatch;
88 objectStubOne->args = endpoint;
89 objectStubOne->isRemote = false;
90 endpoint->identity.cookie = objectStubOne;
91 // handle must -1
92 endpoint->identity.handle = INVALID_INDEX;
93 endpoint->identity.token = SERVICE_TYPE_NORMAL;
94
95 registerEpArg->endpoint = endpoint;
96 registerEpArg->token = token;
97 registerEpArg->service = service;
98 registerEpArg->feature = feature;
99 endpoint->boss = (ThreadId)THREAD_Create(Receive, registerEpArg, &attr);
100 }
101
Receive(void * argv)102 static void *Receive(void *argv)
103 {
104 IRegisterEpArg *registerEpArg = (IRegisterEpArg *)argv;
105 if (registerEpArg == NULL || registerEpArg->endpoint->registerEP == NULL) {
106 return NULL;
107 }
108 int ret = EC_INVALID;
109 uint32 retry = 0;
110 while (retry < MAX_RETRY_TIMES) {
111 ret = registerEpArg->endpoint->registerEP(®isterEpArg->endpoint->identity,
112 registerEpArg->token, registerEpArg->service, registerEpArg->feature);
113 if (ret == EC_SUCCESS) {
114 SvcIdentity *samgr = GetContextObject();
115 (void)RemoveDeathRecipient(*samgr, registerEpArg->endpoint->deadId);
116 (void)AddDeathRecipient(*samgr, OnSamgrServerExit, registerEpArg->endpoint,
117 ®isterEpArg->endpoint->deadId);
118 break;
119 }
120 ++retry;
121 usleep(RETRY_INTERVAL);
122 }
123 if (ret != EC_SUCCESS) {
124 HILOG_FATAL(HILOG_MODULE_SAMGR, "Register endpoint<%s>, handle<%u> failed! will exit to recover!",
125 registerEpArg->endpoint->name, registerEpArg->endpoint->identity.handle);
126 SAMGR_Free(registerEpArg);
127 return NULL;
128 }
129 registerEpArg->endpoint->running = TRUE;
130 if (strcmp(registerEpArg->endpoint->name, SAMGR_SERVICE) != 0) {
131 int remain = RegisterRemoteFeatures(registerEpArg->endpoint);
132 HILOG_INFO(HILOG_MODULE_SAMGR, "Register endpoint<%s> and iunknown finished! remain<%d> iunknown!",
133 registerEpArg->endpoint->name, remain);
134 }
135 SAMGR_Free(registerEpArg);
136 JoinWorkThread();
137 return NULL;
138 }
139
RegisterRemoteFeatures(Endpoint * endpoint)140 static int RegisterRemoteFeatures(Endpoint *endpoint)
141 {
142 int nums = 0;
143 int size = VECTOR_Size(&endpoint->routers);
144 int i;
145 SvcIdentity identity;
146 for (i = 0; i < size; ++i) {
147 Router *router = VECTOR_At(&endpoint->routers, i);
148 if (router == NULL) {
149 continue;
150 }
151 identity.handle = endpoint->identity.handle;
152 identity.token = i;
153 int ret = RegisterIdentity(&(router->saName), &identity, &(router->policy),
154 &(router->policyNum));
155 if (ret == EC_SUCCESS) {
156 ++nums;
157 }
158 HILOG_DEBUG(HILOG_MODULE_SAMGR, "RegisterRemoteFeatures<%s, %s> ret:%d",
159 router->saName.service, router->saName.feature, ret);
160 }
161 return VECTOR_Num(&endpoint->routers) - nums;
162 }
163
RegisterIdentity(const SaName * saName,SvcIdentity * saInfo,PolicyTrans ** policy,uint32 * policyNum)164 int RegisterIdentity(const SaName *saName, SvcIdentity *saInfo, PolicyTrans **policy, uint32 *policyNum)
165 {
166 IpcIo req;
167 uint8 data[MAX_DATA_LEN];
168 IpcIoInit(&req, data, MAX_DATA_LEN, 0);
169 WriteInt32(&req, 0);
170 WriteUint32(&req, RES_FEATURE);
171 WriteUint32(&req, OP_PUT);
172 WriteString(&req, saName->service);
173 WriteBool(&req, saName->feature == NULL);
174 if (saName->feature != NULL) {
175 WriteString(&req, saName->feature);
176 }
177 WriteUint32(&req, saInfo->token);
178 IpcIo reply;
179 void *replyBuf = NULL;
180 SvcIdentity *samgr = GetContextObject();
181 MessageOption option;
182 MessageOptionInit(&option);
183 int ret = SendRequest(*samgr, INVALID_INDEX, &req, &reply, option,
184 (uintptr_t *)&replyBuf);
185 ret = -ret;
186 int32_t ipcRet = EC_FAILURE;
187 if (ret == EC_SUCCESS) {
188 ReadInt32(&reply, &ipcRet);
189 }
190 if (ipcRet == EC_SUCCESS) {
191 SvcIdentity target;
192 (void)ReadRemoteObject(&reply, &target);
193 GetRemotePolicy(&reply, policy, policyNum);
194 }
195 if (replyBuf != NULL) {
196 FreeBuffer(replyBuf);
197 }
198 return ipcRet;
199 }
Dispatch(uint32_t code,IpcIo * data,IpcIo * reply,MessageOption option)200 static int Dispatch(uint32_t code, IpcIo *data, IpcIo *reply, MessageOption option)
201 {
202 Endpoint *endpoint = (Endpoint *)option.args;
203 int token = GetRemoteToken(data);
204 if (token == EC_INVALID) {
205 goto ERROR;
206 }
207 if (TB_CheckMessage(&endpoint->bucket) == BUCKET_BUSY) {
208 HILOG_WARN(HILOG_MODULE_SAMGR, "Flow Control <%u> is NULL", token);
209 goto ERROR;
210 }
211 Router *router = VECTOR_At(&endpoint->routers, token);
212 if (router == NULL) {
213 HILOG_ERROR(HILOG_MODULE_SAMGR, "Router <%s, %u> is NULL", endpoint->name, token);
214 goto ERROR;
215 }
216
217 Response resp = {0};
218 resp.data = endpoint;
219 resp.reply = reply;
220 Request request = {0};
221 request.msgId = token;
222 request.data = data;
223 request.msgValue = code;
224
225 HandleIpc(&request, &resp);
226 return EC_SUCCESS;
227 ERROR:
228 return EC_INVALID;
229 }
230
HandleIpc(const Request * request,const Response * response)231 static void HandleIpc(const Request *request, const Response *response)
232 {
233 Endpoint *endpoint = (Endpoint *)response->data;
234 Router *router = VECTOR_At(&endpoint->routers, request->msgId);
235 if (router == NULL || router->proxy == NULL || router->proxy->Invoke == NULL) {
236 HILOG_ERROR(HILOG_MODULE_SAMGR, "Invalid IPC router!");
237 return;
238 }
239 uid_t uid = GetCallingUid();
240 if ((strcmp(router->saName.service, SAMGR_SERVICE) != 0) &&
241 !JudgePolicy(uid, (const PolicyTrans *)(router->policy), router->policyNum)) {
242 HILOG_ERROR(HILOG_MODULE_SAMGR, "Consumer uid<%d> has no permission to access<%s, %d, %d>!",
243 uid, router->saName.service, router->identity.serviceId, router->identity.featureId);
244 return;
245 }
246 router->proxy->Invoke(router->proxy, request->msgValue, NULL, request->data, response->reply);
247 }
248
JudgePolicy(uid_t callingUid,const PolicyTrans * policy,uint32 policyNum)249 static boolean JudgePolicy(uid_t callingUid, const PolicyTrans *policy, uint32 policyNum)
250 {
251 if (policy == NULL) {
252 HILOG_ERROR(HILOG_MODULE_SAMGR, "Policy is NULL! Num is %u", policyNum);
253 return FALSE;
254 }
255 uint32 i;
256 for (i = 0; i < policyNum; i++) {
257 if (policy[i].type == RANGE && callingUid >= policy[i].uidMin && callingUid <= policy[i].uidMax) {
258 return TRUE;
259 }
260 if (policy[i].type == FIXED && SearchFixedPolicy(callingUid, policy[i])) {
261 return TRUE;
262 }
263 }
264 return FALSE;
265 }
SearchFixedPolicy(uid_t callingUid,PolicyTrans policy)266 static boolean SearchFixedPolicy(uid_t callingUid, PolicyTrans policy)
267 {
268 int i;
269 for (i = 0; i < UID_SIZE; i++) {
270 if (callingUid == policy.fixedUid[i]) {
271 return TRUE;
272 }
273 }
274 return FALSE;
275 }
OnSamgrServerExit(void * argv)276 static void OnSamgrServerExit(void *argv)
277 {
278 HILOG_ERROR(HILOG_MODULE_SAMGR, "Disconnect to samgr server!");
279 Endpoint *endpoint = (Endpoint *)argv;
280 if (endpoint == NULL || endpoint->registerEP == NULL) {
281 return;
282 }
283 int size = VECTOR_Size(&endpoint->routers);
284 int i;
285 for (i = 0; i < size; i++) {
286 Router *router = VECTOR_At(&endpoint->routers, i);
287 if (router == NULL) {
288 continue;
289 }
290 SAMGR_Free(router->policy);
291 router->policy = NULL;
292 router->policyNum = 0;
293 }
294
295 SvcIdentity old = endpoint->identity;
296 while (endpoint->registerEP(&endpoint->identity, 0, "", "") != EC_SUCCESS) {
297 HILOG_ERROR(HILOG_MODULE_SAMGR, "Reconnect to samgr server failed!");
298 usleep(RETRY_INTERVAL);
299 }
300 SvcIdentity new = endpoint->identity;
301 if (old.handle != new.handle || old.cookie != new.cookie || old.token != new.token) {
302 HILOG_ERROR(HILOG_MODULE_SAMGR, "Samgr server identity error!");
303 exit(-1);
304 }
305
306 SvcIdentity identity = {SAMGR_HANDLE, SAMGR_TOKEN, SAMGR_COOKIE};
307 ReleaseSvc(identity);
308 (void)AddDeathRecipient(identity, OnSamgrServerExit, endpoint, &endpoint->deadId);
309 int remain = RegisterRemoteFeatures(endpoint);
310 HILOG_INFO(HILOG_MODULE_SAMGR, "Reconnect and register finished! remain<%d> iunknown!", remain);
311 }
312
GetRemoteToken(IpcIo * data)313 int GetRemoteToken(IpcIo *data)
314 {
315 int32_t token;
316 if (ReadInt32(data, &token)) {
317 return token;
318 }
319 return EC_INVALID;
320 }
321
GetRemotePolicy(IpcIo * reply,PolicyTrans ** policy,uint32 * policyNum)322 static void GetRemotePolicy(IpcIo *reply, PolicyTrans **policy, uint32 *policyNum)
323 {
324 if (reply == NULL) {
325 return;
326 }
327 uint32 i;
328 uint32 j;
329 ReadUint32(reply, policyNum);
330 if (*policyNum > MAX_POLICY_NUM) {
331 *policyNum = MAX_POLICY_NUM;
332 }
333 SAMGR_Free(*policy);
334 if (*policyNum == 0) {
335 *policy = NULL;
336 return;
337 }
338 *policy = (PolicyTrans *)SAMGR_Malloc(sizeof(PolicyTrans) * (*policyNum));
339 if (*policy == NULL) {
340 return;
341 }
342 for (i = 0; i < *policyNum; i++) {
343 if (!ReadInt32(reply, &(*policy)[i].type)) {
344 continue;
345 }
346 switch ((*policy)[i].type) {
347 case RANGE:
348 ReadInt32(reply, &((*policy)[i].uidMin));
349 ReadInt32(reply, &((*policy)[i].uidMax));
350 break;
351 case FIXED:
352 for (j = 0; j < UID_SIZE; j++) {
353 ReadInt32(reply, &((*policy)[i].fixedUid[j]));
354 }
355 break;
356 case BUNDLENAME:
357 ReadInt32(reply, &((*policy)[i].fixedUid[0]));
358 break;
359 default:
360 break;
361 }
362 }
363 }