提交 81cce902 编写于 作者: G ganlan

fix ns invoke issue

Signed-off-by: Nganlan <tony.gan@huawei.com>
上级 fbfed933
......@@ -17,6 +17,8 @@ group("dlns_test") {
testonly = true
deps = [
":dlns_dlopen_test",
":dlns_dlsym_dep_a",
":dlns_dlsym_test",
":dlns_inherit_test",
":dlns_separated_test",
":dlns_set_fun_test",
......@@ -83,3 +85,58 @@ ohos_unittest("dlns_special_scene_test") {
sources = [ "dlns_special_scene.c" ]
configs = [ "//third_party/musl/libc-test/src/common:config_runtest" ]
}
ohos_unittest("dlns_dlsym_test") {
module_out_path = "libc-test/src/functionalext/dlns"
include_dirs = [
"../common",
"//third_party/musl/porting/linux/user/include",
"//third_party/musl/libc-test/src/common",
]
sources = [ "dlns_dlsym.c" ]
configs = [ "//third_party/musl/libc-test/src/common:config_runtest" ]
}
ohos_shared_library("dlns_dlsym_dep_c") {
include_dirs = [ "." ]
sources = [ "dlns_dlsym_dep_c.c" ]
output_name = "dlns_dlsym_dep_c"
output_extension = "so"
subsystem_name = "musl"
part_name = "libc-test-lib"
}
ohos_shared_library("dlns_dlsym_dep_b") {
include_dirs = [ "." ]
sources = [ "dlns_dlsym_dep_b.c" ]
output_name = "dlns_dlsym_dep_b"
output_extension = "so"
deps = [ ":dlns_dlsym_dep_c" ]
subsystem_name = "musl"
part_name = "libc-test-lib"
}
ohos_shared_library("dlns_dlsym_dep_a") {
include_dirs = [ "." ]
sources = [ "dlns_dlsym_dep_a.c" ]
output_name = "dlns_dlsym_dep_a"
output_extension = "so"
deps = [ ":dlns_dlsym_dep_b" ]
subsystem_name = "musl"
part_name = "libc-test-lib"
}
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <dlfcn.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include "dlns_test.h"
#include "functionalext.h"
const char *LIB_NAME_A = "libdlns_dlsym_dep_a.so";
const char *LIB_NAME_B = "libdlns_dlsym_dep_b.so";
const char *LIB_NAME_C = "libdlns_dlsym_dep_c.so";
static inline void dlns_dlsym_0100_init_ns(Dl_namespace *dlnsA, Dl_namespace *dlnsB, Dl_namespace *dlnsC)
{
dlns_init(dlnsA, "dlns_dlsym_0100_A");
dlns_init(dlnsB, "dlns_dlsym_0100_B");
dlns_init(dlnsC, "dlns_dlsym_0100_C");
EXPECT_EQ(__FUNCTION__, dlns_create(dlnsA, pathA), EOK);
EXPECT_EQ(__FUNCTION__, dlns_create(dlnsB, pathB), EOK);
EXPECT_EQ(__FUNCTION__, dlns_create(dlnsC, pathC), EOK);
EXPECT_EQ(__FUNCTION__, dlns_inherit(dlnsB, dlnsC, NULL), EOK);
EXPECT_EQ(__FUNCTION__, dlns_inherit(dlnsA, dlnsB, NULL), EOK);
}
static inline void close_so(void* handle)
{
if (handle) {
dlclose(handle);
}
}
/**
* @tc.name : dlns_dlsym_0100
* @tc.desc : Call the dlsym interface to load libA,libB,libC dynamic library.
* @tc.level : Level1
*/
static void dlns_dlsym_0100(void)
{
Dl_namespace dlnsA, dlnsB, dlnsC;
dlns_dlsym_0100_init_ns(&dlnsA, &dlnsB, &dlnsC);
void* handle_c = dlopen_ns(&dlnsC, LIB_NAME_C, RTLD_NOW);
EXPECT_PTRNE(__FUNCTION__, handle_c, NULL);
if (handle_c == NULL) {
return;
}
void* handle_b = dlopen_ns(&dlnsB, LIB_NAME_B, RTLD_NOW);
EXPECT_PTRNE(__FUNCTION__, handle_b, NULL);
if (handle_b == NULL) {
close_so(handle_c);
return;
}
void* handle_a = dlopen_ns(&dlnsA, LIB_NAME_A, RTLD_NOW);
EXPECT_PTRNE(__FUNCTION__, handle_a, NULL);
if (handle_a == NULL) {
close_so(handle_b);
close_so(handle_c);
return;
}
int(* test_a)(void) = dlsym(handle_a, "test");
EXPECT_PTRNE(__FUNCTION__, test_a, NULL);
if (test_a) {
EXPECT_EQ(__FUNCTION__, test_result_1, test_a());
}
int(* test_b)(void) = dlsym(handle_a, "test_b");
EXPECT_PTRNE(__FUNCTION__, test_b, NULL);
if (test_b) {
EXPECT_EQ(__FUNCTION__, test_result_2, test_b());
}
int(* test_c)(void) = dlsym(handle_c, "test");
EXPECT_PTRNE(__FUNCTION__, test_c, NULL);
if (test_c) {
EXPECT_EQ(__FUNCTION__, test_result_3, test_c());
}
int(* test_d)(void) = dlsym(handle_c, "test_c");
EXPECT_PTRNE(__FUNCTION__, test_d, NULL);
if (test_d) {
EXPECT_EQ(__FUNCTION__, test_result_4, test_d());
}
int(* test_e)(void) = dlsym(handle_a, "test_c");
EXPECT_PTREQ(__FUNCTION__, test_e, NULL);
close_so(handle_c);
close_so(handle_b);
close_so(handle_a);
}
TEST_FUN G_Fun_Array[] = {
dlns_dlsym_0100,
};
int main(void)
{
int num = sizeof(G_Fun_Array)/sizeof(TEST_FUN);
for (int pos = 0; pos < num; ++pos) {
G_Fun_Array[pos]();
}
return t_status;
}
\ No newline at end of file
/**
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "dlns_dlsym_dep_b.h"
#include "dlns_test.h"
int test(void)
{
test_b();
return test_result_1;
}
\ No newline at end of file
/**
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "dlns_dlsym_dep_b.h"
#include "dlns_dlsym_dep_c.h"
#include "dlns_test.h"
int test_b(void)
{
test_c();
return test_result_2;
}
\ No newline at end of file
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef DLNS_DLSYM_DEP_B_H
#define DLNS_DLSYM_DEP_B_H
int test_b(void);
#endif
\ No newline at end of file
/**
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "dlns_dlsym_dep_c.h"
#include "dlns_test.h"
int test(void)
{
return test_result_3;
}
int test_c(void)
{
return test_result_4;
}
\ No newline at end of file
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef DLNS_DLSYM_DEP_C_H
#define DLNS_DLSYM_DEP_C_H
int test_c(void);
#endif
\ No newline at end of file
......@@ -25,6 +25,7 @@ static const char* dllNamePath2 = "/data/tests/libc-test/src/functionalext/dlns/
static const char* errPath_ns = "src/test";
static const char* sharedLib = "sharedlibtest.so";
static const char* pathA = "/data/tests/libc-test/src/functionalext/dlns/A";
static const char* pathB = "/data/tests/libc-test/src/functionalext/dlns/B";
static const char* pathC = "/data/tests/libc-test/src/functionalext/dlns/C";
static const char* pathD = "/data/tests/libc-test/src/functionalext/dlns/D";
......@@ -43,4 +44,9 @@ static const char* dllName_inh_011 = "inherit_1100.so";
typedef void(*TEST_FUN)(void);
static const int EOK = 0;
static const int test_result_1 = 1;
static const int test_result_2 = 2;
static const int test_result_3 = 3;
static const int test_result_4 = 4;
#endif
\ No newline at end of file
......@@ -13,6 +13,8 @@
functionalext_complex_list = [
"dlns_dlopen",
"dlns_dlsym",
"dlns_dlsym_dep_a",
"dlns_set_fun",
"dlns_inherit",
"dlns_separated",
......
......@@ -54,6 +54,8 @@ static void error(const char *, ...);
#define INVALID_FD_INHIBIT_FURTHER_SEARCH (-2)
#endif
#define PARENTS_BASE_CAPACITY 8
struct debug {
int ver;
void *head;
......@@ -144,6 +146,9 @@ struct dso {
size_t *got;
} *funcdescs;
size_t *got;
struct dso **parents;
size_t parents_count;
size_t parents_capacity;
char buf[];
};
......@@ -626,6 +631,77 @@ static Sym *gnu_lookup_filtered(uint32_t h1, uint32_t *hashtab, struct dso *dso,
return gnu_lookup(h1, hashtab, dso, verinfo);
}
static bool check_sym_accessible(struct dso *dso, ns_t *ns)
{
if (!dso || !dso->namespace || !ns) {
return false;
}
if (dso->namespace == ns) {
return true;
}
for (int i = 0; i < dso->parents_count; i++) {
if (dso->parents[i]->namespace == ns) {
return true;
}
}
return false;
}
static int find_dso_parent(struct dso *p, struct dso *target)
{
int index = -1;
for (int i = 0; i < p->parents_count; i++) {
if (p->parents[i] == target) {
index = i;
break;
}
}
return index;
}
static void add_dso_parent(struct dso *p, struct dso *parent)
{
int index = find_dso_parent(p, parent);
if (index != -1) {
return;
}
if (p->parents_count + 1 > p->parents_capacity) {
if (p->parents_capacity == 0) {
p->parents = (struct dso **)malloc(sizeof(struct dso *) * PARENTS_BASE_CAPACITY);
if (!p->parents) {
return;
}
p->parents_capacity = PARENTS_BASE_CAPACITY;
} else {
struct dso ** realloced = (struct dso **)realloc(
p->parents, sizeof(struct dso *) * (p->parents_capacity + PARENTS_BASE_CAPACITY));
if (!realloced) {
return;
}
p->parents = realloced;
p->parents_capacity += PARENTS_BASE_CAPACITY;
}
}
p->parents[p->parents_count] = parent;
p->parents_count++;
}
static void remove_dso_parent(struct dso *p, struct dso *parent)
{
int index = find_dso_parent(p, parent);
if (index == -1) {
return;
}
int i;
for (i = 0; i < index; i++) {
p->parents[i] = p->parents[i];
}
for (i = index; i < p->parents_count - 1; i++) {
p->parents[i] = p->parents[i + 1];
}
p->parents_count--;
}
#define OK_TYPES (1<<STT_NOTYPE | 1<<STT_OBJECT | 1<<STT_FUNC | 1<<STT_COMMON | 1<<STT_TLS)
#define OK_BINDS (1<<STB_GLOBAL | 1<<STB_WEAK | 1<<STB_GNU_UNIQUE)
......@@ -636,7 +712,7 @@ static Sym *gnu_lookup_filtered(uint32_t h1, uint32_t *hashtab, struct dso *dso,
#if defined(__GNUC__)
__attribute__((always_inline))
#endif
static inline struct symdef find_sym2(struct dso *dso, struct verinfo *verinfo, int need_def, int use_deps)
static inline struct symdef find_sym2(struct dso *dso, struct verinfo *verinfo, int need_def, int use_deps, ns_t *ns)
{
uint32_t h = 0, gh = gnu_hash(verinfo->s), gho = gh / (8*sizeof(size_t)), *ght;
size_t ghm = 1ul << gh % (8*sizeof(size_t));
......@@ -644,6 +720,9 @@ static inline struct symdef find_sym2(struct dso *dso, struct verinfo *verinfo,
struct dso **deps = use_deps ? dso->deps : 0;
for (; dso; dso=use_deps ? *deps++ : dso->syms_next) {
Sym *sym;
if (ns && !check_sym_accessible(dso, ns)) {
continue;
}
if ((ght = dso->ghashtab)) {
sym = gnu_lookup_filtered(gh, ght, dso, verinfo, gho, ghm);
} else {
......@@ -670,7 +749,7 @@ static inline struct symdef find_sym2(struct dso *dso, struct verinfo *verinfo,
static struct symdef find_sym(struct dso *dso, const char *s, int need_def)
{
struct verinfo verinfo = { .s = s, .v = "", .verneed = dso->verneed };
return find_sym2(dso, &verinfo, need_def, 0);
return find_sym2(dso, &verinfo, need_def, 0, NULL);
}
static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stride)
......@@ -723,9 +802,10 @@ static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stri
sym = syms + sym_index;
name = strings + sym->st_name;
ctx = type==REL_COPY ? head->syms_next : head;
struct verinfo vinfo = { .s = name, .v = "", .verneed = dso->verneed };
def = (sym->st_info>>4) == STB_LOCAL
? (struct symdef){ .dso = dso, .sym = sym }
: find_sym(ctx, name, type==REL_PLT);
: find_sym2(ctx, &vinfo, type==REL_PLT, 0, dso->namespace);
if (!def.sym && (sym->st_shndx != SHN_UNDEF
|| sym->st_info>>4 != STB_WEAK)) {
if (dso->lazy && (type==REL_PLT || type==REL_GOT)) {
......@@ -1678,6 +1758,9 @@ static void load_direct_deps(struct dso *p, ns_t *namespace, struct reserved_add
}
p->deps[cnt] = 0;
p->ndeps_direct = cnt;
for (i = 0; i < p->ndeps_direct; i++) {
add_dso_parent(p->deps[i], p);
}
}
static void load_deps(struct dso *p, struct reserved_address_params *reserved_params)
......@@ -2579,9 +2662,17 @@ static void *dlopen_impl(
free(p->funcdescs);
if (p->rpath != p->rpath_orig)
free(p->rpath);
if (p->deps) {
for (int i = 0; i < p->ndeps_direct; i++) {
remove_dso_parent(p->deps[i], p);
}
}
free(p->deps);
dlclose_ns(p);
unmap_library(p);
if (p->parents) {
free(p->parents);
}
free(p);
}
free(ctor_queue);
......@@ -2785,12 +2876,12 @@ int dlns_get(const char *name, Dl_namespace *dlns)
void *dlopen_ns(Dl_namespace *dlns, const char *file, int mode)
{
const void *caller_addr = __builtin_return_address(0);
LD_LOGI("dlopen_ns file:%{public}s, mode:%{public}x , caller_addr:%{public}p , dlns->name:%{public}s.",
file,
mode,
caller_addr,
dlns->name);
return dlopen_impl(file, mode, dlns->name, caller_addr, NULL);
LD_LOGI("dlopen_ns file:%{public}s, mode:%{public}x , caller_addr:%{public}p , dlns->name:%{public}s.",
file,
mode,
caller_addr,
dlns->name);
return dlopen_impl(file, mode, dlns->name, caller_addr, NULL);
}
int dlns_create2(Dl_namespace *dlns, const char *lib_path, int flags)
......@@ -2930,18 +3021,31 @@ static void *addr2dso(size_t a)
static void *do_dlsym(struct dso *p, const char *s, const char *v, void *ra)
{
int use_deps = 0;
bool ra2dso = false;
ns_t *ns = NULL;
struct dso *caller = NULL;
if (p == head || p == RTLD_DEFAULT) {
p = head;
ra2dso = true;
} else if (p == RTLD_NEXT) {
p = addr2dso((size_t)ra);
if (!p) p=head;
p = p->next;
ra2dso = true;
} else if (__dl_invalid_handle(p)) {
return 0;
} else
} else {
use_deps = 1;
ns = p->namespace;
}
if (ra2dso) {
caller = (struct dso *)addr2dso((size_t)ra);
if (caller && caller->namespace) {
ns = caller->namespace;
}
}
struct verinfo verinfo = { .s = s, .v = v, .verneed = NULL };
struct symdef def = find_sym2(p, &verinfo, 0, use_deps);
struct symdef def = find_sym2(p, &verinfo, 0, use_deps, ns);
if (!def.sym) {
error("Symbol not found: %s, version: %s", s, strlen(v) > 0 ? v : "null");
return 0;
......@@ -3033,9 +3137,17 @@ static int do_dlclose(struct dso *p)
if (p->lazy != NULL)
free(p->lazy);
if (p->deps) {
for (int i = 0; i < p->ndeps_direct; i++) {
remove_dso_parent(p->deps[i], p);
}
}
if (p->deps != no_deps)
free(p->deps);
unmap_library(p);
if (p->parents) {
free(p->parents);
}
free(p);
return 0;
......@@ -3335,12 +3447,12 @@ int dlns_set_namespace_allowed_libs(const char * name, const char * allowed_libs
int handle_asan_path_open(int fd, const char *name, ns_t *namespace, char *buf, size_t buf_size)
{
LD_LOGD("handle_asan_path_open fd:%{public}d, name:%{public}s , namespace:%{public}p , buf:%{public}s.",
fd,
name,
namespace,
buf);
int fd_tmp = fd;
LD_LOGD("handle_asan_path_open fd:%{public}d, name:%{public}s , namespace:%{public}p , buf:%{public}s.",
fd,
name,
namespace,
buf);
int fd_tmp = fd;
if (fd == -1 && (namespace->asan_lib_paths || namespace->lib_paths)) {
if (namespace->lib_paths && namespace->asan_lib_paths) {
size_t newlen = strlen(namespace->asan_lib_paths) + strlen(namespace->lib_paths) + 2;
......@@ -3354,14 +3466,14 @@ int handle_asan_path_open(int fd, const char *name, ns_t *namespace, char *buf,
free(new_lib_paths);
} else if (namespace->asan_lib_paths) {
fd_tmp = path_open(name, namespace->asan_lib_paths, buf, buf_size);
LD_LOGD("handle_asan_path_open path_open asan_lib_paths:%{public}s ,fd: %{public}d.",
namespace->asan_lib_paths,
fd_tmp);
} else {
LD_LOGD("handle_asan_path_open path_open asan_lib_paths:%{public}s ,fd: %{public}d.",
namespace->asan_lib_paths,
fd_tmp);
} else {
fd_tmp = path_open(name, namespace->lib_paths, buf, buf_size);
LD_LOGD(
"handle_asan_path_open path_open lib_paths:%{public}s ,fd: %{public}d.", namespace->lib_paths, fd_tmp);
}
LD_LOGD(
"handle_asan_path_open path_open lib_paths:%{public}s ,fd: %{public}d.", namespace->lib_paths, fd_tmp);
}
}
return fd_tmp;
}
......@@ -3376,10 +3488,10 @@ void* dlopen_ext(const char *file, int mode, const dl_extinfo *extinfo)
}
const void *caller_addr = __builtin_return_address(0);
LD_LOGI("dlopen_ext file:%{public}s, mode:%{public}x , caller_addr:%{public}p , extinfo->flag:%{public}x",
file,
mode,
caller_addr,
extinfo ? extinfo->flag : 0);
file,
mode,
caller_addr,
extinfo ? extinfo->flag : 0);
return dlopen_impl(file, mode, NULL, caller_addr, extinfo);
}
......@@ -4010,10 +4122,10 @@ static void preload_direct_deps(struct dso *p, ns_t *namespace, struct loadtasks
if (!load_library_header(task)) {
free_task(task);
task = NULL;
LD_LOGE("Error loading shared library %{public}s: (needed by %{public}s)",
p->strings + p->dynv[i + 1],
p->name);
error("Error loading shared library %s: %m (needed by %s)",
LD_LOGE("Error loading shared library %{public}s: (needed by %{public}s)",
p->strings + p->dynv[i + 1],
p->name);
error("Error loading shared library %s: %m (needed by %s)",
p->strings + p->dynv[i + 1], p->name);
if (runtime) {
longjmp(*rtld_fail, 1);
......@@ -4030,6 +4142,9 @@ static void preload_direct_deps(struct dso *p, ns_t *namespace, struct loadtasks
}
p->deps[cnt] = 0;
p->ndeps_direct = cnt;
for (i = 0; i < p->ndeps_direct; i++) {
add_dso_parent(p->deps[i], p);
}
}
static void unmap_preloaded_sections(struct loadtasks *tasks)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册