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
16 #include "namespace.h"
17
18 #include "ld_log.h"
19 #include "malloc_impl.h"
20 #include "strops.h"
21
22 static ns_t g_ns_default;
23 static nslist g_ns_list;
24
25 #ifndef NSLIST_DEFAULT_SIZE
26 #define NSLIST_DEFAULT_SIZE 16
27 #endif
28 #ifndef DSOLIST_DEFAULT_SIZE
29 #define DSOLIST_DEFAULT_SIZE 16
30 #endif
31 #ifndef INHERIT_DEFAULT_SIZE
32 #define INHERIT_DEFAULT_SIZE 16
33 #endif
34
nsinherits_alloc()35 static ns_inherit_list *nsinherits_alloc()
36 {
37 ns_inherit_list *nsinl;
38 nsinl = (ns_inherit_list *)internal_calloc(1, sizeof *nsinl);
39
40 if (nsinl) {
41 nsinl->size = INHERIT_DEFAULT_SIZE;
42 nsinl->inherits = (ns_inherit **)internal_calloc(INHERIT_DEFAULT_SIZE, sizeof *nsinl->inherits);
43 if (!nsinl->inherits) {
44 LD_LOGE("nsinherits_alloc failed,return NULL!");
45 internal_free(nsinl);
46 nsinl = NULL;
47 }
48 }
49 return nsinl;
50 }
51
nsinherits_free(ns_inherit_list * nsinl)52 static void nsinherits_free(ns_inherit_list *nsinl)
53 {
54 if (!nsinl) {
55 return;
56 }
57 for (size_t i = 0; i < nsinl->num; i++) {
58 strlist_free(nsinl->inherits[i]->shared_libs);
59 internal_free(nsinl->inherits[i]);
60 }
61 internal_free(nsinl->inherits);
62 internal_free(nsinl);
63 }
64
nsinherits_realloc(ns_inherit_list * nsinl)65 static void nsinherits_realloc(ns_inherit_list *nsinl)
66 {
67 if (!nsinl) {
68 return;
69 }
70 size_t size = 2 * nsinl->size;
71 if (size) {
72 ns_inherit **inherits;
73 inherits = (ns_inherit **)internal_realloc(nsinl->inherits, size * (sizeof *nsinl->inherits));
74 if (!inherits) {
75 LD_LOGE("nsinherits_realloc failed!");
76 return;
77 }
78 nsinl->size = size;
79 nsinl->inherits = inherits;
80 }
81 return;
82 }
83
dsolist_alloc()84 static dsolist *dsolist_alloc()
85 {
86 dsolist *dsol;
87 dsol = (dsolist *)internal_calloc(1, sizeof *dsol);
88
89 if (dsol) {
90 dsol->size = DSOLIST_DEFAULT_SIZE;
91 dsol->dsos = (struct dso **)internal_calloc(DSOLIST_DEFAULT_SIZE, sizeof *dsol->dsos);
92 if (!dsol->dsos) {
93 LD_LOGE("dsolist_alloc failed,return NULL!");
94 internal_free(dsol);
95 dsol = NULL;
96 }
97 }
98 return dsol;
99 }
100
dsolist_realloc(dsolist * dsol)101 static void dsolist_realloc(dsolist *dsol)
102 {
103 if (!dsol) {
104 return;
105 }
106 size_t size = 2 * dsol->size;
107 if (size) {
108 struct dso **ds;
109 ds = (struct dso **)internal_realloc(dsol->dsos, size * (sizeof *dsol->dsos));
110 if (!ds) {
111 LD_LOGE("dsolist_realloc failed!");
112 return;
113 }
114 dsol->size = size;
115 dsol->dsos = ds;
116 }
117 return;
118 }
119
ns_alloc()120 ns_t *ns_alloc()
121 {
122 ns_t *nst = (ns_t *)internal_calloc(1, sizeof *nst);
123 nst->ns_dsos = dsolist_alloc();
124 if (!nst->ns_dsos) {
125 LD_LOGE("ns_alloc failed,return NULL!");
126 internal_free(nst);
127 nst = NULL;
128 }
129 return nst;
130 }
131
ns_free(ns_t * ns)132 void ns_free(ns_t *ns)
133 {
134 if (!ns) {
135 return;
136 }
137 if (ns->ns_dsos) {
138 internal_free(ns->ns_dsos);
139 ns->ns_dsos = NULL;
140 }
141 if (ns->ns_name) {
142 internal_free(ns->ns_name);
143 ns->ns_name = NULL;
144 }
145 if (ns->env_paths) {
146 internal_free(ns->env_paths);
147 ns->env_paths = NULL;
148 }
149 if (ns->lib_paths) {
150 internal_free(ns->lib_paths);
151 ns->lib_paths = NULL;
152 }
153 if (ns->asan_lib_paths) {
154 internal_free(ns->asan_lib_paths);
155 ns->asan_lib_paths = NULL;
156 }
157 strlist_free(ns->permitted_paths);
158 strlist_free(ns->asan_permitted_paths);
159 strlist_free(ns->allowed_libs);
160 nsinherits_free(ns->ns_inherits);
161 internal_free(ns);
162 }
163
ns_add_dso(ns_t * ns,struct dso * dso)164 void ns_add_dso(ns_t *ns, struct dso *dso)
165 {
166 if (!ns || !dso) {
167 return;
168 }
169 if (!ns->ns_dsos) {
170 ns->ns_dsos = dsolist_alloc();
171 }
172 if (!ns->ns_dsos) {
173 return;
174 }
175 if (ns->ns_dsos->num == ns->ns_dsos->size) {
176 /* if list is full, realloc size to double*/
177 dsolist_realloc(ns->ns_dsos);
178 }
179 if (ns->ns_dsos->num < ns->ns_dsos->size) {
180 /* realloc succ */
181 ns->ns_dsos->dsos[ns->ns_dsos->num] = dso;
182 ns->ns_dsos->num++;
183 }
184 return;
185 }
186
nslist_init()187 nslist *nslist_init()
188 {
189 g_ns_list.size = NSLIST_DEFAULT_SIZE;
190 g_ns_list.num = 0;
191 g_ns_list.nss = (ns_t **)internal_calloc(NSLIST_DEFAULT_SIZE, sizeof *g_ns_list.nss);
192 if (!g_ns_list.nss) {
193 LD_LOGE("nslist_init failed!");
194 return NULL;
195 }
196 return &g_ns_list;
197 }
198
nslist_realloc()199 static void nslist_realloc()
200 {
201 size_t size = 2 * g_ns_list.size;
202 if (size) {
203 ns_t **nss;
204 nss = (ns_t **)internal_realloc(g_ns_list.nss, size * (sizeof *g_ns_list.nss));
205 if (!nss) {
206 LD_LOGE("nslist_realloc failed!");
207 return;
208 }
209 g_ns_list.size = size;
210 g_ns_list.nss = nss;
211 }
212 return;
213 }
214
nslist_add_ns(ns_t * ns)215 void nslist_add_ns(ns_t *ns)
216 {
217 if (!ns) {
218 return;
219 }
220
221 if (g_ns_list.num == g_ns_list.size) {
222 /* if list is full, realloc size to double*/
223 nslist_realloc();
224 }
225 if (g_ns_list.num < g_ns_list.size) {
226 /* realloc succ */
227 g_ns_list.nss[g_ns_list.num] = ns;
228 g_ns_list.num++;
229 }
230 return;
231 }
232
get_default_ns()233 ns_t *get_default_ns()
234 {
235 return &g_ns_default;
236 }
237
238 /* set namespace attributes*/
ns_set_name(ns_t * ns,const char * name)239 void ns_set_name(ns_t *ns, const char *name)
240 {
241 if (!ns || !name) {
242 return;
243 }
244 if (ns->ns_name) internal_free(ns->ns_name);
245 ns->ns_name = ld_strdup(name);
246 strtrim(ns->ns_name);
247 LD_LOGD("ns_set_name ns_name:%{public}s.", ns->ns_name);
248 }
249
ns_set_env_paths(ns_t * ns,const char * env_paths)250 void ns_set_env_paths(ns_t *ns, const char *env_paths)
251 {
252 if (!ns) {
253 return;
254 }
255 if (ns->env_paths) internal_free(ns->env_paths);
256 if (env_paths) {
257 ns->env_paths = ld_strdup(env_paths);
258 strtrim(ns->env_paths);
259 } else {
260 ns->env_paths = NULL;
261 }
262 LD_LOGD("ns_set_env_paths ns[%{public}s] env_paths:%{public}s.", ns->ns_name, ns->env_paths);
263 }
264
ns_set_lib_paths(ns_t * ns,const char * lib_paths)265 void ns_set_lib_paths(ns_t *ns, const char *lib_paths)
266 {
267 if (!ns) {
268 return;
269 }
270 if (ns->lib_paths) internal_free(ns->lib_paths);
271 if (lib_paths) {
272 ns->lib_paths = ld_strdup(lib_paths);
273 strtrim(ns->lib_paths);
274 } else {
275 ns->lib_paths = NULL;
276 }
277 LD_LOGD("ns_set_lib_paths ns[%{public}s] lib_paths:%{public}s.", ns->ns_name, ns->lib_paths);
278 }
279
ns_set_asan_lib_paths(ns_t * ns,const char * asan_lib_paths)280 void ns_set_asan_lib_paths(ns_t *ns, const char *asan_lib_paths)
281 {
282 if (!ns) {
283 return;
284 }
285 if (ns->asan_lib_paths) {
286 internal_free(ns->asan_lib_paths);
287 }
288 if (asan_lib_paths) {
289 ns->asan_lib_paths = ld_strdup(asan_lib_paths);
290 strtrim(ns->asan_lib_paths);
291 } else {
292 ns->asan_lib_paths = NULL;
293 }
294 LD_LOGD("ns_set_asan_lib_paths ns[%{public}s] asan_lib_paths:%{public}s.", ns->ns_name, ns->asan_lib_paths);
295 }
296
ns_set_permitted_paths(ns_t * ns,const char * permitted_paths)297 void ns_set_permitted_paths(ns_t *ns, const char *permitted_paths)
298 {
299 if (!ns) {
300 return;
301 }
302 if (ns->permitted_paths) strlist_free(ns->permitted_paths);
303 ns->permitted_paths = strsplit(permitted_paths, ":");
304 LD_LOGD("ns_set_permitted_paths ns[%{public}s] permitted_paths:%{public}s.", ns->ns_name, permitted_paths);
305 }
306
ns_set_asan_permitted_paths(ns_t * ns,const char * asan_permitted_paths)307 void ns_set_asan_permitted_paths(ns_t *ns, const char *asan_permitted_paths)
308 {
309 if (!ns) {
310 return;
311 }
312 if (ns->asan_permitted_paths) {
313 strlist_free(ns->asan_permitted_paths);
314 }
315 ns->asan_permitted_paths = strsplit(asan_permitted_paths, ":");
316 LD_LOGD("ns_set_asan_permitted_paths ns[%{public}s] asan_permitted_paths:%{public}s.",
317 ns->ns_name,
318 asan_permitted_paths);
319 }
320
ns_set_separated(ns_t * ns,bool separated)321 void ns_set_separated(ns_t *ns, bool separated)
322 {
323 if (!ns) {
324 return;
325 }
326 ns->separated = separated;
327 LD_LOGD("ns_set_separated ns[%{public}s] separated:%{public}d.", ns->ns_name, ns->separated);
328 }
329
ns_set_allowed_libs(ns_t * ns,const char * allowed_libs)330 void ns_set_allowed_libs(ns_t *ns, const char *allowed_libs)
331 {
332 if (!ns) {
333 return;
334 }
335
336 if (ns->allowed_libs) strlist_free(ns->allowed_libs);
337 ns->allowed_libs = NULL;
338 if (allowed_libs) {
339 /* if setted and not empty, split to list. */
340 char *a_libs = ld_strdup(allowed_libs);
341 if (strtrim(a_libs) > 0) ns->allowed_libs = strsplit(a_libs, ":");
342 internal_free(a_libs);
343 }
344 LD_LOGD("ns_set_allowed_libs ns[%{public}s] allowed_libs:%{public}s.", ns->ns_name, allowed_libs);
345 }
346
find_ns_by_name(const char * ns_name)347 ns_t *find_ns_by_name(const char *ns_name)
348 {
349 if (!ns_name) {
350 return NULL;
351 }
352 if (strcmp(NS_DEFAULT_NAME, ns_name) == 0) {
353 LD_LOGD("find_ns_by_name return default namespace!");
354 return get_default_ns();
355 }
356 for (size_t i = 0; i < g_ns_list.num; i++) {
357 if (strcmp(g_ns_list.nss[i]->ns_name, ns_name) == 0) {
358 return g_ns_list.nss[i];
359 }
360 }
361 LD_LOGD("find_ns_by_name ns_name[%{public}s] failed,return NULL!", ns_name);
362 return NULL;
363 }
364
find_ns_inherit(ns_t * ns,ns_t * inherited)365 static ns_inherit *find_ns_inherit(ns_t *ns, ns_t *inherited)
366 {
367 if (!ns || !inherited) {
368 return NULL;
369 }
370 if (ns->ns_inherits) {
371 for (size_t i = 0; i < ns->ns_inherits->num; i++) {
372 if (ns->ns_inherits->inherits[i]->inherited_ns == inherited) return ns->ns_inherits->inherits[i];
373 }
374 }
375 LD_LOGD(
376 "find_ns_inherit ns[%{public}s] ns_inherited[%{public}s] failed,return NULL!", ns->ns_name, inherited->ns_name);
377 return NULL;
378 }
379
ns_add_inherit(ns_t * ns,ns_t * ns_inherited,const char * shared_libs)380 void ns_add_inherit(ns_t *ns, ns_t *ns_inherited, const char *shared_libs)
381 {
382 bool need_add = false;
383 if (!ns || !ns_inherited) {
384 return;
385 }
386
387 ns_inherit *inherit = find_ns_inherit(ns, ns_inherited);
388 if (!inherit) {
389 inherit = internal_calloc(1, sizeof *inherit);
390 if (!inherit) {
391 LD_LOGE("ns_add_inherit ns[%{public}s] ns_inherited[%{public}s] calloc failed!",
392 ns->ns_name,
393 ns_inherited->ns_name);
394 return;
395 }
396 inherit->inherited_ns = ns_inherited;
397 need_add = true;
398 LD_LOGD("ns_add_inherit ns[%{public}s] ns_inherited[%{public}s] need_add is true.",
399 ns->ns_name,
400 ns_inherited->ns_name);
401 }
402
403 if (inherit->shared_libs) {
404 strlist_free(inherit->shared_libs);
405 inherit->shared_libs = NULL;
406 }
407
408 /* if setted and not empty, split to list. */
409 if (shared_libs) {
410 char *s_libs = ld_strdup(shared_libs);
411 if (strtrim(s_libs) > 0) inherit->shared_libs = strsplit(shared_libs, ":");
412 internal_free(s_libs);
413 }
414
415 if (!need_add) {
416 LD_LOGD(
417 "ns_add_inherit ns[%{public}s] ns_inherited[%{public}s] not need_add!", ns->ns_name, ns_inherited->ns_name);
418 return;
419 }
420
421 if (!ns->ns_inherits) {
422 ns->ns_inherits = nsinherits_alloc();
423 }
424
425 if (!ns->ns_inherits) {
426 if (inherit->shared_libs) strlist_free(inherit->shared_libs);
427 LD_LOGD("ns_add_inherit ns[%{public}s] ns_inherited[%{public}s] nsinherits_alloc failed!",
428 ns->ns_name,
429 ns_inherited->ns_name);
430 internal_free(inherit);
431 return;
432 }
433
434 if (ns->ns_inherits->num == ns->ns_inherits->size) {
435 /* if list is full, realloc size to double*/
436 LD_LOGD("ns_add_inherit ns[%{public}s] ns_inherited[%{public}s] list is full, realloc size to double!",
437 ns->ns_name,
438 ns_inherited->ns_name);
439 nsinherits_realloc(ns->ns_inherits);
440 }
441
442 if (ns->ns_inherits->num < ns->ns_inherits->size) {
443 /* realloc succ */
444 LD_LOGD("ns_add_inherit ns[%{public}s] ns_inherited[%{public}s] realloc success!",
445 ns->ns_name,
446 ns_inherited->ns_name);
447 ns->ns_inherits->inherits[ns->ns_inherits->num] = inherit;
448 ns->ns_inherits->num++;
449 } else {
450 /* realloc failed */
451 LD_LOGD("ns_add_inherit ns[%{public}s] ns_inherited[%{public}s] realloc failed!",
452 ns->ns_name,
453 ns_inherited->ns_name);
454 if (inherit->shared_libs) strlist_free(inherit->shared_libs);
455 internal_free(inherit);
456 }
457 return;
458 }
459
460 /* check library's pathname if accessible in this namespace */
is_accessible(ns_t * ns,const char * lib_pathname,bool is_asan,bool check_inherited)461 bool is_accessible(ns_t *ns, const char *lib_pathname, bool is_asan, bool check_inherited)
462 {
463 if (check_inherited && !ns->separated) {
464 LD_LOGD("is_accessible ns [%{public}s] is not separated, return true.", ns->ns_name);
465 return true;
466 }
467 if (ns->allowed_libs) {
468 char *shortname = strrchr(lib_pathname, '/');
469 if (shortname) {
470 shortname += 1;
471 size_t i = 0;
472 for (; i < ns->allowed_libs->num; i++) {
473 if (strcmp(shortname, ns->allowed_libs->strs[i]) == 0) {
474 break;
475 }
476 }
477 if (i >= ns->allowed_libs->num) {
478 LD_LOGD("is_accessible ns [%{public}s] lib_pathname [%{public}s] is not in allowed_libs, return false.",
479 ns->ns_name,
480 lib_pathname);
481 return false;
482 }
483 }
484 }
485 strlist *paths;
486 if (ns->env_paths && (paths = strsplit(ns->env_paths, ":"))) {
487 for (size_t i = 0; i < paths->num; i++) {
488 size_t len = strlen(paths->strs[i]);
489 if (strncmp(lib_pathname, paths->strs[i], len) == 0 &&
490 lib_pathname[len] == '/' &&
491 !strchr(lib_pathname + len + 1, '/')) {
492 LD_LOGD("is_accessible ns [%{public}s] lib_pathname [%{public}s] in env_paths, return true.",
493 ns->ns_name,
494 lib_pathname);
495 strlist_free(paths);
496 return true;
497 }
498 }
499 strlist_free(paths);
500 }
501
502 if (is_asan) {
503 if (check_asan_path(ns, lib_pathname)) {
504 LD_LOGD("is_accessible ns [%{public}s] lib_pathname [%{public}s] check_asan_path success, return true.",
505 ns->ns_name,
506 lib_pathname);
507 return true;
508 }
509 }
510
511 if (ns->lib_paths && (paths = strsplit(ns->lib_paths, ":"))) {
512 for (size_t i = 0; i < paths->num; i++) {
513 size_t len = strlen(paths->strs[i]);
514 if (strncmp(lib_pathname, paths->strs[i], len) == 0 &&
515 lib_pathname[len] == '/' &&
516 !strchr(lib_pathname + len + 1, '/')) {
517 strlist_free(paths);
518 LD_LOGD("is_accessible ns [%{public}s] lib_pathname [%{public}s] in lib_paths, return true.",
519 ns->ns_name,
520 lib_pathname);
521 return true;
522 }
523 }
524 strlist_free(paths);
525 }
526
527 if (ns->permitted_paths) {
528 for (size_t i = 0; i < ns->permitted_paths->num; i++) {
529 size_t len = strlen(ns->permitted_paths->strs[i]);
530 if (strncmp(lib_pathname, ns->permitted_paths->strs[i], len) == 0 &&
531 lib_pathname[len] == '/') {
532 LD_LOGD("is_accessible ns [%{public}s] lib_pathname [%{public}s] in permitted_paths, return true.",
533 ns->ns_name,
534 lib_pathname);
535 return true;
536 }
537 }
538 }
539 return false;
540 }
541
check_asan_path(ns_t * ns,const char * lib_pathname)542 bool check_asan_path(ns_t *ns, const char *lib_pathname)
543 {
544 strlist *paths;
545 if (ns->asan_lib_paths && (paths = strsplit(ns->asan_lib_paths, ":"))) {
546 for (size_t i = 0; i < paths->num; i++) {
547 size_t len = strlen(paths->strs[i]);
548 if (strncmp(lib_pathname, paths->strs[i], len) == 0 &&
549 lib_pathname[len] == '/' &&
550 !strchr(lib_pathname + len + 1, '/')) {
551 strlist_free(paths);
552 LD_LOGD("check_asan_path ns [%{public}s] lib_pathname [%{public}s] in asan_lib_paths, return true.",
553 ns->ns_name,
554 lib_pathname);
555 return true;
556 }
557 }
558 strlist_free(paths);
559 }
560 if (ns->asan_permitted_paths) {
561 for (size_t i = 0; i < ns->asan_permitted_paths->num; i++) {
562 size_t len = strlen(ns->asan_permitted_paths->strs[i]);
563 if (strncmp(lib_pathname, ns->asan_permitted_paths->strs[i], len) == 0 &&
564 lib_pathname[len] == '/') {
565 LD_LOGD(
566 "check_asan_path ns [%{public}s] lib_pathname [%{public}s] in asan_permitted_paths, return true.",
567 ns->ns_name,
568 lib_pathname);
569 return true;
570 }
571 }
572 }
573 LD_LOGD(
574 "check_asan_path ns [%{public}s] lib_pathname [%{public}s] failed, return false.", ns->ns_name, lib_pathname);
575 return false;
576 }
577
is_sharable(ns_inherit * inherit,const char * lib_name)578 bool is_sharable(ns_inherit *inherit, const char *lib_name)
579 {
580 if (inherit && lib_name && inherit->shared_libs) {
581 for (size_t i = 0; i < inherit->shared_libs->num; i++) {
582 if (strcmp(inherit->shared_libs->strs[i], lib_name) == 0) {
583 LD_LOGD("is_sharable inherit [%{public}s] lib_name [%{public}s] found, return true.",
584 inherit->inherited_ns->ns_name,
585 lib_name);
586 return true;
587 }
588 }
589 LD_LOGD("is_sharable inherit [%{public}s] lib_name [%{public}s] not found, return false.",
590 inherit->inherited_ns->ns_name,
591 lib_name);
592 return false;
593 }
594 LD_LOGD("is_sharable shared_libs not config, return true.");
595 return true;
596 }
597