From 21268015bfe47bb0c2427cbaaec7ddb6bce1f2e9 Mon Sep 17 00:00:00 2001 From: liyiming13 Date: Thu, 19 Sep 2024 19:44:16 +0800 Subject: [PATCH] Add dl_iterate_phdr lock Issue:https://gitee.com/openharmony/third_party_musl/issues/IAUQNT?from=project-issue Test:libc-test Signed-off-by: liyiming13 --- ldso/linux/dynlink.c | 7 + .../supplement/ldso/dl_iterate_phdr.c | 135 +++++++++++++++++- 2 files changed, 140 insertions(+), 2 deletions(-) diff --git a/ldso/linux/dynlink.c b/ldso/linux/dynlink.c index 3b342f199..c08ddca73 100644 --- a/ldso/linux/dynlink.c +++ b/ldso/linux/dynlink.c @@ -172,6 +172,7 @@ static int noload; static int shutting_down; static jmp_buf *rtld_fail; static pthread_rwlock_t lock; +static pthread_mutex_t dlclose_lock = { { PTHREAD_MUTEX_RECURSIVE } }; // set mutex type to PTHREAD_MUTEX_RECURSIVE static struct debug debug; static struct tls_module *tls_tail; static size_t tls_cnt, tls_offset, tls_align = MIN_TLS_ALIGN; @@ -4452,11 +4453,13 @@ static int do_dlclose(struct dso *p, bool check_deps_all) hidden int __dlclose(void *p) { + pthread_mutex_lock(&dlclose_lock); int rc; pthread_rwlock_wrlock(&lock); if (shutting_down) { error("Cannot dlclose while program is exiting."); pthread_rwlock_unlock(&lock); + pthread_mutex_unlock(&dlclose_lock); return -1; } #ifdef HANDLE_RANDOMIZATION @@ -4466,6 +4469,7 @@ hidden int __dlclose(void *p) error("Handle is invalid."); LD_LOGE("Handle is not find."); pthread_rwlock_unlock(&lock); + pthread_mutex_unlock(&dlclose_lock); return -1; } rc = do_dlclose(dso, 0); @@ -4473,6 +4477,7 @@ hidden int __dlclose(void *p) rc = do_dlclose(p, 0); #endif pthread_rwlock_unlock(&lock); + pthread_mutex_unlock(&dlclose_lock); return rc; } @@ -4644,6 +4649,7 @@ no_redir: int dl_iterate_phdr(int(*callback)(struct dl_phdr_info *info, size_t size, void *data), void *data) { + pthread_mutex_lock(&dlclose_lock); struct dso *current; struct dl_phdr_info info; int ret = 0; @@ -4668,6 +4674,7 @@ int dl_iterate_phdr(int(*callback)(struct dl_phdr_info *info, size_t size, void current = current->next; pthread_rwlock_unlock(&lock); } + pthread_mutex_unlock(&dlclose_lock); return ret; } diff --git a/libc-test/src/functionalext/supplement/ldso/dl_iterate_phdr.c b/libc-test/src/functionalext/supplement/ldso/dl_iterate_phdr.c index ce1a88fa5..427ce9671 100644 --- a/libc-test/src/functionalext/supplement/ldso/dl_iterate_phdr.c +++ b/libc-test/src/functionalext/supplement/ldso/dl_iterate_phdr.c @@ -17,6 +17,11 @@ #include #include #include "functionalext.h" +#include "test.h" + +#define SAME_NAME_COUT_1 1 +#define SAME_NAME_COUT_2 2 +#define OOM_FILL 50000 static int header_handler(struct dl_phdr_info *info, size_t size, void *data) { @@ -27,6 +32,25 @@ static int header_handler(struct dl_phdr_info *info, size_t size, void *data) return 0; } +static int same_name_count = 0; + +static int same_name_count_handler(struct dl_phdr_info *info, size_t size, void *data) +{ + void *addrhead = (void *)(info->dlpi_addr + info->dlpi_phdr[0].p_vaddr); + if ((strcmp(info->dlpi_name, "/data/libtest.so") == 0) && (addrhead != NULL)) { + same_name_count++; + } + return 0; +} + +static int lock_recursive_handler(struct dl_phdr_info *info, size_t size, void *data) +{ + if (dl_iterate_phdr(header_handler, NULL)) { + return 0; + } + return 1; +} + /** * @tc.name : dl_iterate_phdr_0100 * @tc.desc : The parameter is valid, get the starting address of the dynamic library loaded in the memory. @@ -34,17 +58,124 @@ static int header_handler(struct dl_phdr_info *info, size_t size, void *data) */ void dl_iterate_phdr_0100(void) { - system("cp /system/lib/libutils.z.so /data/libtest.so"); void *handle = dlopen("/data/libtest.so", RTLD_NOW); int ret = 0; ret = dl_iterate_phdr(header_handler, NULL); EXPECT_EQ("dl_iterate_phdr_0100", (int)ret, 1); + + dlclose(handle); + ret = dl_iterate_phdr(header_handler, NULL); + EXPECT_EQ("dl_iterate_phdr_0100", (int)ret, 0); +} + +/** + * @tc.name : dl_iterate_phdr_0200 + * @tc.desc : Call dlopen twice, dlclose twice, the target so cannot find when second dlclose call. + * @tc.level : Level 0 + */ +void dl_iterate_phdr_0200(void) +{ + void *handle = dlopen("/data/libtest.so", RTLD_NOW); + int ret = 0; + ret = dl_iterate_phdr(header_handler, NULL); + EXPECT_EQ("dl_iterate_phdr_0200", (int)ret, 1); + + handle = dlopen("/data/libtest.so", RTLD_NOW); + ret = dl_iterate_phdr(header_handler, NULL); + EXPECT_EQ("dl_iterate_phdr_0200", (int)ret, 1); + + dlclose(handle); + ret = dl_iterate_phdr(header_handler, NULL); + EXPECT_EQ("dl_iterate_phdr_0200", (int)ret, 1); + + dlclose(handle); + ret = dl_iterate_phdr(header_handler, NULL); + EXPECT_EQ("dl_iterate_phdr_0200", (int)ret, 0); +} + +/** + * @tc.name : dl_iterate_phdr_0300 + * @tc.desc : Call dlopen twice, dlclose twice, so file use the same name but it is two different files. + * @tc.level : Level 0 + */ +void dl_iterate_phdr_0300(void) +{ + void *handle1 = dlopen("/data/libtest.so", RTLD_NOW); + int ret = 0; + same_name_count = 0; + ret = dl_iterate_phdr(same_name_count_handler, NULL); + EXPECT_EQ("dl_iterate_phdr_0300", same_name_count, SAME_NAME_COUT_1); + system("rm -rf /data/libtest.so"); - exit(EXIT_SUCCESS); + system("cp /system/lib/libutils.z.so /data/libtest.so"); + + void *handle2 = dlopen("/data/libtest.so", RTLD_NOW); + same_name_count = 0; + ret = dl_iterate_phdr(same_name_count_handler, NULL); + EXPECT_EQ("dl_iterate_phdr_0300", same_name_count, SAME_NAME_COUT_2); + + dlclose(handle1); + same_name_count = 0; + ret = dl_iterate_phdr(same_name_count_handler, NULL); + EXPECT_EQ("dl_iterate_phdr_0300", same_name_count, SAME_NAME_COUT_1); + + dlclose(handle2); + same_name_count = 0; + ret = dl_iterate_phdr(same_name_count_handler, NULL); + EXPECT_EQ("dl_iterate_phdr_0300", same_name_count, 0); +} + +/** + * @tc.name : dl_iterate_phdr_0400 + * @tc.desc : Test lock is RECURSIVE when call dl_iterate_phdr + * @tc.level : Level 0 + */ +void dl_iterate_phdr_0400(void) +{ + void *handle = dlopen("/data/libtest.so", RTLD_NOW); + int ret = 0; + ret = dl_iterate_phdr(lock_recursive_handler, NULL); + EXPECT_EQ("dl_iterate_phdr_0400", (int)ret, 0); + + dlclose(handle); +} + +/** + * @tc.name : dl_iterate_phdr_0500 + * @tc.desc : Call dl_iterate_phdr when OOM happen. + * @tc.level : Level 0 + */ +void dl_iterate_phdr_0500(void) +{ + void *handle = dlopen("/data/libtest.so", RTLD_NOW); + int ret = 0; + ret = dl_iterate_phdr(header_handler, NULL); + EXPECT_EQ("dl_iterate_phdr_0500", (int)ret, 1); + // create oom start + if (t_memfill() < 0) { + EXPECT_TRUE("dl_iterate_phdr_0500", false); + } + errno = 0; + if (malloc(OOM_FILL)) { + EXPECT_TRUE("dl_iterate_phdr_0500", false); + } + if (errno != ENOMEM) { + EXPECT_TRUE("dl_iterate_phdr_0500", false); + } + // create oom end + ret = dl_iterate_phdr(header_handler, NULL); + EXPECT_EQ("dl_iterate_phdr_0500", (int)ret, 1); + dlclose(handle); } int main(int argc, char *argv[]) { + system("cp /system/lib/libutils.z.so /data/libtest.so"); dl_iterate_phdr_0100(); + dl_iterate_phdr_0200(); + dl_iterate_phdr_0300(); + dl_iterate_phdr_0500(); + system("rm -rf /data/libtest.so"); + exit(EXIT_SUCCESS); return t_status; } \ No newline at end of file -- Gitee