• 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 
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