Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
Third Party Musl
提交
731da990
T
Third Party Musl
项目概览
OpenHarmony
/
Third Party Musl
1 年多 前同步成功
通知
37
Star
125
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
T
Third Party Musl
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
731da990
编写于
2月 28, 2023
作者:
R
root
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feature: mallocng memory addresses random and pointer confusion
Close #I6I6M9 Signed-off-by:
N
wangchen
<
wangchen240@huawei.com
>
上级
a31ed2a6
变更
9
隐藏空白更改
内联
并排
Showing
9 changed file
with
318 addition
and
110 deletion
+318
-110
README_zh.md
README_zh.md
+1
-0
libc-test/src/regression/malloc-encode-pointer.c
libc-test/src/regression/malloc-encode-pointer.c
+129
-39
libc-test/src/regression/malloc-modify-pointer.c
libc-test/src/regression/malloc-modify-pointer.c
+45
-33
libc-test/src/regression/malloc-multi-thread-performance.c
libc-test/src/regression/malloc-multi-thread-performance.c
+20
-5
libc-test/src/regression/malloc-random.c
libc-test/src/regression/malloc-random.c
+67
-0
libc-test/src/regression/malloc-safe-unlink.c
libc-test/src/regression/malloc-safe-unlink.c
+45
-19
libc-test/src/regression/test_src_regression.gni
libc-test/src/regression/test_src_regression.gni
+1
-0
porting/linux/user/src/malloc/mallocng/malloc.c
porting/linux/user/src/malloc/mallocng/malloc.c
+9
-13
porting/linux/user/src/malloc/mallocng/meta.h
porting/linux/user/src/malloc/mallocng/meta.h
+1
-1
未找到文件。
README_zh.md
浏览文件 @
731da990
...
...
@@ -28,6 +28,7 @@ musl编译框架时编译,使用BUILD.gn进行配置编译。
-
提供加载器namespace机制
-
OHOS容器中能够运行依赖bionic的库
-
musl全球化接口适配locale数据能力
-
mallocng堆内存分配器安全增强,默认开启meta指针混淆。地址随机化通过MALLOC_SECURE_ALL宏开关。可在编译命令中增加--gn-args="musl_secure_level=3"开启
等。在新增特性基础上,也进行了对于musl接口功能的完善与错误的修复。
...
...
libc-test/src/regression/malloc-encode-pointer.c
浏览文件 @
731da990
...
...
@@ -12,57 +12,147 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <malloc.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>
#include <errno.h>
#include <string.h>
#include "test.h"
int
main
(
int
argc
,
char
*
argv
[])
#define UNIT 16
#define OFF_OFFSET 2
#define FIRST_OFFSET (-4)
#define FIRST_OFF_OFFSET 8
#define MALLOC_SIZE_S (10 * sizeof(uintptr_t))
#define MALLOC_SIZE_L (50 * sizeof(uintptr_t))
#define TEST_NUM 512
struct
meta_in
{
struct
meta_in
*
prev
,
*
next
;
uintptr_t
*
mem
;
};
struct
group_in
{
struct
meta_in
*
meta
;
};
static
struct
group_in
*
get_group
(
const
uint8_t
*
p
)
{
uintptr_t
*
c0
=
(
uintptr_t
*
)
malloc
(
sizeof
(
uintptr_t
)
*
10
);
if
(
!
c0
)
{
t_error
(
"Malloc c0 failed: %s
\n
"
,
strerror
(
errno
));
return
-
1
;
int
offset
=
*
(
const
uint16_t
*
)(
p
-
OFF_OFFSET
);
if
(
p
[
FIRST_OFFSET
])
{
offset
=
*
(
uint32_t
*
)(
p
-
FIRST_OFF_OFFSET
)
;
}
/* Malloc dividing chunk to avoid combination of neighbouring freed chunk */
void
*
d0
=
malloc
(
sizeof
(
uintptr_t
)
*
10
);
if
(
!
d0
)
{
t_error
(
"Malloc d0 failed: %s
\n
"
,
strerror
(
errno
));
return
-
1
;
struct
group_in
*
base
=
(
void
*
)(
p
-
UNIT
*
offset
-
UNIT
);
return
base
;
}
static
void
handler
(
int
s
)
{
}
static
int
child
(
void
)
{
void
*
d0
;
void
*
d1
;
struct
group_in
*
g0
=
NULL
;
struct
group_in
*
g1
=
NULL
;
struct
group_in
*
g2
=
NULL
;
for
(
int
i
=
0
;
i
<
TEST_NUM
;
++
i
)
{
d0
=
malloc
(
MALLOC_SIZE_S
);
if
(
!
d0
)
{
t_error
(
"Malloc d0 failed: %s
\n
"
,
strerror
(
errno
));
return
-
1
;
}
g0
=
get_group
(
d0
);
d1
=
malloc
(
MALLOC_SIZE_L
);
if
(
!
d1
)
{
t_error
(
"Malloc d1 failed: %s
\n
"
,
strerror
(
errno
));
return
-
1
;
}
g1
=
get_group
(
d1
);
if
((
uintptr_t
)
g0
->
meta
->
mem
==
(
uintptr_t
)
g0
)
t_error
(
"encoding pointer is equal to real pointer 1
\n
"
);
if
((
uintptr_t
)
g1
->
meta
->
mem
==
(
uintptr_t
)
g1
)
t_error
(
"encoding pointer is equal to real pointer 2
\n
"
);
if
((
uintptr_t
)
g0
->
meta
->
prev
->
next
==
(
uintptr_t
)
g0
->
meta
->
mem
)
t_error
(
"encoding pointer is equal to real pointer 1
\n
"
);
if
((
uintptr_t
)
g1
->
meta
->
prev
->
next
==
(
uintptr_t
)
g1
->
meta
->
mem
)
t_error
(
"encoding pointer is equal to real pointer 2
\n
"
);
free
(
d0
);
free
(
d1
);
}
return
0
;
}
static
pid_t
start_child
(
void
)
{
pid_t
pid
;
int
ret
;
pid
=
fork
();
if
(
pid
==
0
)
{
ret
=
child
();
t_error
(
"child process normally out with %d
\n
"
,
ret
);
return
ret
;
}
return
pid
;
}
uintptr_t
*
c1
=
(
uintptr_t
*
)
malloc
(
sizeof
(
uintptr_t
)
*
10
);
if
(
!
c1
)
{
t_error
(
"Malloc c1 failed: %s
\n
"
,
strerror
(
errno
));
int
main
(
int
argc
,
char
*
argv
[])
{
sigset_t
set
;
int
status
;
pid_t
pid
;
int
flag
=
0
;
sigemptyset
(
&
set
);
sigaddset
(
&
set
,
SIGCHLD
);
sigprocmask
(
SIG_BLOCK
,
&
set
,
0
);
signal
(
SIGCHLD
,
handler
);
pid
=
start_child
();
if
(
pid
==
-
1
)
{
t_error
(
"%s fork failed: %s
\n
"
,
argv
[
0
],
strerror
(
errno
));
return
-
1
;
}
/* Malloc dividing chunk to avoid combination of neighbouring freed chunk */
void
*
d1
=
malloc
(
sizeof
(
uintptr_t
)
*
10
);
if
(
!
d1
)
{
t_error
(
"Malloc d1 failed: %s
\n
"
,
strerror
(
errno
));
if
(
sigtimedwait
(
&
set
,
0
,
&
(
struct
timespec
){
5
,
0
})
==
-
1
)
{
/* Wait for 5 seconds */
if
(
errno
==
EAGAIN
)
flag
=
1
;
else
t_error
(
"%s sigtimedwait failed: %s
\n
"
,
argv
[
0
],
strerror
(
errno
));
if
(
kill
(
pid
,
SIGKILL
)
==
-
1
)
t_error
(
"%s kill failed: %s
\n
"
,
argv
[
0
],
strerror
(
errno
));
}
if
(
waitpid
(
pid
,
&
status
,
0
)
!=
pid
)
{
t_error
(
"%s waitpid failed: %s
\n
"
,
argv
[
0
],
strerror
(
errno
));
return
-
1
;
}
/* Free the chunk, with same size, they're put into the same bin */
/* -------- -------- --------
* | c0 | | c1 | | bin |
* -->| next |----->| next |----->| next |-----
* | | prev |<-----| prev |<-----| prev | |
* | ------- ------- ------- |
* --------------------------------------------
*/
free
(
c0
);
free
(
c1
);
uintptr_t
xoraddr
=
c0
[
0
];
/* Get the next of c0 */
uintptr_t
realaddr
=
(
uintptr_t
)((
char
*
)
c1
-
sizeof
(
uintptr_t
)
*
2
);
if
(
xoraddr
==
realaddr
)
{
t_error
(
"encoding pointer is equal to real pointer
\n
"
);
if
(
flag
)
{
t_error
(
"Child process time out
\n
"
);
}
free
(
d0
);
free
(
d1
);
return
t_status
;
if
(
WIFSIGNALED
(
status
))
{
if
(
WTERMSIG
(
status
)
!=
SIGSEGV
&&
WTERMSIG
(
status
)
!=
SIGILL
)
{
t_error
(
"%s child process out with %s
\n
"
,
argv
[
0
],
strsignal
(
WTERMSIG
(
status
)));
return
-
1
;
}
}
else
{
t_error
(
"%s child process finished normally
\n
"
,
argv
[
0
]);
}
return
0
;
}
libc-test/src/regression/malloc-modify-pointer.c
浏览文件 @
731da990
...
...
@@ -25,49 +25,61 @@ static void handler(int s)
{
}
volatile
uintptr_t
*
p0
;
volatile
uintptr_t
*
p1
;
volatile
void
*
tmp
[
512
];
uint8_t
*
p0
;
uint8_t
*
p1
;
#define UNIT 16
#define OFF_OFFSET 2
#define FIRST_OFFSET (-4)
#define FIRST_OFF_OFFSET 8
#define MALLOC_SIZE_S (10 * sizeof(uintptr_t))
#define TEST_NUM 512
volatile
void
*
tmp
[
TEST_NUM
];
struct
meta_in
{
struct
meta_in
*
prev
,
*
next
;
uintptr_t
*
mem
;
};
struct
group_in
{
struct
meta_in
*
meta
;
};
static
struct
group_in
*
get_group
(
uint8_t
*
p
)
{
int
offset
=
*
(
uint16_t
*
)(
p
-
OFF_OFFSET
);
if
(
p
[
FIRST_OFFSET
])
{
offset
=
*
(
uint32_t
*
)(
p
-
FIRST_OFF_OFFSET
);
}
struct
group_in
*
base
=
(
void
*
)(
p
-
UNIT
*
offset
-
UNIT
);
return
base
;
}
static
int
child
(
void
)
{
p0
=
(
uintptr_t
*
)
malloc
(
10
*
sizeof
(
uintptr_t
));
struct
group_in
*
g
=
NULL
;
p0
=
(
uint8_t
*
)
malloc
(
MALLOC_SIZE_S
);
if
(
!
p0
)
{
t_error
(
"Malloc failed:%s
\n
"
,
strerror
(
errno
));
return
-
1
;
}
/* Malloc a dividing chunk to avoid combination of neighbouring freed chunk */
tmp
[
0
]
=
malloc
(
10
*
sizeof
(
uintptr_t
));
/* Malloc another chunk to get a key */
p1
=
(
uintptr_t
*
)
malloc
(
10
*
sizeof
(
uintptr_t
));
if
(
!
p1
)
{
t_error
(
"Malloc failed:%s
\n
"
,
strerror
(
errno
));
return
-
1
;
}
/* Malloc a dividing chunk to avoid combination of neighbouring freed chunk */
tmp
[
0
]
=
malloc
(
10
*
sizeof
(
uintptr_t
));
free
((
void
*
)
p0
);
free
((
void
*
)
p1
);
uintptr_t
*
fake_ptr
=
(
uintptr_t
*
)((
uintptr_t
)((
char
*
)
p1
-
sizeof
(
size_t
)
*
2
)
^
(
uintptr_t
)
p0
[
0
]);
p0
[
0
]
=
(
uintptr_t
)
fake_ptr
;
p1
[
0
]
=
(
uintptr_t
)
fake_ptr
;
/*
* The init procedure makes the freelist unpredictable. To make sure to trigger the ivalid ptr
* acess, here we create as many chunks as possible to make sure there are enough chunks in
* bin[j] of size "10 * sizeof(uintptr_t)". Basically this is heap spray.
*/
for
(
int
i
=
0
;
i
<
512
;
++
i
)
{
tmp
[
i
]
=
malloc
(
10
*
sizeof
(
uintptr_t
));
tmp
[
0
]
=
malloc
(
MALLOC_SIZE_S
);
g
=
get_group
(
p0
);
free
((
void
*
)
tmp
[
0
]);
g
->
meta
+=
1
;
for
(
int
i
=
0
;
i
<
TEST_NUM
;
++
i
)
{
tmp
[
i
]
=
malloc
(
MALLOC_SIZE_S
);
}
/*
* When freelist quarantine is on, the modifiy-pointer chunk maybe in quarantine. So here we
* need free the pointer.
*/
for
(
int
i
=
0
;
i
<
512
;
++
i
)
{
for
(
int
i
=
0
;
i
<
TEST_NUM
;
++
i
)
{
free
((
void
*
)
tmp
[
i
]);
}
return
0
;
...
...
libc-test/src/regression/malloc-multi-thread-performance.c
浏览文件 @
731da990
...
...
@@ -8,16 +8,27 @@
#define THREAD_MAX_N 8
#define SIZE_ALIGN (4 * sizeof(size_t))
#define THRESHOLD (0x1c00 * SIZE_ALIGN)
#define ITER_TIME 20
#define MMAP_THRESHOLD 131052
#define FREE_CYCLE 16
#define THRESHOLD (MMAP_THRESHOLD / 16)
#define ITER_TIME 80
#define NANOSEC_PER_SEC 1e9
#define MALLOC_TIME (ITER_TIME * (THRESHOLD / (SIZE_ALIGN + 1)))
void
free_all
(
void
**
ptr
)
{
for
(
int
j
=
0
;
j
<
FREE_CYCLE
;
j
++
)
{
free
(
ptr
[
j
]);
}
}
void
*
func
(
void
*
arg
)
{
int
*
val
=
(
int
*
)
arg
;
cpu_set_t
mask
;
struct
timespec
ts
[
2
];
int
num
=
0
;
void
*
ptr
[
FREE_CYCLE
];
CPU_ZERO
(
&
mask
);
CPU_SET
(
0
,
&
mask
);
...
...
@@ -28,13 +39,17 @@ void *func(void *arg)
for
(
int
i
=
0
;
i
<
ITER_TIME
;
++
i
)
{
for
(
size_t
size
=
0
;
size
<
THRESHOLD
;
size
+=
SIZE_ALIGN
+
1
)
{
void
*
ptr
=
malloc
(
size
);
if
(
!
ptr
)
{
if
(
num
==
FREE_CYCLE
)
{
free_all
(
ptr
);
num
=
0
;
}
ptr
[
num
]
=
malloc
(
size
);
if
(
!
ptr
[
num
])
{
t_error
(
"Thread %d malloc failed for size %u
\n
"
,
*
val
,
size
);
*
val
=
errno
;
return
NULL
;
}
free
(
ptr
)
;
num
++
;
}
}
...
...
libc-test/src/regression/malloc-random.c
0 → 100644
浏览文件 @
731da990
/*
* 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 <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <errno.h>
#include "test.h"
#define MALLOC_SIZE_S 0x20
#define MALLOC_SIZE_L 0x40
#define IDX_IN_CHUNK (-3)
static
int
get_slotnum
(
uint8_t
*
p
)
{
return
(
p
[
IDX_IN_CHUNK
]
&
0x1f
);
}
int
main
(
void
)
{
void
*
p
=
malloc
(
MALLOC_SIZE_S
);
void
*
q
=
malloc
(
MALLOC_SIZE_S
);
void
*
r
=
malloc
(
MALLOC_SIZE_S
);
if
(
!
p
||
!
q
||
!
r
)
t_error
(
"malloc returned NULL
\n
"
);
int
slot_p_1
=
get_slotnum
((
uint8_t
*
)
p
);
int
slot_q_1
=
get_slotnum
((
uint8_t
*
)
q
);
int
slot_r_1
=
get_slotnum
((
uint8_t
*
)
r
);
free
(
p
);
free
(
q
);
free
(
r
);
p
=
malloc
(
MALLOC_SIZE_L
);
q
=
malloc
(
MALLOC_SIZE_L
);
r
=
malloc
(
MALLOC_SIZE_L
);
if
(
!
p
||
!
q
||
!
r
)
t_error
(
"malloc returned NULL
\n
"
);
int
slot_p_2
=
get_slotnum
((
uint8_t
*
)
p
);
int
slot_q_2
=
get_slotnum
((
uint8_t
*
)
q
);
int
slot_r_2
=
get_slotnum
((
uint8_t
*
)
r
);
free
(
p
);
free
(
q
);
free
(
r
);
if
(((
slot_p_1
+
1
)
==
slot_q_1
)
&&
((
slot_q_1
+
1
)
==
slot_r_1
))
{
if
(((
slot_p_2
+
1
)
==
slot_q_2
)
&&
((
slot_q_2
+
1
)
==
slot_r_2
))
t_error
(
"malloc(0) random error
\n
"
);
}
return
t_status
;
}
libc-test/src/regression/malloc-safe-unlink.c
浏览文件 @
731da990
...
...
@@ -21,6 +21,34 @@
#include <string.h>
#include "test.h"
#define UNIT 16
#define OFF_OFFSET 2
#define FIRST_OFFSET (-4)
#define FIRST_OFF_OFFSET 8
#define MALLOC_SIZE_S 50
#define MALLOC_SIZE_L 100
#define TEST_NUM 512
struct
meta_in
{
struct
meta_in
*
prev
,
*
next
;
uintptr_t
*
mem
;
};
struct
group_in
{
struct
meta_in
*
meta
;
};
static
struct
group_in
*
get_group
(
const
uint8_t
*
p
)
{
int
offset
=
*
(
const
uint16_t
*
)(
p
-
OFF_OFFSET
);
if
(
p
[
FIRST_OFFSET
])
{
offset
=
*
(
uint32_t
*
)(
p
-
FIRST_OFF_OFFSET
);
}
struct
group_in
*
base
=
(
void
*
)(
p
-
UNIT
*
offset
-
UNIT
);
return
base
;
}
static
void
handler
(
int
s
)
{
}
...
...
@@ -38,31 +66,29 @@ int set_devide_chunk(size_t size)
static
int
child
(
void
)
{
uint
ptr_t
*
c
;
uint
ptr_t
*
temp
;
uint
8_t
*
c1
;
uint
8_t
*
c2
;
/* Set first dividing chunk */
if
(
set_devide_chunk
(
sizeof
(
size_t
)))
return
-
1
;
uint8_t
*
temp
;
struct
group_in
*
g1
=
NULL
;
struct
group_in
*
g2
=
NULL
;
/*
* The init procedure makes the freelist unpredictable. To make sure trigger the safe-unlink
* check, Here we create as many chunks as possible to make sure there are enough chunks in
* bin[0] and malloc again. Basically this is heap spray.
*/
for
(
int
i
=
0
;
i
<
512
;
++
i
)
{
if
(
set_devide_chunk
(
sizeof
(
size_t
)))
for
(
int
i
=
0
;
i
<
TEST_NUM
;
++
i
)
{
c1
=
(
uint8_t
*
)
malloc
(
MALLOC_SIZE_S
);
if
(
!
c1
)
{
t_error
(
"Malloc failed: %s
\n
"
,
strerror
(
errno
));
return
-
1
;
c
=
(
uintptr_t
*
)
malloc
(
sizeof
(
uintptr_t
));
if
(
!
c
)
{
}
g1
=
get_group
(
c1
);
c2
=
(
uint8_t
*
)
malloc
(
MALLOC_SIZE_L
);
if
(
!
c2
)
{
t_error
(
"Malloc failed: %s
\n
"
,
strerror
(
errno
));
return
-
1
;
}
free
(
c
);
/* exchange the prev and next pointer */
uintptr_t
temp
=
c
[
0
];
c
[
0
]
=
c
[
1
];
c
[
1
]
=
temp
;
g2
=
get_group
(
c2
);
g2
->
meta
=
g1
->
meta
;
free
(
c2
);
free
(
c1
);
}
return
0
;
...
...
libc-test/src/regression/test_src_regression.gni
浏览文件 @
731da990
...
...
@@ -81,6 +81,7 @@ regression_list = [
if (musl_secure_level >= 3) {
regression_list += [
"malloc-random",
"malloc-overflow-check",
"malloc-uaf-check",
]
...
...
porting/linux/user/src/malloc/mallocng/malloc.c
浏览文件 @
731da990
...
...
@@ -19,31 +19,27 @@ extern int je_mallopt(int param, int value);
#ifdef MALLOC_SECURE_ALL
#include <fcntl.h>
#define RANDOM_BUFFER_LEN
64
#define RANDOM_BUFFER_LEN
512
static
uint8_t
buffer
[
RANDOM_BUFFER_LEN
]
=
{
0
};
static
size_t
ri
=
RANDOM_BUFFER_LEN
;
static
void
*
get_ri
(
size_t
width
)
static
uint8_t
get_random8
(
)
{
if
((
ri
+
width
>
RANDOM_BUFFER_LEN
)
||
(
buffer
[
0
]
==
0
))
{
uint8_t
num
;
if
((
ri
>=
RANDOM_BUFFER_LEN
)
||
(
buffer
[
0
]
==
0
))
{
int
fd
=
open
(
"/dev/urandom"
,
O_RDONLY
);
if
(
fd
<
0
)
{
return
(
void
*
)
buffer
;
num
=
(
uint8_t
)
get_random_secret
();
return
num
;
}
read
(
fd
,
buffer
,
RANDOM_BUFFER_LEN
);
close
(
fd
);
ri
=
0
;
}
ri
+=
width
;
return
(
void
*
)(
buffer
+
ri
-
width
);
}
static
uint8_t
get_random8
()
{
uint8_t
*
pr
=
(
uint8_t
*
)
get_ri
(
sizeof
(
uint8_t
));
return
*
pr
;
num
=
buffer
[
ri
];
ri
++
;
return
num
;
}
static
int
get_randomIdx
(
int
avail_mask
,
int
last_idx
)
...
...
porting/linux/user/src/malloc/mallocng/meta.h
浏览文件 @
731da990
...
...
@@ -75,7 +75,7 @@ int is_allzero(void *);
static
inline
void
*
encode_ptr
(
void
*
ptr
,
uint64_t
key
)
{
#ifdef MALLOC_FREELIST_HARDENED
return
(
void
*
)((
uintptr_t
)
ptr
^
(
key
|
1
)
);
return
(
void
*
)((
uintptr_t
)
ptr
^
key
);
#else
(
void
)
key
;
return
ptr
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录