未验证 提交 03a3c130 编写于 作者: O openharmony_ci 提交者: Gitee

!351 加载器地址随机化,RELRO共享机制

Merge pull request !351 from 王家辉/update_code_rm011_0623_1
# 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.
import("../../../test_template.gni")
test_unittest("ldso_randomization_test") {
target_dir = "functionalext/ldso_randomization"
}
test_unittest("ldso_randomization_manual") {
target_dir = "functionalext/ldso_randomization"
}
ohos_shared_library("ldso_randomization_dep_e") {
include_dirs = [ "." ]
sources = [ "ldso_randomization_dep_e.c" ]
output_name = "ldso_randomization_dep_e"
output_extension = "so"
subsystem_name = "musl"
part_name = "libc-test-lib"
}
ohos_shared_library("ldso_randomization_dep_d") {
include_dirs = [ "." ]
sources = [ "ldso_randomization_dep_d.c" ]
output_name = "ldso_randomization_dep_d"
output_extension = "so"
subsystem_name = "musl"
part_name = "libc-test-lib"
}
ohos_shared_library("ldso_randomization_dep_c") {
include_dirs = [ "." ]
sources = [ "ldso_randomization_dep_c.c" ]
output_name = "ldso_randomization_dep_c"
output_extension = "so"
subsystem_name = "musl"
part_name = "libc-test-lib"
}
ohos_shared_library("ldso_randomization_dep_b") {
include_dirs = [ "." ]
sources = [ "ldso_randomization_dep_b.c" ]
output_name = "ldso_randomization_dep_b"
output_extension = "so"
deps = [
":ldso_randomization_dep_d",
":ldso_randomization_dep_e",
]
subsystem_name = "musl"
part_name = "libc-test-lib"
}
ohos_shared_library("ldso_randomization_dep_a") {
include_dirs = [ "." ]
sources = [ "ldso_randomization_dep_a.c" ]
output_name = "ldso_randomization_dep_a"
output_extension = "so"
deps = [
":ldso_randomization_dep_b",
":ldso_randomization_dep_c",
]
subsystem_name = "musl"
part_name = "libc-test-lib"
}
ohos_shared_library("ldso_randomization_dep") {
include_dirs = [ "." ]
sources = [ "ldso_randomization_dep.c" ]
output_name = "ldso_randomization_dep"
output_extension = "so"
subsystem_name = "musl"
part_name = "libc-test-lib"
}
group("functionalext_ldso_randomization_test") {
testonly = true
deps = [
":ldso_randomization_dep",
":ldso_randomization_dep_a",
":ldso_randomization_manual",
":ldso_randomization_test",
]
}
/*
* 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.
*/
int i = 0;
void test(void)
{
i++;
}
\ 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 LDSO_RANDOMIZATION_DEP_H
#define LDSO_RANDOMIZATION_DEP_H
int test(void);
int test_b(void);
int test_c(void);
int test_d(void);
int test_e(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 "ldso_randomization_dep.h"
int i = 0;
int test(void)
{
i++;
return test_b() + test_c();
}
\ 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 "ldso_randomization_dep.h"
static int i = 0;
int test_b(void)
{
test_d();
test_e();
return i++;
}
\ 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 "ldso_randomization_dep.h"
static int i = 0;
int test_c(void)
{
return i++;
}
\ 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 "ldso_randomization_dep.h"
static int i = 0;
int test_d(void)
{
return i++;
}
\ 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 "ldso_randomization_dep.h"
static int i = 0;
int test_e(void)
{
return i++;
}
\ 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 <dlfcn_ext.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include "test.h"
#define PIPE_FD 2
#define TEST_COUNTS 32
const char *LIB_NAME = "./libldso_randomization_dep.so";
const char *LIB_NAME_A = "./libldso_randomization_dep_a.so";
typedef void (*TEST_FUNC)(void);
static uintptr_t compare(const void *a, const void *b)
{
return (*(uintptr_t *)a - *(uintptr_t *)b);
}
static bool check_address(void **array, size_t length)
{
qsort(array, length, sizeof(void *), (void *)compare);
for (size_t i = 0, j = 1; j < length; i++, j++) {
if (array[i] == array[j]) {
return false;
}
}
return true;
}
/**
* @tc.name : dlopen_randomization_0500
* @tc.desc : Repeatedly calling the dlopen interface to load the dynamic library,
* and calling dlclose to unload each time
* @tc.level : Level3
*/
static void dlopen_randomization_0500(void)
{
void *handles[TEST_COUNTS] = {0};
void *handle = 0;
int i = TEST_COUNTS;
do {
handle = dlopen(LIB_NAME, RTLD_NOW);
handles[--i] = handle;
if (handle) {
dlclose(handle);
}
} while (i);
if (check_address(handles, TEST_COUNTS)) {
t_printf("%s handles are randomized\n", __FUNCTION__);
} else {
t_printf("%s exists the same handle!!!!\n", __FUNCTION__);
}
}
/**
* @tc.name : dlopen_randomization_0700
* @tc.desc : Different processes call the dlopen interface to load dynamic libraries
* @tc.level : Level3
*/
static void dlopen_randomization_0700(void)
{
void *parent_handle = 0;
void *get_child_handle = 0;
int fd[PIPE_FD];
if (pipe(fd) < 0) {
t_printf("%s create pipe error!\n", __FUNCTION__);
return;
}
pid_t pid = fork();
if (pid == 0) {
void *child_handle = dlopen(LIB_NAME, RTLD_NOW);
t_printf("%s child handle is %p \n", __FUNCTION__, child_handle);
if (child_handle) {
dlclose(child_handle);
}
write(fd[1], &child_handle, sizeof(void *));
exit(0);
}
parent_handle = dlopen(LIB_NAME, RTLD_NOW);
t_printf("%s parent handle is %p \n", __FUNCTION__, parent_handle);
if (parent_handle) {
dlclose(parent_handle);
}
int status;
waitpid(pid, &status, 0);
read(fd[0], &get_child_handle, sizeof(void *));
t_printf("%s get child handle is %p\n", __FUNCTION__, get_child_handle);
if (parent_handle == get_child_handle) {
t_printf("%s the parent handle is the same as the child handle!!!!\n", __FUNCTION__);
} else {
t_printf("%s the parent handle is different form the child handle.\n", __FUNCTION__);
}
close(fd[0]);
close(fd[1]);
}
/**
* @tc.name : dlopen_ext_randomization_0500
* @tc.desc : Repeatedly calling the dlopen_ext interface to load the dynamic library,
* and calling dlclose to unload each time
* @tc.level : Level3
*/
static void dlopen_ext_randomization_0500(void)
{
dl_extinfo extinfo = {0};
void *handles[TEST_COUNTS] = {0};
void *handle = 0;
int i = TEST_COUNTS;
do {
handle = dlopen_ext(LIB_NAME, RTLD_NOW, &extinfo);
handles[--i] = handle;
if (handle) {
dlclose(handle);
}
} while (i);
if (check_address(handles, TEST_COUNTS)) {
t_printf("%s handles are randomized\n", __FUNCTION__);
} else {
t_printf("%s exists the same handle!!!!\n", __FUNCTION__);
}
}
/**
* @tc.name : dlopen_ext_randomization_0700
* @tc.desc : Different processes call the dlopen_ext interface to load dynamic libraries
* @tc.level : Level3
*/
static void dlopen_ext_randomization_0700(void)
{
void *parent_handle = 0;
void *get_child_handle = 0;
dl_extinfo extinfo = {0};
int fd[PIPE_FD];
if (pipe(fd) < 0) {
t_printf("%s create pipe error!\n", __FUNCTION__);
return;
}
pid_t pid = fork();
if (pid == 0) {
void *child_handle = dlopen_ext(LIB_NAME, RTLD_NOW, &extinfo);
t_printf("%s child handle is %p \n", __FUNCTION__, child_handle);
if (child_handle) {
dlclose(child_handle);
}
write(fd[1], &child_handle, sizeof(void *));
exit(0);
}
parent_handle = dlopen_ext(LIB_NAME, RTLD_NOW, &extinfo);
t_printf("%s parent handle is %p \n", __FUNCTION__, parent_handle);
if (parent_handle) {
dlclose(parent_handle);
}
int status;
waitpid(pid, &status, 0);
read(fd[0], &get_child_handle, sizeof(void *));
t_printf("%s get child handle is %p\n", __FUNCTION__, get_child_handle);
if (parent_handle == get_child_handle) {
t_printf("%s the parent handle is the same as the child handle!!!!\n", __FUNCTION__);
} else {
t_printf("%s the parent handle is different form the child handle.\n", __FUNCTION__);
}
close(fd[0]);
close(fd[1]);
}
/**
* @tc.name : dlopen_ns_randomization_0500
* @tc.desc : Repeatedly calling the dlopen_ns interface to load the dynamic library,
* and calling dlclose to unload each time
* @tc.level : Level3
*/
static void dlopen_ns_randomization_0500(void)
{
Dl_namespace dlns;
dlns_init(&dlns, __FUNCTION__);
dlns_create(&dlns, "./");
void *handles[TEST_COUNTS] = {0};
void *handle = 0;
int i = TEST_COUNTS;
do {
handle = dlopen_ns(&dlns, LIB_NAME, RTLD_NOW);
handles[--i] = handle;
if (handle) {
dlclose(handle);
}
} while (i);
if (check_address(handles, TEST_COUNTS)) {
t_printf("%s handles are randomized\n", __FUNCTION__);
} else {
t_printf("%s exists the same handle!!!!\n", __FUNCTION__);
}
}
/**
* @tc.name : dlopen_ns_randomization_0700
* @tc.desc : Different processes call the dlopen_ns interface to load dynamic libraries
* @tc.level : Level3
*/
static void dlopen_ns_randomization_0700(void)
{
Dl_namespace dlns;
dlns_init(&dlns, __FUNCTION__);
dlns_create(&dlns, "./");
void *parent_handle = 0;
void *get_child_handle = 0;
int fd[PIPE_FD];
if (pipe(fd) < 0) {
t_printf("%s create pipe error!\n", __FUNCTION__);
return;
}
pid_t pid = fork();
if (pid == 0) {
void *child_handle = dlopen_ns(&dlns, LIB_NAME, RTLD_NOW);
t_printf("%s child handle is %p \n", __FUNCTION__, child_handle);
if (child_handle) {
dlclose(child_handle);
}
write(fd[1], &child_handle, sizeof(void *));
exit(0);
}
parent_handle = dlopen_ns(&dlns, LIB_NAME, RTLD_NOW);
t_printf("%s parent handle is %p \n", __FUNCTION__, parent_handle);
if (parent_handle) {
dlclose(parent_handle);
}
int status;
waitpid(pid, &status, 0);
read(fd[0], &get_child_handle, sizeof(void *));
t_printf("%s get child handle is %p\n", __FUNCTION__, get_child_handle);
if (parent_handle == get_child_handle) {
t_printf("%s the parent handle is the same as the child handle!!!!\n", __FUNCTION__);
} else {
t_printf("%s the parent handle is different form the child handle.\n", __FUNCTION__);
}
close(fd[0]);
close(fd[1]);
}
/**
* @tc.name : dlsym_randomization_0100
* @tc.desc : Repeatedly calling the dlsym interface to get symbol address, and calling dlclose to unload each time
* @tc.level : Level3
*/
static void dlsym_randomization_0100(void)
{
void *handle = dlopen(LIB_NAME, RTLD_NOW);
if (!handle) {
t_printf("%s dlopen failed: %s\n", __FUNCTION__, LIB_NAME);
return;
};
void *sym = dlsym(handle, "test");
t_printf("%s symbol address is %p\n", __FUNCTION__, sym);
dlclose(handle);
}
/**
* @tc.name : dlsym_randomization_0200
* @tc.desc : Different processes call the dlsym interface to get symbol address
* @tc.level : Level3
*/
static void dlsym_randomization_0200(void)
{
void *parent_handle = 0;
void *child_handle = 0;
void *parent_sym = 0;
void *child_sym = 0;
void *get_child_sym = 0;
int fd[PIPE_FD];
if (pipe(fd) < 0) {
t_printf("%s create pipe error!\n", __FUNCTION__);
return;
}
pid_t pid = fork();
if (pid == 0) {
child_handle = dlopen(LIB_NAME_A, RTLD_NOW);
if (!child_handle) {
t_printf("%s child process dlopen failed: %s\n", __FUNCTION__, LIB_NAME_A);
exit(-1);
}
child_sym = dlsym(child_handle, "test");
t_printf("%s child sym is %p\n", __FUNCTION__, child_sym);
write(fd[1], &child_sym, sizeof(void *));
dlclose(child_handle);
exit(0);
}
parent_handle = dlopen(LIB_NAME_A, RTLD_NOW);
if (!parent_handle) {
t_printf("%s parent process dlopen failed: %s\n", __FUNCTION__, LIB_NAME_A);
return;
};
parent_sym = dlsym(parent_handle, "test");
t_printf("%s parent sym is %p\n", __FUNCTION__, parent_sym);
dlclose(parent_handle);
int status;
waitpid(pid, &status, 0);
read(fd[0], &get_child_sym, sizeof(void *));
if (parent_sym == get_child_sym) {
t_printf("%s the parent sym is the same as the child sym!!!!\n", __FUNCTION__);
} else {
t_printf("%s the parent sym is different form the child sym.\n", __FUNCTION__);
}
close(fd[0]);
close(fd[1]);
}
TEST_FUNC test_cases[] = {
dlopen_randomization_0500,
dlopen_randomization_0700,
dlopen_ext_randomization_0500,
dlopen_ext_randomization_0700,
dlopen_ns_randomization_0500,
dlopen_ns_randomization_0700,
dlsym_randomization_0100,
dlsym_randomization_0200,
};
int main(int argc, char *argv[])
{
size_t case_counts = sizeof test_cases / sizeof(TEST_FUNC);
for (size_t case_num = 0; case_num < case_counts; case_num++) {
test_cases[case_num]();
}
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 <dlfcn_ext.h>
#include <errno.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include "functionalext.h"
#define NUM_OF_BYTE 8
#define BASE_NUM 11
#define TEST_COUNTS 32
const char *LIB_NAME = "./libldso_randomization_dep.so";
const char *LIB_NAME_A = "./libldso_randomization_dep_a.so";
typedef void (*TEST_FUNC)(void);
int g_test = BASE_NUM;
extern void test_f(void)
{
++g_test;
}
/**
* @tc.name : dlopen_randomization_0100
* @tc.desc : Call the dlopen interface to load a valid dynamic library
* @tc.level : Level0
*/
static void dlopen_randomization_0100(void)
{
void *handle = dlopen(LIB_NAME, RTLD_NOW);
EXPECT_PTRNE(__FUNCTION__, handle, 0);
if (handle) {
EXPECT_EQ(__FUNCTION__, dlclose(handle), 0);
}
}
/**
* @tc.name : dlopen_randomization_0200
* @tc.desc : Call the dlopen interface to load NULL
* @tc.level : Level1
*/
static void dlopen_randomization_0200(void)
{
void *handle = dlopen(NULL, RTLD_NOW);
EXPECT_PTRNE(__FUNCTION__, handle, 0);
if (!handle) {
return;
};
int *i = dlsym(handle, "g_test");
EXPECT_PTRNE(__FUNCTION__, i, 0);
if (!i) {
dlclose(handle);
return;
}
EXPECT_EQ(__FUNCTION__, BASE_NUM, *i);
TEST_FUNC test = (TEST_FUNC)dlsym(handle, "test_f");
EXPECT_PTRNE(__FUNCTION__, test, 0);
if (!test) {
dlclose(handle);
return;
}
test();
EXPECT_EQ(__FUNCTION__, BASE_NUM + 1, g_test);
g_test = BASE_NUM;
dlclose(handle);
}
/**
* @tc.name : dlopen_randomization_0300
* @tc.desc : Call the dlopen interface to load a invalid dynamic library
* @tc.level : Level2
*/
static void dlopen_randomization_0300(void)
{
void *handle = dlopen("test_invaild.so", RTLD_NOW);
EXPECT_PTREQ(__FUNCTION__, handle, 0);
if (handle) {
dlclose(handle);
}
}
/**
* @tc.name : dlopen_randomization_0400
* @tc.desc : Repeatedly calling the dlopen interface to load the same dynamic library
* @tc.level : Level1
*/
static void dlopen_randomization_0400(void)
{
void *ori_handle = dlopen(LIB_NAME, RTLD_NOW);
void *handle = 0;
EXPECT_PTRNE(__FUNCTION__, ori_handle, 0);
if (!ori_handle) {
return;
}
int i = TEST_COUNTS;
while (i--) {
handle = dlopen(LIB_NAME, RTLD_NOW);
EXPECT_PTREQ(__FUNCTION__, ori_handle, handle);
}
i = TEST_COUNTS + 1;
while (i--) {
dlclose(ori_handle);
}
}
/**
* @tc.name : dlopen_randomization_0600
* @tc.desc : Call the dlopen interface to load a invalid dynamic library,
* and call the dlsym interface to get symbol address
* @tc.level : Level1
*/
static void dlopen_randomization_0600(void)
{
void *handle;
int *i;
TEST_FUNC test;
handle = dlopen(LIB_NAME, RTLD_NOW);
EXPECT_PTRNE(__FUNCTION__, handle, 0);
if (!handle) {
return;
}
i = dlsym(handle, "i");
EXPECT_PTRNE(__FUNCTION__, i, 0);
if (!i) {
dlclose(handle);
return;
}
EXPECT_EQ(__FUNCTION__, *i, 0);
test = (TEST_FUNC)dlsym(handle, "test");
EXPECT_PTRNE(__FUNCTION__, test, 0);
if (!test) {
dlclose(handle);
return;
}
test();
EXPECT_EQ(__FUNCTION__, *i, 1);
dlclose(handle);
}
/**
* @tc.name : dlopen_ext_randomization_0100
* @tc.desc : Call the dlopen_ext interface to load a valid dynamic library
* @tc.level : Level0
*/
static void dlopen_ext_randomization_0100(void)
{
dl_extinfo extinfo = {0};
void *handle = dlopen_ext(LIB_NAME_A, RTLD_NOW, &extinfo);
EXPECT_PTRNE(__FUNCTION__, handle, 0);
if (handle) {
EXPECT_EQ(__FUNCTION__, dlclose(handle), 0);
}
}
/**
* @tc.name : dlopen_ext_randomization_0200
* @tc.desc : Call the dlopen interface to load NULL
* @tc.level : Level1
*/
static void dlopen_ext_randomization_0200(void)
{
dl_extinfo extinfo = {0};
void *handle = dlopen_ext(NULL, RTLD_NOW, &extinfo);
EXPECT_PTRNE(__FUNCTION__, handle, 0);
if (!handle) {
return;
}
int *i = dlsym(handle, "g_test");
EXPECT_PTRNE(__FUNCTION__, i, 0);
if (!i) {
dlclose(handle);
return;
}
EXPECT_EQ(__FUNCTION__, BASE_NUM, *i);
TEST_FUNC test = (TEST_FUNC)dlsym(handle, "test_f");
EXPECT_PTRNE(__FUNCTION__, test, 0);
if (!test) {
dlclose(handle);
return;
}
test();
EXPECT_EQ(__FUNCTION__, BASE_NUM + 1, g_test);
g_test = BASE_NUM;
dlclose(handle);
}
/**
* @tc.name : dlopen_ext_randomization_0300
* @tc.desc : Call the dlopen interface to load a invalid dynamic library
* @tc.level : Level2
*/
static void dlopen_ext_randomization_0300(void)
{
dl_extinfo extinfo = {0};
void *handle = dlopen_ext("test_invaild.so", RTLD_NOW, &extinfo);
EXPECT_PTREQ(__FUNCTION__, handle, 0);
if (handle) {
dlclose(handle);
}
}
/**
* @tc.name : dlopen_ext_randomization_0400
* @tc.desc : Repeatedly calling the dlopen_ext interface to load the same dynamic library
* @tc.level : Level1
*/
static void dlopen_ext_randomization_0400(void)
{
dl_extinfo extinfo = {0};
void *ori_handle = dlopen_ext(LIB_NAME, RTLD_NOW, &extinfo);
void *handle = 0;
EXPECT_PTRNE(__FUNCTION__, ori_handle, 0);
if (!ori_handle) {
return;
}
int i = TEST_COUNTS;
while (i--) {
handle = dlopen_ext(LIB_NAME, RTLD_NOW, &extinfo);
EXPECT_PTREQ(__FUNCTION__, ori_handle, handle);
}
i = TEST_COUNTS + 1;
while (i--) {
dlclose(ori_handle);
}
}
/**
* @tc.name : dlopen_ext_randomization_0600
* @tc.desc : Call the dlopen_ext interface to load a invalid dynamic library,
* and call the dlsym interface to get symbol address
* @tc.level : Level1
*/
static void dlopen_ext_randomization_0600(void)
{
void *handle;
int *i;
TEST_FUNC test;
dl_extinfo extinfo = {0};
handle = dlopen_ext(LIB_NAME, RTLD_NOW, &extinfo);
EXPECT_PTRNE(__FUNCTION__, handle, 0);
if (!handle) {
return;
}
i = dlsym(handle, "i");
EXPECT_PTRNE(__FUNCTION__, i, 0);
if (!i) {
dlclose(handle);
return;
}
EXPECT_EQ(__FUNCTION__, *i, 0);
test = (TEST_FUNC)dlsym(handle, "test");
EXPECT_PTRNE(__FUNCTION__, test, 0);
if (!test) {
dlclose(handle);
return;
}
test();
EXPECT_EQ(__FUNCTION__, *i, 1);
dlclose(handle);
}
/**
* @tc.name : dlopen_ext_randomization_0800
* @tc.desc : The flag of dl_extinfo is set to DL_EXT_RESERVED_ADDRESS_RECURSIVE,
* call the dlopen_ext interface to load a valid dynamic library
* @tc.level : Level1
*/
static void dlopen_ext_randomization_0800(void)
{
dl_extinfo extinfo = {
.flag = DL_EXT_RESERVED_ADDRESS_RECURSIVE,
};
void *handle = dlopen_ext(NULL, RTLD_NOW, &extinfo);
EXPECT_PTRNE(__FUNCTION__, handle, 0);
if (!handle) {
return;
}
int *i = dlsym(handle, "g_test");
EXPECT_PTRNE(__FUNCTION__, i, 0);
if (!i) {
dlclose(handle);
return;
}
EXPECT_EQ(__FUNCTION__, BASE_NUM, *i);
TEST_FUNC test = (TEST_FUNC)dlsym(handle, "test_f");
EXPECT_PTRNE(__FUNCTION__, test, 0);
if (!test) {
dlclose(handle);
return;
}
test();
EXPECT_EQ(__FUNCTION__, BASE_NUM + 1, *i);
g_test = BASE_NUM;
dlclose(handle);
}
/**
* @tc.name : dlopen_ns_randomization_0100
* @tc.desc : Call the dlopen_ns interface to load a valid dynamic library
* @tc.level : Level0
*/
static void dlopen_ns_randomization_0100(void)
{
Dl_namespace dlns;
dlns_init(&dlns, __FUNCTION__);
dlns_create(&dlns, "./");
void *handle = dlopen_ns(&dlns, LIB_NAME, RTLD_NOW);
EXPECT_PTRNE(__FUNCTION__, handle, 0);
if (handle) {
EXPECT_EQ(__FUNCTION__, dlclose(handle), 0);
}
}
/**
* @tc.name : dlopen_ns_randomization_0200
* @tc.desc : Call the dlopen_ns interface to load NULL
* @tc.level : Level1
*/
static void dlopen_ns_randomization_0200(void)
{
Dl_namespace dlns;
dlns_init(&dlns, __FUNCTION__);
dlns_create(&dlns, "./");
void *handle = dlopen_ns(&dlns, NULL, RTLD_NOW);
EXPECT_PTRNE(__FUNCTION__, handle, 0);
if (!handle) {
return;
}
int *i = dlsym(handle, "g_test");
EXPECT_PTRNE(__FUNCTION__, i, 0);
if (!i) {
dlclose(handle);
return;
}
EXPECT_EQ(__FUNCTION__, BASE_NUM, *i);
TEST_FUNC test = (TEST_FUNC)dlsym(handle, "test_f");
EXPECT_PTRNE(__FUNCTION__, test, 0);
if (!test) {
dlclose(handle);
return;
}
test();
EXPECT_EQ(__FUNCTION__, BASE_NUM + 1, g_test);
g_test = BASE_NUM;
dlclose(handle);
}
/**
* @tc.name : dlopen_ns_randomization_0300
* @tc.desc : Call the dlopen_ns interface to load a invalid dynamic library
* @tc.level : Level2
*/
static void dlopen_ns_randomization_0300(void)
{
Dl_namespace dlns;
dlns_init(&dlns, __FUNCTION__);
dlns_create(&dlns, "./");
void *handle = dlopen_ns(&dlns, "test_invaild.so", RTLD_NOW);
EXPECT_PTREQ(__FUNCTION__, handle, 0);
if (handle) {
dlclose(handle);
}
}
/**
* @tc.name : dlopen_ns_randomization_0400
* @tc.desc : Repeatedly calling the dlopen_ns interface to load the same dynamic library
* @tc.level : Level1
*/
static void dlopen_ns_randomization_0400(void)
{
Dl_namespace dlns;
dlns_init(&dlns, __FUNCTION__);
dlns_create(&dlns, "./");
void *ori_handle = dlopen_ns(&dlns, LIB_NAME, RTLD_NOW);
void *handle = 0;
EXPECT_PTRNE(__FUNCTION__, ori_handle, 0);
if (!ori_handle) {
return;
}
int i = TEST_COUNTS;
while (i--) {
handle = dlopen_ns(&dlns, LIB_NAME, RTLD_NOW);
EXPECT_PTREQ(__FUNCTION__, ori_handle, handle);
}
i = TEST_COUNTS + 1;
while (i--) {
dlclose(ori_handle);
}
}
/**
* @tc.name : dlopen_ns_randomization_0600
* @tc.desc : Call the dlopen_ns interface to load a invalid dynamic library,
* and call the dlsym interface to get symbol address
* @tc.level : Level1
*/
static void dlopen_ns_randomization_0600(void)
{
Dl_namespace dlns;
dlns_init(&dlns, __FUNCTION__);
dlns_create(&dlns, "./");
void *handle;
int *i;
TEST_FUNC test;
handle = dlopen_ns(&dlns, LIB_NAME, RTLD_NOW);
EXPECT_PTRNE(__FUNCTION__, handle, 0);
if (!handle) {
return;
}
i = dlsym(handle, "i");
EXPECT_PTRNE(__FUNCTION__, i, 0);
if (!i) {
dlclose(handle);
return;
}
EXPECT_EQ(__FUNCTION__, *i, 0);
test = (TEST_FUNC)dlsym(handle, "test");
EXPECT_PTRNE(__FUNCTION__, test, 0);
if (!test) {
dlclose(handle);
return;
}
test();
EXPECT_EQ(__FUNCTION__, *i, 1);
dlclose(handle);
}
/**
* @tc.name : dlsym_randomization_0300
* @tc.desc : Call the dlsym interface to get symbol address
* @tc.level : Level2
*/
static void dlsym_randomization_0300(void)
{
void *sym = dlsym(NULL, "test");
EXPECT_FALSE(__FUNCTION__, sym);
}
/**
* @tc.name : dlclose_randomization_0100
* @tc.desc : Call the dlclose interface to unload dynamic library
* @tc.level : Level2
*/
static void dlclose_randomization_0100(void)
{
int ret = dlclose(NULL);
EXPECT_EQ(__FUNCTION__, -1, ret);
}
TEST_FUNC test_cases[] = {
dlopen_randomization_0100,
dlopen_randomization_0200,
dlopen_randomization_0300,
dlopen_randomization_0400,
dlopen_randomization_0600,
dlopen_ext_randomization_0100,
dlopen_ext_randomization_0200,
dlopen_ext_randomization_0300,
dlopen_ext_randomization_0400,
dlopen_ext_randomization_0600,
dlopen_ext_randomization_0800,
dlopen_ns_randomization_0100,
dlopen_ns_randomization_0200,
dlopen_ns_randomization_0300,
dlopen_ns_randomization_0400,
dlopen_ns_randomization_0600,
dlsym_randomization_0300,
dlclose_randomization_0100,
};
int main(int argc, char *argv[])
{
size_t case_counts = sizeof(test_cases) / sizeof(TEST_FUNC);
for (size_t case_num = 0; case_num < case_counts; case_num++) {
test_cases[case_num]();
}
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.
import("../../../test_template.gni")
test_unittest("dlopen_ext_relro_test") {
target_dir = "functionalext/relro"
}
ohos_shared_library("dlopen_ext_relro_dso") {
include_dirs = [ "." ]
sources = [ "dlopen_ext_relro_dso.c" ]
output_name = "dlopen_ext_relro_dso"
output_extension = "so"
subsystem_name = "musl"
part_name = "libc-test-lib"
}
group("functionalext_relro_test") {
testonly = true
deps = [
":dlopen_ext_relro_dso",
":dlopen_ext_relro_test",
]
}
/*
* 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 <stdio.h>
void relro(void)
{
printf ("hello world!\n");
}
\ 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 <dlfcn_ext.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/wait.h>
#include <stdbool.h>
#include "functionalext.h"
#include "test.h"
#define LIB_NAME "./libdlopen_ext_relro_dso.so"
#define RELRO_FILE_PATH "./TemporaryFile-XXXXXX"
const char* RELRO_NS_PATH = "./";
const int RELRO_INVALID_FLAG = 0x20;
const int LIB_PATH_SIZE = 512;
typedef void(*TEST_FUN)(void);
static int create_temp_relro_file(char *path)
{
int fd = -1;
#if defined(_WIN32)
fd = mkstemp(path, strlen(RELRO_FILE_PATH) + 1);
#else
fd = mkstemp(path);
#endif
if (fd != -1) {
close(fd);
}
return 0;
}
static void tear_down(const int fd, const char* relro_path)
{
if (fd != -1) {
close(fd);
}
if (relro_path != NULL) {
unlink(relro_path);
}
}
static void clear_handle(void *handle)
{
if (handle) {
dlclose(handle);
}
}
static void test_wirte_relro_file(const char* lib, const int relro_fd)
{
pid_t pid = fork();
if (pid == 0) {
dl_extinfo extinfo = {
.flag = DL_EXT_WIRTE_INFO,
.relro_fd = relro_fd,
};
void* handle = dlopen_ext(lib, RTLD_NOW, &extinfo);
EXPECT_PTRNE(__FUNCTION__, handle, NULL);
clear_handle(handle);
exit(-1);
}
int status = 0;
waitpid(pid, &status, 0);
}
/**
* @tc.name : dlopen_ext_relro_0100
* @tc.desc : extinfo is NULL, call dlopen_ext, return handle is not NULL.
* @tc.level : Level 1
*/
static void dlopen_ext_relro_0100(void)
{
void* handle = dlopen_ext(LIB_NAME, RTLD_NOW, NULL);
EXPECT_PTRNE(__FUNCTION__, handle, NULL);
clear_handle(handle);
}
/**
* @tc.name : dlopen_ext_relro_0200
* @tc.desc : extinfo flag is 0, call dlopen_ext, return handle is not NULL.
* @tc.level : Level 1
*/
static void dlopen_ext_relro_0200(void)
{
dl_extinfo extinfo = {
.flag = 0,
.relro_fd = -1,
};
void* handle = dlopen_ext(LIB_NAME, RTLD_NOW, &extinfo);
EXPECT_PTRNE(__FUNCTION__, handle, NULL);
clear_handle(handle);
}
/**
* @tc.name : dlopen_ext_relro_0300
* @tc.desc : extinfo flag is 20, call dlopen_ext, return handle is NULL.
* @tc.level : Level 2
*/
static void dlopen_ext_relro_0300(void)
{
dl_extinfo extinfo = {
.flag = RELRO_INVALID_FLAG,
.relro_fd = -1,
};
void* handle = dlopen_ext(LIB_NAME, RTLD_NOW, &extinfo);
EXPECT_EQ(__FUNCTION__, handle, NULL);
clear_handle(handle);
}
/**
* @tc.name : dlopen_ext_relro_0400
* @tc.desc : extinfo flag is DL_EXT_WIRTE_INFO, relro_fd is valid, call dlopen_ext, return handle is not NULL.
* @tc.level : Level 1
*/
static void dlopen_ext_relro_0400(void)
{
char relro_file[] = RELRO_FILE_PATH;
if (create_temp_relro_file(relro_file) < 0) {
return;
}
int relro_fd = open(relro_file, O_RDWR | O_TRUNC | O_CLOEXEC);
if (relro_fd < 0) {
t_error("%s relro file %s open failed error is : %s \n", __FUNCTION__, relro_file, dlerror());
return;
}
dl_extinfo extinfo = {
.flag = DL_EXT_WIRTE_INFO,
.relro_fd = relro_fd,
};
void* handle = dlopen_ext(LIB_NAME, RTLD_NOW, &extinfo);
EXPECT_PTRNE(__FUNCTION__, handle, NULL);
tear_down(relro_fd, relro_file);
clear_handle(handle);
}
/**
* @tc.name : dlopen_ext_relro_0500
* @tc.desc : extinfo flag is DL_EXT_WIRTE_INFO, relro_fd is not valid, call dlopen_ext, return handle is NULL.
* @tc.level : Level 2
*/
static void dlopen_ext_relro_0500(void)
{
dl_extinfo extinfo = {
.flag = DL_EXT_WIRTE_INFO,
.relro_fd = -1,
};
void* handle = dlopen_ext(LIB_NAME, RTLD_NOW, &extinfo);
EXPECT_EQ(__FUNCTION__, handle, NULL);
clear_handle(handle);
}
/**
* @tc.name : dlopen_ext_relro_0600
* @tc.desc : extinfo flag is DL_EXT_USE_INFO, relro_fd is valid, call dlopen_ext, return handle is not NULL.
* @tc.level : Level 1
*/
static void dlopen_ext_relro_0600(void)
{
char relro_file[] = RELRO_FILE_PATH;
if (create_temp_relro_file(relro_file) < 0) {
return;
}
int relro_fd = open(relro_file, O_RDWR | O_TRUNC | O_CLOEXEC);
if (relro_fd < 0) {
t_error("%s relro file %s open failed error is : %s \n", __FUNCTION__, relro_file, dlerror());
return;
}
test_wirte_relro_file(LIB_NAME, relro_fd);
dl_extinfo extinfo = {
.flag = DL_EXT_USE_INFO,
.relro_fd = relro_fd,
};
void* handle = dlopen_ext(LIB_NAME, RTLD_NOW, &extinfo);
EXPECT_PTRNE(__FUNCTION__, handle, NULL);
tear_down(relro_fd, relro_file);
clear_handle(handle);
}
/**
* @tc.name : dlopen_ext_relro_0700
* @tc.desc : extinfo flag is DL_EXT_USE_INFO, relro_fd is not valid, call dlopen_ext, return handle is NULL.
* @tc.level : Level 2
*/
static void dlopen_ext_relro_0700(void)
{
char relro_file[] = RELRO_FILE_PATH;
if (create_temp_relro_file(relro_file) < 0) {
return;
}
int relro_fd = open(relro_file, O_RDWR | O_TRUNC | O_CLOEXEC);
if (relro_fd < 0) {
t_error("%s relro file %s open failed error is : %s \n", __FUNCTION__, relro_file, dlerror());
return;
}
test_wirte_relro_file(LIB_NAME, relro_fd);
dl_extinfo extinfo = {
.flag = DL_EXT_USE_INFO,
.relro_fd = -1,
};
void* handle = dlopen_ext(LIB_NAME, RTLD_NOW, &extinfo);
EXPECT_EQ(__FUNCTION__, handle, NULL);
tear_down(relro_fd, relro_file);
clear_handle(handle);
}
/**
* @tc.name : dlopen_ext_relro_0800
* @tc.desc : extinfo flag is DL_EXT_WIRTE_INFO | DL_EXT_RESERVED_ADDRESS_RECURSIVE, relro_fd is valid,
* call dlopen_ext, return handle is not NULL.
* @tc.level : Level 1
*/
static void dlopen_ext_relro_0800(void)
{
char relro_file[] = RELRO_FILE_PATH;
if (create_temp_relro_file(relro_file) < 0) {
return;
}
int relro_fd = open(relro_file, O_RDWR | O_TRUNC | O_CLOEXEC);
if (relro_fd < 0) {
t_error("%s relro file %s open failed error is : %s \n", __FUNCTION__, relro_file, dlerror());
return;
}
dl_extinfo extinfo = {
.flag = DL_EXT_WIRTE_INFO | DL_EXT_RESERVED_ADDRESS_RECURSIVE,
.relro_fd = relro_fd,
};
void* handle = dlopen_ext(LIB_NAME, RTLD_NOW, &extinfo);
EXPECT_PTRNE(__FUNCTION__, handle, NULL);
tear_down(relro_fd, relro_file);
clear_handle(handle);
}
/**
* @tc.name : dlopen_ext_relro_0900
* @tc.desc : extinfo flag is DL_EXT_WIRTE_INFO, relro_fd is not valid, call dlopen_ext, return handle is NULL.
* @tc.level : Level 2
*/
static void dlopen_ext_relro_0900(void)
{
dl_extinfo extinfo = {
.flag = DL_EXT_WIRTE_INFO | DL_EXT_RESERVED_ADDRESS_RECURSIVE,
.relro_fd = -1,
};
void* handle = dlopen_ext(LIB_NAME, RTLD_NOW, &extinfo);
EXPECT_EQ(__FUNCTION__, handle, NULL);
clear_handle(handle);
}
/**
* @tc.name : dlopen_ext_relro_1000
* @tc.desc : extinfo flag is DL_EXT_USE_INFO | DL_EXT_RESERVED_ADDRESS_RECURSIVE, relro_fd is valid,
* call dlopen_ext, return handle is not NULL.
* @tc.level : Level 1
*/
static void dlopen_ext_relro_1000(void)
{
char relro_file[] = RELRO_FILE_PATH;
if (create_temp_relro_file(relro_file) < 0) {
return;
}
int relro_fd = open(relro_file, O_RDWR | O_TRUNC | O_CLOEXEC);
if (relro_fd < 0) {
t_error("%s relro file %s open failed error is : %s \n", __FUNCTION__, relro_file, dlerror());
return;
}
test_wirte_relro_file(LIB_NAME, relro_fd);
dl_extinfo extinfo = {
.flag = DL_EXT_USE_INFO | DL_EXT_RESERVED_ADDRESS_RECURSIVE,
.relro_fd = relro_fd,
};
void* handle = dlopen_ext(LIB_NAME, RTLD_NOW, &extinfo);
EXPECT_PTRNE(__FUNCTION__, handle, NULL);
tear_down(relro_fd, relro_file);
clear_handle(handle);
}
/**
* @tc.name : dlopen_ext_relro_1100
* @tc.desc : extinfo flag is DL_EXT_USE_INFO | DL_EXT_RESERVED_ADDRESS_RECURSIVE, relro_fd is not valid,
* call dlopen_ext, return handle is NULL.
* @tc.level : Level 2
*/
static void dlopen_ext_relro_1100(void)
{
char relro_file[] = RELRO_FILE_PATH;
if (create_temp_relro_file(relro_file) < 0) {
return;
}
int relro_fd = open(relro_file, O_RDWR | O_TRUNC | O_CLOEXEC);
if (relro_fd < 0) {
t_error("%s relro file %s open failed error is : %s \n", __FUNCTION__, relro_file, dlerror());
return;
}
test_wirte_relro_file(LIB_NAME, relro_fd);
dl_extinfo extinfo = {
.flag = DL_EXT_USE_INFO | DL_EXT_RESERVED_ADDRESS_RECURSIVE,
.relro_fd = -1,
};
void* handle = dlopen_ext(LIB_NAME, RTLD_NOW, &extinfo);
EXPECT_EQ(__FUNCTION__, handle, NULL);
tear_down(relro_fd, relro_file);
clear_handle(handle);
}
/**
* @tc.name : dlopen_ext_relro_1200
* @tc.desc : extinfo flag is DL_EXT_USE_INFO when relro file do not wirte,
* when call dlopen_ext, return handle is NULL.
* @tc.level : Level 2
*/
static void dlopen_ext_relro_1200(void)
{
char relro_file[] = RELRO_FILE_PATH;
if (create_temp_relro_file(relro_file) < 0) {
return;
}
int relro_fd = open(relro_file, O_RDWR | O_TRUNC | O_CLOEXEC);
if (relro_fd < 0) {
t_error("%s relro file %s open failed error is : %s \n", __FUNCTION__, relro_file, dlerror());
return;
}
dl_extinfo extinfo = {
.flag = DL_EXT_USE_INFO,
.relro_fd = relro_fd,
};
void* handle = dlopen_ext(LIB_NAME, RTLD_NOW, &extinfo);
EXPECT_EQ(__FUNCTION__, handle, NULL);
tear_down(relro_fd, relro_file);
clear_handle(handle);
}
/**
* @tc.name : dlopen_ext_relro_1500
* @tc.desc : extinfo flag is DL_EXT_USE_INFO | DL_EXT_WIRTE_INFO, relro_fd is valid,
* call dlopen_ext, return handle is not NULL.
* @tc.level : Level 1
*/
static void dlopen_ext_relro_1500(void)
{
char relro_file[] = RELRO_FILE_PATH;
if (create_temp_relro_file(relro_file) < 0) {
return;
}
int relro_fd = open(relro_file, O_RDWR | O_TRUNC | O_CLOEXEC);
if (relro_fd < 0) {
t_error("%s relro file %s open failed error is : %s \n", __FUNCTION__, relro_file, dlerror());
return;
}
test_wirte_relro_file(LIB_NAME, relro_fd);
dl_extinfo extinfo = {
.flag = DL_EXT_WIRTE_INFO | DL_EXT_USE_INFO,
.relro_fd = relro_fd,
};
void* handle = dlopen_ext(LIB_NAME, RTLD_NOW, &extinfo);
EXPECT_PTRNE(__FUNCTION__, handle, NULL);
tear_down(relro_fd, relro_file);
clear_handle(handle);
}
TEST_FUN g_fun_array[] = {
dlopen_ext_relro_0100,
dlopen_ext_relro_0200,
dlopen_ext_relro_0300,
dlopen_ext_relro_0400,
dlopen_ext_relro_0500,
dlopen_ext_relro_0600,
dlopen_ext_relro_0700,
dlopen_ext_relro_0800,
dlopen_ext_relro_0900,
dlopen_ext_relro_1000,
dlopen_ext_relro_1100,
dlopen_ext_relro_1200,
dlopen_ext_relro_1500,
};
int main(int argc, char *argv[])
{
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
...@@ -20,4 +20,6 @@ functionalext_list = [ ...@@ -20,4 +20,6 @@ functionalext_list = [
"trace:functionalext_trace_test", "trace:functionalext_trace_test",
"dlns:dlns_test", "dlns:dlns_test",
"info:functionalext_info_test", "info:functionalext_info_test",
"ldso_randomization:functionalext_ldso_randomization_test",
"relro:functionalext_relro_test",
] ]
...@@ -118,6 +118,18 @@ template("test_unittest") { ...@@ -118,6 +118,18 @@ template("test_unittest") {
} }
} }
if (target_dir == "functionalext/ldso_randomization") {
if (target_name == "ldso_randomization_test") {
ldflags += [ "-Wl,--export-dynamic,-rpath=./" ]
}
if (target_name == "ldso_randomization_manual") {
ldflags += [ "-Wl,-rpath=./" ]
}
include_dirs += [ "//${test_dir}/src/functionalext/common" ]
}
if (target_dir == "musl") { if (target_dir == "musl") {
cflags_c += [ "-w" ] cflags_c += [ "-w" ]
...@@ -151,6 +163,14 @@ template("test_unittest") { ...@@ -151,6 +163,14 @@ template("test_unittest") {
[ "//${root_out_dir}/${test_lib_dir}/libtls_get_new-dtv_dso.so" ] [ "//${root_out_dir}/${test_lib_dir}/libtls_get_new-dtv_dso.so" ]
} }
} }
if (target_dir == "functionalext/relro") {
if (target_name == "dlopen_ext_relro_test") {
include_dirs += [ "//${test_dir}/src/functionalext/common" ]
ldflags += [ "-Wl,-rpath=./" ]
}
}
} }
} }
......
...@@ -1561,6 +1561,7 @@ musl_src_ldso = [ ...@@ -1561,6 +1561,7 @@ musl_src_ldso = [
"ldso/namespace.c", "ldso/namespace.c",
"ldso/ns_config.c", "ldso/ns_config.c",
"ldso/strops.c", "ldso/strops.c",
"ldso/dynlink_rand.c",
] ]
if (musl_arch == "arm") { if (musl_arch == "arm") {
...@@ -1769,6 +1770,7 @@ musl_inc_root_files = [ ...@@ -1769,6 +1770,7 @@ musl_inc_root_files = [
"include/ctype.h", "include/ctype.h",
"include/dirent.h", "include/dirent.h",
"include/dlfcn.h", "include/dlfcn.h",
"include/dlfcn_ext.h",
"include/elf.h", "include/elf.h",
"include/endian.h", "include/endian.h",
"include/err.h", "include/err.h",
...@@ -1871,6 +1873,7 @@ musl_src_porting_file = [ ...@@ -1871,6 +1873,7 @@ musl_src_porting_file = [
"include/trace/trace_marker.h", "include/trace/trace_marker.h",
"include/unistd.h", "include/unistd.h",
"include/dlfcn.h", "include/dlfcn.h",
"include/dlfcn_ext.h",
"src/internal/musl_log.h", "src/internal/musl_log.h",
"src/info/application_target_sdk_version.c", "src/info/application_target_sdk_version.c",
"src/info/device_api_version.c", "src/info/device_api_version.c",
...@@ -1919,6 +1922,8 @@ musl_src_porting_file = [ ...@@ -1919,6 +1922,8 @@ musl_src_porting_file = [
"ldso/namespace.c", "ldso/namespace.c",
"ldso/ns_config.c", "ldso/ns_config.c",
"ldso/strops.c", "ldso/strops.c",
"ldso/dynlink_rand.c",
"ldso/dynlink_rand.h",
"src/thread/pthread_create.c", "src/thread/pthread_create.c",
"src/sched/sched_cpualloc.c", "src/sched/sched_cpualloc.c",
"src/signal/signal.c", "src/signal/signal.c",
......
/*
* 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 DLFCN_EXT_H
#define DLFCN_EXT_H
#include <dlfcn.h>
#ifdef __cplusplus
extern "C" {
#endif
/* for dl_extinfo flag */
#define DL_EXT_WIRTE_INFO 0x1
#define DL_EXT_USE_INFO 0x2
#define DL_EXT_RESERVED_ADDRESS_RECURSIVE 0x4
/** Mask of valid bits. */
#define DL_EXT_VALID_FLAG_BITS (DL_EXT_WIRTE_INFO | DL_EXT_USE_INFO | DL_EXT_RESERVED_ADDRESS_RECURSIVE)
typedef struct {
int flag;
int relro_fd;
} dl_extinfo;
/**
* @brief Loads the dynamic shared object (shared library) file with the extended feature.
* If extinfo is NULL, it is equivalent to dlopen.
* If DL_EXT_WIRTE_INFO is set in extinfo, the GNU RELRO section will be written to relro_fd and allowed to
* reused by other process loading the same library at the same address.
* IF DL_EXT_USE_INFO is set in extinfo, the GNU RELRO section written in relro_fd will be reused.
* @param file Equivalent to the argument of dlopen.
* @param mode Equivalent to the argument of dlopen.
* @param extinfo Indicates the dl_extinfo struct.
* @return Returns a non-NULL handle for the loaded object on success. On error returns NULL.
*/
void *dlopen_ext(const char *file, int mode, const dl_extinfo *extinfo);
#ifdef __cplusplus
}
#endif
#endif
此差异已折叠。
/*
* 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 "dynlink_rand.h"
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/random.h>
#include <unistd.h>
#define HANDLE_INCREASE 2
#define TASK_BASE_CAPACITY 8
// linked list node for handle randomization
struct handle_node {
struct handle_node *next;
void *handle;
struct dso *dso;
};
// linked list for handle randomization
static struct handle_node *handle_map_list = NULL;
static bool is_first_stage_init(void)
{
static bool ret;
ret = (getpid() == 1 && access("/proc/self/exe", F_OK) == -1);
return ret;
}
void *add_handle_node(void *handle, struct dso *dso)
{
struct handle_node *node = malloc(sizeof(*node));
if (!node) {
return NULL;
}
node->handle = handle;
node->dso = dso;
node->next = handle_map_list;
handle_map_list = node;
return node;
}
struct dso *find_dso_by_handle(void *handle)
{
struct handle_node *node = handle_map_list;
while (node) {
if (node->handle == handle) {
return node->dso;
}
node = node->next;
}
return NULL;
}
static void *find_handle_by_dso(struct dso *dso)
{
struct handle_node *node = handle_map_list;
while (node) {
if (node->dso == dso) {
return node->handle;
}
node = node->next;
}
return 0;
}
void remove_handle_node(void *handle)
{
struct handle_node *node = handle_map_list;
struct handle_node *pre_node = NULL;
while (node) {
if (node->handle == handle) {
if (pre_node) {
pre_node->next = node->next;
} else {
handle_map_list = node->next;
}
free(node);
return;
} else {
pre_node = node;
node = node->next;
}
}
}
static void *gen_handle(void)
{
uintptr_t handle = 0;
do {
if (!is_first_stage_init()) {
getrandom(&handle, sizeof handle, GRND_RANDOM);
} else {
handle += HANDLE_INCREASE;
}
} while (find_dso_by_handle((void *)handle) || handle == 0);
return (void *)handle;
}
void *assign_valid_handle(struct dso *p)
{
void *handle = find_handle_by_dso(p);
if (handle == 0) {
handle = gen_handle();
if (!add_handle_node(handle, p)) {
handle = 0;
}
}
return handle;
}
struct loadtasks *create_loadtasks(void)
{
struct loadtasks *tasks = malloc(sizeof(struct loadtasks));
if (tasks) {
tasks->array = NULL;
tasks->capacity = 0;
tasks->length = 0;
return tasks;
}
return NULL;
}
bool append_loadtasks(struct loadtasks *tasks, struct loadtask *item)
{
if (tasks->length + 1 > tasks->capacity) {
size_t new_cap = 0;
new_cap = tasks->capacity + TASK_BASE_CAPACITY;
void *realloced = NULL;
if (tasks->array) {
realloced = realloc(tasks->array, new_cap * sizeof(struct loadtask *));
} else {
realloced = malloc(TASK_BASE_CAPACITY * sizeof(struct loadtask *));
}
if (realloced) {
tasks->array = realloced;
tasks->capacity = new_cap;
} else {
return false;
}
}
tasks->array[tasks->length] = item;
tasks->length += 1;
return true;
}
void free_task(struct loadtask *task)
{
if (task == NULL) {
return;
}
if (task->allocated_buf) {
free(task->allocated_buf);
task->allocated_buf = NULL;
}
if (task->dyn_map_len) {
munmap(task->dyn_map, task->dyn_map_len);
task->dyn_map = NULL;
task->dyn_map_len = 0;
}
if (task->str_map_len) {
munmap(task->str_map, task->str_map_len);
task->str_map = NULL;
task->str_map_len = 0;
}
if (task->fd != -1 && task->fd) {
close(task->fd);
task->fd = -1;
}
free(task);
}
struct loadtask *get_loadtask(struct loadtasks *tasks, size_t index)
{
if (tasks && tasks->array && (index < tasks->length)) {
return tasks->array[index];
} else {
return NULL;
}
}
void free_loadtasks(struct loadtasks *tasks)
{
if (tasks) {
if (tasks->length) {
for (int i = 0; i < tasks->length; i++) {
free_task(get_loadtask(tasks, i));
}
tasks->length = 0;
}
if (tasks->array) {
free(tasks->array);
tasks->array = NULL;
}
tasks->capacity = 0;
free(tasks);
}
}
void shuffle_loadtasks(struct loadtasks *tasks)
{
size_t index = 0;
struct loadtask *task = NULL;
if (is_first_stage_init()) {
return;
}
for (size_t i = 0; i < tasks->length; i++) {
getrandom(&index, sizeof index, GRND_RANDOM);
index %= tasks->length;
task = tasks->array[i];
tasks->array[i] = tasks->array[index];
tasks->array[index] = task;
}
}
struct loadtask *create_loadtask(const char *name, struct dso *needed_by, ns_t *ns, bool check_inherited)
{
struct loadtask *task = calloc(1, sizeof(struct loadtask));
if (!task) {
return NULL;
}
task->name = name;
task->needed_by = needed_by;
task->namespace = ns;
task->check_inherited = check_inherited;
return task;
}
/*
* 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 DYNLINK_RAND_H
#define DYNLINK_RAND_H
#include <limits.h>
#include <stdbool.h>
#include <stddef.h>
#include "libc.h"
#include "dynlink.h"
#include "namespace.h"
#ifdef __cplusplus
extern "C" {
#endif
struct dso;
#define READ_ELF_LENGTH 896
// load library context
hidden struct loadtask {
// parameters
const char *name;
struct dso *needed_by;
ns_t *namespace;
bool check_inherited;
bool isloaded;
// variables for load library
char buf[PATH_MAX + 1];
const char *pathname;
struct dso *p;
int fd;
// variables for map library
Ehdr ehdr_buf[(READ_ELF_LENGTH + sizeof(Ehdr)) / sizeof(Ehdr)];
void *allocated_buf;
size_t phsize;
Ehdr *eh;
Phdr *ph0;
size_t dyn;
size_t tls_image;
void *dyn_map;
size_t dyn_map_len;
size_t *dyn_addr;
void *str_map;
size_t str_map_len;
char *str_addr;
struct tls_module tls;
};
// dynamic array for loadtask
hidden struct loadtasks {
struct loadtask **array;
size_t capacity;
size_t length;
};
hidden void *add_handle_node(void *handle, struct dso *dso);
hidden struct dso *find_dso_by_handle(void *handle);
hidden void remove_handle_node(void *handle);
hidden void *assign_valid_handle(struct dso *p);
hidden struct loadtasks *create_loadtasks(void);
hidden bool append_loadtasks(struct loadtasks *tasks, struct loadtask *item);
hidden void free_task(struct loadtask *task);
hidden struct loadtask *get_loadtask(struct loadtasks *tasks, size_t index);
hidden void free_loadtasks(struct loadtasks *tasks);
hidden void shuffle_loadtasks(struct loadtasks *tasks);
hidden struct loadtask *create_loadtask(const char *name, struct dso *needed_by, ns_t *ns, bool check_inherited);
#ifdef __cplusplus
}
#endif
#endif
\ No newline at end of file
...@@ -13,11 +13,11 @@ ...@@ -13,11 +13,11 @@
* limitations under the License. * limitations under the License.
*/ */
#include <musl_log.h>
#ifndef LD_LOG_H #ifndef LD_LOG_H
#define LD_LOG_H #define LD_LOG_H
#include <musl_log.h>
#define LD_LOG_ERROR 1 #define LD_LOG_ERROR 1
#define LD_LOG_WARNING 2 #define LD_LOG_WARNING 2
#define LD_LOG_INFO 4 #define LD_LOG_INFO 4
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册