• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(&registerEpArg->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                     &registerEpArg->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 }