提交 20910486 编写于 作者: D dhy308 提交者: Gitee

Merge branch 'master' of gitee.com:openharmony/third_party_musl into release_sigchain_0113

Issue: I6AEEI
Test: Build & Boot Devices
Signed-off-by: Ndhy308 <tony.gan@huawei.com>
# Copyright (c) 2023 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.
import("../../../test_template.gni")
group("ldso_cfi_test") {
testonly = true
deps = [
":ldso_cfi_check",
":ldso_cfi_test_lib",
]
}
ohos_executable("ldso_cfi_check") {
subsystem_name = "musl"
part_name = "libc-test"
include_dirs = [
"../common",
"//third_party/musl/porting/linux/user/include",
"//third_party/musl/porting/linux/user/ldso",
"//third_party/musl/libc-test/src/common",
]
sources = [ "ldso_cfi_check.c" ]
configs = [ "//third_party/musl/libc-test/src/common:config_runtest" ]
}
ohos_shared_library("ldso_cfi_test_lib") {
include_dirs = [ "." ]
sources = [ "ldso_cfi_test_lib.c" ]
output_name = "ldso_cfi_test_lib"
output_extension = "so"
subsystem_name = "musl"
part_name = "libc-test-lib"
}
/**
* Copyright (c) 2023 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 <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <sys/wait.h>
#include "functionalext.h"
#define LIB_PATH "/data/tests/libc-test/src/libldso_cfi_test_lib.so"
struct dso {
char *mock;
unsigned char *map;
size_t map_len;
};
extern int init_cfi_shadow(struct dso *dso_list, struct dso *ldso);
extern int map_dso_to_cfi_shadow(struct dso *dso);
extern void unmap_dso_from_cfi_shadow(struct dso *dso);
extern void __cfi_slowpath(uint64_t CallSiteTypeId, void *Ptr);
extern void __cfi_slowpath_diag(uint64_t CallSiteTypeId, void *Ptr, void *DiagData);
typedef void(*TEST_FUN)(void);
typedef size_t (*GET_COUNT)();
typedef uint64_t (*GET_TP_ID)();
typedef void* (*GET_LAST_ADDR)();
typedef void* (*GET_LAST_DIAG)();
typedef void* (*GET_GL_ADDR)();
typedef void (*CFI_CHECK)();
typedef char* (*BUF_CHECK)();
GET_COUNT get_count = NULL;
GET_TP_ID get_type_id = NULL;
GET_LAST_ADDR get_address = NULL;
GET_LAST_DIAG get_diag = NULL;
GET_GL_ADDR get_global_address = NULL;
CFI_CHECK cfi_check = NULL;
BUF_CHECK buf_check = NULL;
static void test_func() {}
/**
* @tc.name : cfi_init_test_0001
* @tc.desc : If no dso while initializing the CFI shadow, do nothing and return true.
* @tc.level : Level 1
*/
void cfi_init_test_0001(void)
{
printf("["__FILE__"][Line: %d][%s]: entry\n", __LINE__, __func__);
EXPECT_EQ("cfi_init_test_0001", init_cfi_shadow(NULL, NULL), 0);
}
/**
* @tc.name : cfi_init_test_0002
* @tc.desc : If dso is NULL while mapping to the CFI shadow, do nothing and return true.
* @tc.level : Level 2
*/
void cfi_init_test_0002(void)
{
printf("["__FILE__"][Line: %d][%s]: entry\n", __LINE__, __func__);
EXPECT_EQ("cfi_init_test_0002", map_dso_to_cfi_shadow(NULL), 0);
}
/**
* @tc.name : cfi_init_test_0003
* @tc.desc : If dso is NULL while unmapping from the CFI shadow, do nothing.
* @tc.level : Level 2
*/
void cfi_init_test_0003(void)
{
printf("["__FILE__"][Line: %d][%s]: entry\n", __LINE__, __func__);
unmap_dso_from_cfi_shadow(NULL);
}
/**
* @tc.name : cfi_slowpath_function_test_0002
* @tc.desc : Loading a dso that contains __cfi_check() symbol, call the __cfi_slowpath() function with
* address inside the DSO, the __cfi_check() function is called.
* @tc.level : Level 1
*/
void cfi_slowpath_function_test_0002(void)
{
printf("["__FILE__"][Line: %d][%s]: entry\n", __LINE__, __func__);
uint64_t expected_call_site_type_id = 20;
void* handle = dlopen(LIB_PATH, RTLD_LAZY);
EXPECT_PTRNE("cfi_slowpath_function_test_0002", handle, NULL);
*(void **)(&get_count) = dlsym(handle, "get_count");
*(void **)(&get_type_id) = dlsym(handle, "get_type_id");
*(void **)(&get_address) = dlsym(handle, "get_address");
*(void **)(&get_diag) = dlsym(handle, "get_diag");
*(void **)(&get_global_address) = dlsym(handle, "get_global_address");
size_t count = (*get_count)();
__cfi_slowpath(expected_call_site_type_id, (*get_global_address)());
EXPECT_EQ("cfi_slowpath_function_test_0002", expected_call_site_type_id, (*get_type_id)());
EXPECT_EQ("cfi_slowpath_function_test_0002", (*get_global_address)(), (*get_address)());
EXPECT_EQ("cfi_slowpath_function_test_0002", NULL, (*get_diag)());
EXPECT_EQ("cfi_slowpath_function_test_0002", ++count, (*get_count)());
dlclose(handle);
printf("["__FILE__"][Line: %d][%s]: end\n", __LINE__, __func__);
}
/**
* @tc.name : cfi_slowpath_function_test_0003
* @tc.desc : Loading a dso that contains __cfi_check() symbol, call the __cfi_slowpath() function with
* address belongs to other dso that does not enable Cross-DSO, the __cfi_check() function is
* not called.
* @tc.level : Level 1
*/
void cfi_slowpath_function_test_0003(void)
{
printf("["__FILE__"][Line: %d][%s]: entry\n", __LINE__, __func__);
uint64_t expected_call_site_type_id = 30;
uint64_t unexpected_call_site_type_id = 40;
void* handle = dlopen(LIB_PATH, RTLD_LAZY);
EXPECT_PTRNE("cfi_slowpath_function_test_0003", handle, NULL);
*(void **)(&get_count) = dlsym(handle, "get_count");
*(void **)(&get_type_id) = dlsym(handle, "get_type_id");
*(void **)(&get_address) = dlsym(handle, "get_address");
*(void **)(&get_diag) = dlsym(handle, "get_diag");
*(void **)(&get_global_address) = dlsym(handle, "get_global_address");
__cfi_slowpath(expected_call_site_type_id, (*get_global_address)());
size_t count = (*get_count)();
__cfi_slowpath(unexpected_call_site_type_id, (void*)(&test_func));
EXPECT_EQ("cfi_slowpath_function_test_0003", expected_call_site_type_id, (*get_type_id)());
EXPECT_EQ("cfi_slowpath_function_test_0003", (*get_global_address)(), (*get_address)());
EXPECT_EQ("cfi_slowpath_function_test_0003", NULL, (*get_diag)());
EXPECT_EQ("cfi_slowpath_function_test_0003", count, (*get_count)());
dlclose(handle);
printf("["__FILE__"][Line: %d][%s]: end\n", __LINE__, __func__);
}
/**
* @tc.name : cfi_slowpath_function_test_0004
* @tc.desc : Calling __cfi_slowpath() with target_addr = NULL
* @tc.level : Level 2
*/
void cfi_slowpath_function_test_0004(void)
{
printf("["__FILE__"][Line: %d][%s]: entry\n", __LINE__, __func__);
uint64_t call_site_type_id = 30;
void* handle = dlopen(LIB_PATH, RTLD_LAZY);
EXPECT_PTRNE("cfi_slowpath_function_test_0004", handle, NULL);
*(void **)(&get_count) = dlsym(handle, "get_count");
size_t count = (*get_count)();
__cfi_slowpath(call_site_type_id, NULL);
EXPECT_EQ("cfi_slowpath_function_test_0004", count, (*get_count)());
dlclose(handle);
printf("["__FILE__"][Line: %d][%s]: end\n", __LINE__, __func__);
}
/**
* @tc.name : cfi_slowpath_function_test_0005
* @tc.desc : Loading a dso that contains __cfi_check() symbol, call the __cfi_slowpath() function with
* invalid address, coredump happened.
* @tc.level : Level 2
*/
void cfi_slowpath_function_test_0005(void)
{
printf("["__FILE__"][Line: %d][%s]: entry\n", __LINE__, __func__);
uint64_t call_site_type_id = 30;
void* handle = dlopen(LIB_PATH, RTLD_LAZY);
EXPECT_PTRNE("cfi_slowpath_function_test_0005", handle, NULL);
*(void **)(&get_count) = dlsym(handle, "get_count");
*(void **)(&get_type_id) = dlsym(handle, "get_type_id");
*(void **)(&get_address) = dlsym(handle, "get_address");
*(void **)(&get_diag) = dlsym(handle, "get_diag");
*(void **)(&get_global_address) = dlsym(handle, "get_global_address");
size_t count = (*get_count)();
int status;
pid_t pid;
pid = fork();
if (pid > 0) {
printf("["__FILE__"][Line: %d][%s]: parent process pid = %d\n", __LINE__, __func__, getppid());
wait(&status);
} else if (pid == 0) {
printf("["__FILE__"][Line: %d][%s]: child pid = %d\n", __LINE__, __func__, pid);
__cfi_slowpath(call_site_type_id, (void*)&count);
} else {
printf("["__FILE__"][Line: %d][%s]: fork failed!\n", __LINE__, __func__);
}
dlclose(handle);
printf("["__FILE__"][Line: %d][%s]: end\n", __LINE__, __func__);
}
/**
* @tc.name : cfi_slowpath_function_test_0006
* @tc.desc : Loading a dso which size is larger than 1 LIBRARY_ALIGNMENT(256KB), call the __cfi_slowpath()
* function with address in different LIBRARY_ALIGNMENT range and make sure __cfi_check() is called.
* @tc.level : Level 1
*/
void cfi_slowpath_function_test_0006(void)
{
printf("["__FILE__"][Line: %d][%s]: entry\n", __LINE__, __func__);
uint64_t call_site_type_id = 50;
void* handle = dlopen(LIB_PATH, RTLD_LAZY);
EXPECT_PTRNE("cfi_slowpath_function_test_0006", handle, NULL);
*(void **)(&get_count) = dlsym(handle, "get_count");
*(void **)(&buf_check) = dlsym(handle, "buf");
size_t count = (*get_count)();
const size_t bss_size = 1024 * 1024;
for (size_t i = 0; i < bss_size; ++i) {
__cfi_slowpath(call_site_type_id, (char*)buf_check + i);
EXPECT_EQ("cfi_slowpath_function_test_0006", ++count, (*get_count)());
}
dlclose(handle);
printf("["__FILE__"][Line: %d][%s]: end\n", __LINE__, __func__);
}
/**
* @tc.name : cfi_slowpath_function_test_0007
* @tc.desc : Loading a dso 2 times
* @tc.level : Level 1
*/
void cfi_slowpath_function_test_0007(void)
{
printf("["__FILE__"][Line: %d][%s]: entry\n", __LINE__, __func__);
uint64_t call_site_type_id1 = 10;
uint64_t call_site_type_id2 = 20;
void* handle = dlopen(LIB_PATH, RTLD_LAZY);
EXPECT_PTRNE("cfi_slowpath_function_test_0007", handle, NULL);
*(void **)(&get_count) = dlsym(handle, "get_count");
*(void **)(&get_global_address) = dlsym(handle, "get_global_address");
__cfi_slowpath(call_site_type_id1, (*get_global_address)());
void* handle2 = dlopen(LIB_PATH, RTLD_LAZY);
EXPECT_PTREQ("cfi_slowpath_function_test_0007", handle, handle2);
*(void **)(&get_count) = dlsym(handle2, "get_count");
*(void **)(&get_type_id) = dlsym(handle2, "get_type_id");
*(void **)(&get_address) = dlsym(handle2, "get_address");
*(void **)(&get_diag) = dlsym(handle2, "get_diag");
*(void **)(&get_global_address) = dlsym(handle2, "get_global_address");
size_t count = (*get_count)();
__cfi_slowpath(call_site_type_id2, (*get_global_address)());
EXPECT_EQ("cfi_slowpath_function_test_0007", call_site_type_id2, (*get_type_id)());
EXPECT_EQ("cfi_slowpath_function_test_0007", (*get_global_address)(), (*get_address)());
EXPECT_EQ("cfi_slowpath_function_test_0007", ++count, (*get_count)());
dlclose(handle);
dlclose(handle2);
printf("["__FILE__"][Line: %d][%s]: end\n", __LINE__, __func__);
}
/**
* @tc.name : cfi_slowpath_function_test_0008
* @tc.desc : Calling dso's function after unloading the dso.
* @tc.level : Level 1
*/
void cfi_slowpath_function_test_0008(void)
{
printf("["__FILE__"][Line: %d][%s]: entry\n", __LINE__, __func__);
uint64_t call_site_type_id = 30;
void* handle = dlopen(LIB_PATH, RTLD_LAZY);
EXPECT_PTRNE("cfi_slowpath_function_test_0008", handle, NULL);
*(void **)(&get_global_address) = dlsym(handle, "get_global_address");
dlclose(handle);
int status;
pid_t pid;
pid = fork();
if (pid > 0) {
printf("["__FILE__"][Line: %d][%s]: parent process pid = %d\n", __LINE__, __func__, getppid());
wait(&status);
} else if (pid == 0) {
printf("["__FILE__"][Line: %d][%s]: child pid = %d\n", __LINE__, __func__, pid);
__cfi_slowpath(call_site_type_id, (*get_global_address)());
} else {
printf("["__FILE__"][Line: %d][%s]: fork failed!\n", __LINE__, __func__);
}
printf("["__FILE__"][Line: %d][%s]: end\n", __LINE__, __func__);
}
/**
* @tc.name : cfi_slowpath_diag_function_test_0001
* @tc.desc : Loading a dso that contains __cfi_check() symbol, call the __cfi_slowpath_diag() function with
* address inside the DSO, the __cfi_check() function is called.
* @tc.level : Level 1
*/
void cfi_slowpath_diag_function_test_0001(void)
{
printf("["__FILE__"][Line: %d][%s]: entry\n", __LINE__, __func__);
uint64_t call_site_type_id = 10;
uint64_t diag_info = 0;
void* handle = dlopen(LIB_PATH, RTLD_LAZY);
EXPECT_PTRNE("cfi_slowpath_diag_function_test_0001", handle, NULL);
*(void **)(&get_count) = dlsym(handle, "get_count");
*(void **)(&get_type_id) = dlsym(handle, "get_type_id");
*(void **)(&get_diag) = dlsym(handle, "get_diag");
*(void **)(&get_global_address) = dlsym(handle, "get_global_address");
size_t count = (*get_count)();
__cfi_slowpath_diag(call_site_type_id, NULL, &diag_info);
EXPECT_EQ("cfi_slowpath_diag_function_test_0001", count, (*get_count)());
__cfi_slowpath_diag(call_site_type_id, (*get_global_address)(), &diag_info);
EXPECT_EQ("cfi_slowpath_diag_function_test_0001", ++count, (*get_count)());
EXPECT_EQ("cfi_slowpath_diag_function_test_0001", call_site_type_id, (*get_type_id)());
EXPECT_EQ("cfi_slowpath_diag_function_test_0001", (*get_diag)(), &diag_info);
dlclose(handle);
printf("["__FILE__"][Line: %d][%s]: end\n", __LINE__, __func__);
}
/**
* @tc.name : cfi_unmap_dso_from_cfi_shadow_001
* @tc.desc : If dso map is NULL while unmapping from the CFI shadow, do nothing.
* @tc.level : Level 2
*/
void cfi_unmap_dso_from_cfi_shadow_001(void)
{
printf("["__FILE__"][Line: %d][%s]: entry\n", __LINE__, __func__);
struct dso test_dso = {};
test_dso.map = 0;
test_dso.map_len = 1;
unmap_dso_from_cfi_shadow(&test_dso);
printf("["__FILE__"][Line: %d][%s]: end\n", __LINE__, __func__);
}
/**
* @tc.name : cfi_unmap_dso_from_cfi_shadow_002
* @tc.desc : If dso map_len is NULL while unmapping from the CFI shadow, do nothing.
* @tc.level : Level 2
*/
void cfi_unmap_dso_from_cfi_shadow_002(void)
{
printf("["__FILE__"][Line: %d][%s]: entry\n", __LINE__, __func__);
struct dso test_dso = {};
unsigned char a = 'S';
test_dso.map = &a;
test_dso.map_len = 0;
unmap_dso_from_cfi_shadow(&test_dso);
printf("["__FILE__"][Line: %d][%s]: end\n", __LINE__, __func__);
}
TEST_FUN G_Fun_Array[] = {
cfi_init_test_0001,
cfi_init_test_0002,
cfi_init_test_0003,
cfi_slowpath_function_test_0002,
cfi_slowpath_function_test_0003,
cfi_slowpath_function_test_0004,
cfi_slowpath_function_test_0005,
cfi_slowpath_function_test_0006,
cfi_slowpath_function_test_0007,
cfi_slowpath_function_test_0008,
cfi_slowpath_diag_function_test_0001,
cfi_unmap_dso_from_cfi_shadow_001,
cfi_unmap_dso_from_cfi_shadow_002,
};
int main(void)
{
printf("["__FILE__"][Line: %d][%s]: entry\n", __LINE__, __func__);
int num = sizeof(G_Fun_Array) / sizeof(TEST_FUN);
for (int pos = 0; pos < num; ++pos) {
G_Fun_Array[pos]();
}
printf("["__FILE__"][Line: %d][%s]: end\n", __LINE__, __func__);
return 0;
}
/**
* Copyright (c) 2023 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 <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
static size_t g_count = 0;
static uint64_t g_type_id = 0;
static void *g_address = NULL;
static void *g_diag = NULL;
// Make sure the library crosses at least one kLibraryAlignment(=256KB) boundary.
char buf[1024 * 1024];
// Mock a CFI-enabled library without relying on the compiler.
__attribute__((aligned(4096))) void __cfi_check(uint64_t call_site_type_id,
void *target_addr, void *diag) {
printf("["__FILE__"][Line: %d][%s]: entry\n", __LINE__, __func__);
++g_count;
g_type_id = call_site_type_id;
g_address = target_addr;
g_diag = diag;
}
size_t get_count() {
return g_count;
}
uint64_t get_type_id() {
return g_type_id;
}
void *get_address() {
return g_address;
}
void *get_diag() {
return g_diag;
}
void *get_global_address() {
return &g_count;
}
......@@ -25,8 +25,9 @@ functionalext_list = [
"supplement:functionalext_supplement_test",
"fortify:functionalext_fortify_test",
"symver:functionalext_symver_test",
"sigchain:functionalext_sigchain_test",
"ldso_cfi:ldso_cfi_test",
"sched:functionalext_sched_test",
"unittest:functionalext_unittest_test",
"legacy:functionalext_legacy_test",
"sigchain:functionalext_sigchain_test",
]
......@@ -1669,6 +1669,7 @@ musl_src_ldso = [
"ldso/ns_config.c",
"ldso/strops.c",
"ldso/dynlink_rand.c",
"ldso/cfi.c",
"ldso/ld_log.c",
]
......@@ -2105,11 +2106,13 @@ musl_src_porting_file = [
"crt/arm/crti.s",
"crt/aarch64/crti.s",
"crt/crtplus.c",
"ldso/cfi.h",
"ldso/ld_log.h",
"ldso/ld_log.c",
"ldso/namespace.c",
"ldso/ns_config.c",
"ldso/strops.c",
"ldso/cfi.c",
"ldso/dynlink_rand.c",
"ldso/dynlink_rand.h",
"src/thread/pthread_create.c",
......
此差异已折叠。
/*
* Copyright (c) 2023 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 "dynlink.h"
#define CFI_SUCCESS 0
#define CFI_FAILED -1
/* Define LIBRARY_ALIGNMENT to balance the size of CFI shadow and the number of DSOs that each process can load.
* The LIBRARY_ALIGNMENT is use to calculate the start address of a DSO. Each DSO should be in the different
* LIBRARY_ALIGNMENT memory range so that each DSO can be well mapped to the CFI shadow.
*/
#define LIBRARY_ALIGNMENT_BITS 18
#define LIBRARY_ALIGNMENT (1UL << LIBRARY_ALIGNMENT_BITS)
/* map all the dso and the dependents to cfi shadow */
int init_cfi_shadow(struct dso *dso_list, struct dso *ldso);
/* map a dso and the dependents to cfi shadow */
int map_dso_to_cfi_shadow(struct dso *dso);
/* unmap a dso from cfi shadow */
void unmap_dso_from_cfi_shadow(struct dso *dso);
\ No newline at end of file
......@@ -26,7 +26,9 @@
#include <sys/membarrier.h>
#include <sys/time.h>
#include <time.h>
#include <sys/prctl.h>
#include "cfi.h"
#include "dlfcn_ext.h"
#include "dynlink_rand.h"
#include "ld_log.h"
......@@ -90,105 +92,6 @@ struct reserved_address_params {
#endif
};
struct td_index {
size_t args[2];
struct td_index *next;
};
struct verinfo {
const char *s;
const char *v;
bool use_vna_hash;
uint32_t vna_hash;
};
struct sym_info_pair {
uint_fast32_t sym_h;
uint32_t sym_l;
};
struct dso {
#if DL_FDPIC
struct fdpic_loadmap *loadmap;
#else
unsigned char *base;
#endif
char *name;
size_t *dynv;
struct dso *next, *prev;
/* add namespace */
ns_t *namespace;
/* mark the dso status */
unsigned int flags;
int cache_sym_index;
struct dso *cache_dso;
Sym *cache_sym;
Phdr *phdr;
int phnum;
size_t phentsize;
Sym *syms;
Elf_Symndx *hashtab;
uint32_t *ghashtab;
int16_t *versym;
Verdef *verdef;
Verneed *verneed;
char *strings;
struct dso *syms_next, *lazy_next;
size_t *lazy, lazy_cnt;
unsigned char *map;
size_t map_len;
dev_t dev;
ino_t ino;
uint64_t file_offset;
char relocated;
char constructed;
char kernel_mapped;
char mark;
char bfs_built;
char runtime_loaded;
char by_dlopen;
struct dso **deps, *needed_by;
size_t ndeps_direct;
size_t next_dep;
int ctor_visitor;
int nr_dlopen;
char *rpath_orig, *rpath;
struct tls_module tls;
size_t tls_id;
size_t relro_start, relro_end;
uintptr_t *new_dtv;
unsigned char *new_tls;
struct td_index *td_index;
struct dso *fini_next;
char *shortname;
#if DL_FDPIC
unsigned char *base;
#else
struct fdpic_loadmap *loadmap;
#endif
struct funcdesc {
void *addr;
size_t *got;
} *funcdescs;
size_t *got;
struct dso **parents;
size_t parents_count;
size_t parents_capacity;
bool is_global;
bool is_reloc_head_so_dep;
struct dso **reloc_can_search_dso_list;
size_t reloc_can_search_dso_count;
size_t reloc_can_search_dso_capacity;
char buf[];
};
struct symdef {
Sym *sym;
struct dso *dso;
};
typedef void (*stage3_func)(size_t *, size_t *);
static struct builtin_tls {
......@@ -268,7 +171,6 @@ static void handle_relro_sharing(struct dso *p, const dl_extinfo *extinfo, ssize
int handle_asan_path_open(int fd, const char *name, ns_t *namespace, char *buf, size_t buf_size);
/* add namespace function */
static void *addr2dso(size_t a);
static void get_sys_path(ns_configor *conf);
static void dlclose_ns(struct dso *p);
static bool get_app_path(char *path, size_t size)
......@@ -433,7 +335,7 @@ static void init_namespace(struct dso *app)
/* Compute load address for a virtual address in a given dso. */
#if DL_FDPIC
static void *laddr(const struct dso *p, size_t v)
void *laddr(const struct dso *p, size_t v)
{
size_t j=0;
if (!p->loadmap) return p->base + v;
......@@ -588,7 +490,7 @@ static struct sym_info_pair sysv_hash(const char *s0)
return s_info_p;
}
static struct sym_info_pair gnu_hash(const char *s0)
struct sym_info_pair gnu_hash(const char *s0)
{
struct sym_info_pair s_info_p;
const unsigned char *s = (void *)s0;
......@@ -803,6 +705,60 @@ static void add_can_search_so_list_in_dso(struct dso *dso_relocating, struct dso
#if defined(__GNUC__)
__attribute__((always_inline))
#endif
struct symdef find_sym_impl(
struct dso *dso, struct verinfo *verinfo, struct sym_info_pair s_info_p, int need_def, ns_t *ns)
{
Sym *sym;
uint32_t *ght;
uint32_t h = 0;
uint32_t gh = s_info_p.sym_h;
uint32_t gho = gh / (8 * sizeof(size_t));
size_t ghm = 1ul << gh % (8 * sizeof(size_t));
struct symdef def = {0};
if (ns && !check_sym_accessible(dso, ns))
return def;
if ((ght = dso->ghashtab)) {
const size_t *bloomwords = (const void *)(ght + 4);
size_t f = bloomwords[gho & (ght[2] - 1)];
if (!(f & ghm))
return def;
f >>= (gh >> ght[3]) % (8 * sizeof f);
if (!(f & 1))
return def;
sym = gnu_lookup(s_info_p, ght, dso, verinfo);
} else {
if (!h)
s_info_p = sysv_hash(verinfo->s);
sym = sysv_lookup(verinfo, s_info_p, dso);
}
if (!sym)
return def;
if (!sym->st_shndx)
if (need_def || (sym->st_info & 0xf) == STT_TLS || ARCH_SYM_REJECT_UND(sym))
return def;
if (!sym->st_value)
if ((sym->st_info & 0xf) != STT_TLS)
return def;
if (!(1 << (sym->st_info & 0xf) & OK_TYPES))
return def;
if (!(1 << (sym->st_info >> 4) & OK_BINDS))
return def;
def.sym = sym;
def.dso = dso;
return def;
}
static inline struct symdef find_sym2(struct dso *dso, struct verinfo *verinfo, int need_def, int use_deps, ns_t *ns)
{
struct sym_info_pair s_info_p = gnu_hash(verinfo->s);
......@@ -1386,19 +1342,45 @@ static void *map_library(int fd, struct dso *dso, struct reserved_address_params
map_flags |= MAP_FIXED;
}
}
/* The first time, we map too much, possibly even more than
* the length of the file. This is okay because we will not
* use the invalid part; we just need to reserve the right
* amount of virtual address space to map over later. */
map = DL_NOMMU_SUPPORT
? mmap((void *)start_addr, map_len, PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
: mmap((void *)start_addr, map_len, prot,
map_flags, fd, off_start);
if (map==MAP_FAILED) goto error;
if (reserved_params && map_len < reserved_params->reserved_size) {
reserved_params->reserved_size -= (map_len + (start_addr - (size_t)reserved_params->start_addr));
reserved_params->start_addr = (void *)((uint8_t *)map + map_len);
/* we will find a LIBRARY_ALIGNMENT aligned address as the start of dso
* so we need a tmp_map_len as map_len + LIBRARY_ALIGNMENT to make sure
* we have enough space to shift the dso to the correct location. */
size_t tmp_map_len = ALIGN(map_len, LIBRARY_ALIGNMENT) + LIBRARY_ALIGNMENT - PAGE_SIZE;
/* if reserved_params exists, we should use start_addr as prefered result to do the mmap operation */
if (reserved_params) {
map = DL_NOMMU_SUPPORT
? mmap((void *)start_addr, map_len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)
: mmap((void *)start_addr, map_len, prot, map_flags, fd, off_start);
if (map == MAP_FAILED) {
goto error;
}
if (reserved_params && map_len < reserved_params->reserved_size) {
reserved_params->reserved_size -= (map_len + (start_addr - (size_t)reserved_params->start_addr));
reserved_params->start_addr = (void *)((uint8_t *)map + map_len);
}
/* if reserved_params does not exist, we should use real_map as prefered result to do the mmap operation */
} else {
/* use tmp_map_len to mmap enough space for the dso with anonymous mapping */
unsigned char *temp_map = mmap((void *)NULL, tmp_map_len, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (temp_map == MAP_FAILED) {
goto error;
}
/* find the LIBRARY_ALIGNMENT aligned address */
unsigned char *real_map = (unsigned char*)ALIGN((uintptr_t)temp_map, LIBRARY_ALIGNMENT);
/* mummap the space we mmap before so that we can mmap correct space again */
munmap(temp_map, tmp_map_len);
map = DL_NOMMU_SUPPORT
? mmap(real_map, map_len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)
/* use map_len to mmap correct space for the dso with file mapping */
: mmap(real_map, map_len, prot, map_flags, fd, off_start);
if (map == MAP_FAILED) {
goto error;
}
}
dso->map = map;
dso->map_len = map_len;
......@@ -1592,7 +1574,7 @@ static void decode_dyn(struct dso *p)
p->verneed = laddr(p, *dyn);
}
static size_t count_syms(struct dso *p)
size_t count_syms(struct dso *p)
{
if (p->hashtab) return p->hashtab[1];
......@@ -2915,6 +2897,10 @@ void __dls3(size_t *sp, size_t *auxv)
libc.tls_size = tmp_tls_size;
}
if (init_cfi_shadow(head, &ldso) == CFI_FAILED) {
error("[%s] init_cfi_shadow failed: %m", __FUNCTION__);
}
if (ldso_fail) _exit(127);
if (ldd_mode) _exit(0);
......@@ -3215,6 +3201,11 @@ static void *dlopen_impl(
* relocations resolved to symbol definitions that get removed. */
redo_lazy_relocs();
if (map_dso_to_cfi_shadow(p) == CFI_FAILED) {
error("[%s] map_dso_to_cfi_shadow failed: %m", __FUNCTION__);
longjmp(*rtld_fail, 1);
}
if (mode & RTLD_NODELETE) {
p->flags |= DSO_FLAGS_NODELETE;
}
......@@ -3427,7 +3418,7 @@ hidden int __dl_invalid_handle(void *h)
return 1;
}
static void *addr2dso(size_t a)
void *addr2dso(size_t a)
{
struct dso *p;
size_t i;
......@@ -3582,6 +3573,8 @@ static int dlclose_impl(struct dso *p)
/* remove dso from namespace */
dlclose_ns(p);
unmap_dso_from_cfi_shadow(p);
if (p->lazy != NULL)
internal_free(p->lazy);
......@@ -4393,20 +4386,45 @@ static bool task_map_library(struct loadtask *task, struct reserved_address_para
map_flags |= MAP_FIXED;
}
}
/* The first time, we map too much, possibly even more than
* the length of the file. This is okay because we will not
* use the invalid part; we just need to reserve the right
* amount of virtual address space to map over later. */
map = DL_NOMMU_SUPPORT
/* we will find a LIBRARY_ALIGNMENT aligned address as the start of dso
* so we need a tmp_map_len as map_len + LIBRARY_ALIGNMENT to make sure
* we have enough space to shift the dso to the correct location. */
size_t tmp_map_len = ALIGN(map_len, LIBRARY_ALIGNMENT) + LIBRARY_ALIGNMENT - PAGE_SIZE;
/* if reserved_params exists, we should use start_addr as prefered result to do the mmap operation */
if (reserved_params) {
map = DL_NOMMU_SUPPORT
? mmap((void *)start_addr, map_len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)
: mmap((void *)start_addr, map_len, prot, map_flags, task->fd, off_start + task->file_offset);
if (map == MAP_FAILED) {
LD_LOGE("Error mapping library %{public}s: failed to map fd", task->name);
goto error;
}
if (reserved_params && map_len < reserved_params->reserved_size) {
reserved_params->reserved_size -= (map_len + (start_addr - (size_t)reserved_params->start_addr));
reserved_params->start_addr = (void *)((uint8_t *)map + map_len);
if (map == MAP_FAILED) {
goto error;
}
if (reserved_params && map_len < reserved_params->reserved_size) {
reserved_params->reserved_size -= (map_len + (start_addr - (size_t)reserved_params->start_addr));
reserved_params->start_addr = (void *)((uint8_t *)map + map_len);
}
/* if reserved_params does not exist, we should use real_map as prefered result to do the mmap operation */
} else {
/* use tmp_map_len to mmap enough space for the dso with anonymous mapping */
unsigned char *temp_map = mmap((void *)NULL, tmp_map_len, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (temp_map == MAP_FAILED) {
goto error;
}
/* find the LIBRARY_ALIGNMENT aligned address */
unsigned char *real_map = (unsigned char*)ALIGN((uintptr_t)temp_map, LIBRARY_ALIGNMENT);
/* mummap the space we mmap before so that we can mmap correct space again */
munmap(temp_map, tmp_map_len);
map = DL_NOMMU_SUPPORT
? mmap(real_map, map_len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)
/* use map_len to mmap correct space for the dso with file mapping */
: mmap(real_map, map_len, prot, map_flags, task->fd, off_start + task->file_offset);
if (map == MAP_FAILED) {
goto error;
}
}
task->p->map = map;
task->p->map_len = map_len;
......
......@@ -6,6 +6,11 @@
#include <stdint.h>
#include <stddef.h>
#include <stdarg.h>
#include <link.h>
#include <sys/types.h>
#include <stdlib.h>
#include "libc.h"
#include "../../ldso/namespace.h"
#if UINTPTR_MAX == 0xffffffff
typedef Elf32_Ehdr Ehdr;
......@@ -53,6 +58,106 @@ enum {
REL_FUNCDESC_VAL,
};
struct td_index {
size_t args[2];
struct td_index *next;
};
struct verinfo {
const char *s;
const char *v;
bool use_vna_hash;
uint32_t vna_hash;
};
struct sym_info_pair {
uint_fast32_t sym_h;
uint32_t sym_l;
};
struct dso {
#if DL_FDPIC
struct fdpic_loadmap *loadmap;
#else
unsigned char *base;
#endif
char *name;
size_t *dynv;
struct dso *next, *prev;
/* add namespace */
ns_t *namespace;
/* mark the dso status */
unsigned int flags;
int cache_sym_index;
struct dso *cache_dso;
Sym *cache_sym;
Phdr *phdr;
int phnum;
size_t phentsize;
Sym *syms;
Elf_Symndx *hashtab;
uint32_t *ghashtab;
int16_t *versym;
Verdef *verdef;
Verneed *verneed;
char *strings;
struct dso *syms_next, *lazy_next;
size_t *lazy, lazy_cnt;
unsigned char *map;
size_t map_len;
dev_t dev;
ino_t ino;
uint64_t file_offset;
char relocated;
char constructed;
char kernel_mapped;
char mark;
char bfs_built;
char runtime_loaded;
char by_dlopen;
struct dso **deps, *needed_by;
size_t ndeps_direct;
size_t next_dep;
int ctor_visitor;
int nr_dlopen;
char *rpath_orig, *rpath;
struct tls_module tls;
size_t tls_id;
size_t relro_start, relro_end;
uintptr_t *new_dtv;
unsigned char *new_tls;
struct td_index *td_index;
struct dso *fini_next;
char *shortname;
#if DL_FDPIC
unsigned char *base;
#else
struct fdpic_loadmap *loadmap;
#endif
struct funcdesc {
void *addr;
size_t *got;
} *funcdescs;
size_t *got;
struct dso **parents;
size_t parents_count;
size_t parents_capacity;
bool is_global;
bool is_reloc_head_so_dep;
struct dso **reloc_can_search_dso_list;
size_t reloc_can_search_dso_count;
size_t reloc_can_search_dso_capacity;
bool is_mapped_to_shadow;
char buf[];
};
struct symdef {
Sym *sym;
struct dso *dso;
};
struct fdpic_loadseg {
uintptr_t addr, p_vaddr, p_memsz;
};
......@@ -118,6 +223,16 @@ struct fdpic_dummy_loadmap {
typedef void (*stage2_func)(unsigned char *, size_t *);
#if DL_FDPIC
void *laddr(const struct dso *p, size_t v);
#endif
void *addr2dso(size_t a);
size_t count_syms(struct dso *p);
struct sym_info_pair gnu_hash(const char *s0);
struct symdef find_sym_impl(
struct dso *dso, struct verinfo *verinfo, struct sym_info_pair s_info_p, int need_def, ns_t *ns);
hidden void *__dlsym(void *restrict, const char *restrict, void *restrict);
hidden void *__dlvsym(void *restrict, const char *restrict, const char *restrict, void *restrict);
hidden int __dlclose(void *p);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册