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