Skip to content

Commit e44ad40

Browse files
authored
[+] add protection for memory pool (#387)
1 parent 20b163d commit e44ad40

File tree

6 files changed

+162
-2
lines changed

6 files changed

+162
-2
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ option (XQC_ENABLE_RENO "enable reno" OFF)
1313
option (XQC_ENABLE_UNLIMITED "enable unlimited cc" OFF)
1414
option (XQC_ENABLE_MP_INTEROP "enable MPQUIC interop" OFF)
1515
option (XQC_NO_PID_PACKET_PROCESS "do not expose path_id in xqc_engine_packet_process" OFF)
16+
option (XQC_PROTECT_POOL_MEM "enable write protection for pool memory (for debug)" OFF)
1617

1718
if(NOT CMAKE_BUILD_TYPE)
1819
set(CMAKE_BUILD_TYPE Release)

include/xquic/xquic.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1257,6 +1257,9 @@ typedef struct xqc_conn_settings_s {
12571257
*/
12581258
xqc_bool_t is_interop_mode;
12591259

1260+
#ifdef XQC_PROTECT_POOL_MEM
1261+
uint8_t protect_pool_mem;
1262+
#endif
12601263

12611264
} xqc_conn_settings_t;
12621265

scripts/case_test.sh

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -853,6 +853,18 @@ else
853853
echo "$errlog"
854854
fi
855855

856+
clear_log
857+
echo -e "send 10M data (mempool protected) ...\c"
858+
result=`${CLIENT_BIN} -s 10240000 -l e -E -x 600 |grep ">>>>>>>> pass"`
859+
errlog=`grep_err_log`
860+
echo "$result"
861+
if [ -z "$errlog" ] && [ "$result" == ">>>>>>>> pass:1" ]; then
862+
case_print_result "send_10M_data_mempool_protected" "pass"
863+
else
864+
case_print_result "send_10M_data_mempool_protected" "fail"
865+
echo "$errlog"
866+
fi
867+
856868
clear_log
857869
echo -e "send 4K every time ...\c"
858870
result=`${CLIENT_BIN} -s 10240000 -l e -E -x 49|grep ">>>>>>>> pass"`
@@ -1166,12 +1178,13 @@ fi
11661178
clear_log
11671179
killall test_server
11681180
echo -e "client Initial dcid corruption ...\c"
1181+
sleep 1
11691182
${SERVER_BIN} -l d -e > /dev/null &
11701183
sleep 1
11711184
client_print_res=`${CLIENT_BIN} -s 1024000 -l d -t 1 -x 22 -E | grep ">>>>>>>> pass"`
11721185
errlog=`grep_err_log`
11731186
server_log_res=`grep "decrypt payload error" slog`
1174-
server_conn_cnt=`grep "xqc_conn_create" slog | grep -v "tra_parameters_set" | wc -l`
1187+
server_conn_cnt=`grep "xqc_conn_create" slog | grep -v "tra_parameters_set" | grep -v "mempool" | wc -l`
11751188
echo "$client_print_res"
11761189
if [ "$client_print_res" != "" ] && [ "$server_log_res" != "" ] && [ $server_conn_cnt -eq 2 ]; then
11771190
case_print_result "client_initial_dcid_corruption" "pass"

src/common/xqc_memory_pool.h

Lines changed: 123 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,19 @@
77

88
#include <string.h>
99
#include <stdint.h>
10+
#include <xquic/xquic.h>
1011

1112
#include "src/common/xqc_malloc.h"
1213

14+
#ifdef XQC_PROTECT_POOL_MEM
15+
#ifndef XQC_SYS_WINDOWS
16+
#include <stdlib.h>
17+
#include <unistd.h>
18+
#include <sys/mman.h>
19+
#include <assert.h>
20+
#endif
21+
#endif
22+
1323
/* Interfaces:
1424
* xqc_memory_pool_t *xqc_create_pool(size_t size)
1525
* void xqc_destroy_pool(xqc_memory_pool_t* pool)
@@ -36,19 +46,78 @@ typedef struct xqc_memory_pool_s {
3646
xqc_memory_block_t *current;
3747
xqc_memory_large_t *large; /* large chunk list */
3848
size_t max;
49+
#ifdef XQC_PROTECT_POOL_MEM
50+
xqc_bool_t protect_block;
51+
size_t page_size;
52+
#endif
3953
} xqc_memory_pool_t;
4054

4155
#define XQC_MAX_MALLOC_FROM_POOL (4096)
4256

57+
#ifdef XQC_PROTECT_POOL_MEM
58+
static inline void *
59+
xqc_mempool_malloc_protected(size_t size, size_t page_sz)
60+
{
61+
#ifndef XQC_SYS_WINDOWS
62+
int ret;
63+
void *ptr = NULL;
64+
ret = posix_memalign(&ptr, page_sz, page_sz + size);
65+
if (ret != 0) {
66+
return NULL;
67+
}
68+
ret = mprotect(ptr, page_sz, PROT_READ);
69+
if (ret != 0) {
70+
xqc_free(ptr);
71+
return NULL;
72+
}
73+
return (void*)((char*)ptr + page_sz);
74+
#else
75+
return xqc_malloc(size);
76+
#endif
77+
}
78+
79+
static inline void
80+
xqc_mempool_free_protected(void* ptr, size_t page_sz) {
81+
#ifndef XQC_SYS_WINDOWS
82+
void *start;
83+
int ret;
84+
start = (void*)((char*)ptr - page_sz);
85+
ret = mprotect(start, page_sz, PROT_READ | PROT_WRITE | PROT_EXEC);
86+
assert(ret == 0);
87+
xqc_free(start);
88+
#else
89+
xqc_free(ptr);
90+
#endif
91+
}
92+
#endif
4393

94+
#ifdef XQC_PROTECT_POOL_MEM
95+
static inline xqc_memory_pool_t *
96+
xqc_create_pool(size_t size, xqc_bool_t protect_block)
97+
#else
4498
static inline xqc_memory_pool_t *
4599
xqc_create_pool(size_t size)
100+
#endif
46101
{
47102
if (size <= sizeof(xqc_memory_pool_t)) {
48103
return NULL;
49104
}
50105

106+
#ifdef XQC_PROTECT_POOL_MEM
107+
char *m;
108+
#ifndef XQC_SYS_WINDOWS
109+
size_t page_sz = sysconf(_SC_PAGESIZE);
110+
#else
111+
size_t page_sz = 4096;
112+
#endif
113+
if (protect_block) {
114+
m = xqc_mempool_malloc_protected(size, page_sz);
115+
} else {
116+
m = xqc_malloc(size);
117+
}
118+
#else
51119
char *m = xqc_malloc(size);
120+
#endif
52121
if (m == NULL) {
53122
return NULL;
54123
}
@@ -58,6 +127,10 @@ xqc_create_pool(size_t size)
58127
pool->block.end = m + size;
59128
pool->block.failed = 0;
60129
pool->block.next = NULL;
130+
#ifdef XQC_PROTECT_POOL_MEM
131+
pool->protect_block = protect_block;
132+
pool->page_size = page_sz;
133+
#endif
61134

62135
pool->current = &pool->block;
63136
pool->large = NULL;
@@ -76,23 +149,61 @@ xqc_destroy_pool(xqc_memory_pool_t *pool)
76149
while (block) {
77150
xqc_memory_block_t *p = block;
78151
block = block->next;
152+
#ifdef XQC_PROTECT_POOL_MEM
153+
if (pool->protect_block) {
154+
xqc_mempool_free_protected(p, pool->page_size);
155+
156+
} else {
157+
xqc_free(p);
158+
}
159+
#else
79160
xqc_free(p);
161+
#endif
80162
}
81163

82164
xqc_memory_large_t *large = pool->large;
83165
while (large) {
84166
xqc_memory_large_t * p = large;
85167
large = large->next;
168+
#ifdef XQC_PROTECT_POOL_MEM
169+
if (pool->protect_block) {
170+
xqc_mempool_free_protected(p, pool->page_size);
171+
172+
} else {
173+
xqc_free(p);
174+
}
175+
#else
86176
xqc_free(p);
177+
#endif
87178
}
88179

89-
xqc_free(pool);
180+
#ifdef XQC_PROTECT_POOL_MEM
181+
if (pool->protect_block) {
182+
xqc_mempool_free_protected(pool, pool->page_size);
183+
184+
} else {
185+
xqc_free(pool);
186+
}
187+
#else
188+
xqc_free(pool);
189+
#endif
90190
}
91191

92192
static inline void *
93193
xqc_palloc_large(xqc_memory_pool_t *pool, size_t size)
94194
{
195+
#ifdef XQC_PROTECT_POOL_MEM
196+
xqc_memory_large_t *p;
197+
if (pool->protect_block) {
198+
p = xqc_mempool_malloc_protected(size + sizeof(xqc_memory_large_t), pool->page_size);
199+
200+
} else {
201+
p = xqc_malloc(size + sizeof(xqc_memory_large_t));
202+
}
203+
#else
95204
xqc_memory_large_t *p = xqc_malloc(size + sizeof(xqc_memory_large_t));
205+
#endif
206+
96207
if (p == NULL) {
97208
return NULL;
98209
}
@@ -112,7 +223,18 @@ xqc_palloc_block(xqc_memory_pool_t *pool, size_t size)
112223
{
113224
size_t psize = pool->block.end - (char *)pool;
114225

226+
#ifdef XQC_PROTECT_POOL_MEM
227+
char *m;
228+
if (pool->protect_block) {
229+
m = xqc_mempool_malloc_protected(psize, pool->page_size);
230+
231+
} else {
232+
m = xqc_malloc(psize);
233+
}
234+
#else
115235
char *m = xqc_malloc(psize);
236+
#endif
237+
116238
if (m == NULL) {
117239
return NULL;
118240
}

src/transport/xqc_conn.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ xqc_conn_settings_t default_conn_settings = {
8080
.rtt_us_thr_low = 500000
8181
},
8282
.is_interop_mode = 0,
83+
#ifdef XQC_PROTECT_POOL_MEM
84+
.protect_pool_mem = 0,
85+
#endif
8386
};
8487

8588

@@ -118,6 +121,9 @@ xqc_server_set_conn_settings(const xqc_conn_settings_t *settings)
118121
default_conn_settings.recv_rate_bytes_per_sec = settings->recv_rate_bytes_per_sec;
119122
default_conn_settings.enable_stream_rate_limit = settings->enable_stream_rate_limit;
120123
default_conn_settings.init_recv_window = settings->init_recv_window;
124+
#ifdef XQC_PROTECT_POOL_MEM
125+
default_conn_settings.protect_pool_mem = settings->protect_pool_mem;
126+
#endif
121127

122128
if (default_conn_settings.init_recv_window) {
123129
default_conn_settings.init_recv_window = xqc_max(default_conn_settings.init_recv_window, XQC_QUIC_MAX_MSS);
@@ -477,11 +483,20 @@ xqc_conn_create(xqc_engine_t *engine, xqc_cid_t *dcid, xqc_cid_t *scid,
477483
const xqc_conn_settings_t *settings, void *user_data, xqc_conn_type_t type)
478484
{
479485
xqc_connection_t *xc = NULL;
486+
#ifdef XQC_PROTECT_POOL_MEM
487+
xqc_memory_pool_t *pool = xqc_create_pool(engine->config->conn_pool_size, settings->protect_pool_mem);
488+
#else
480489
xqc_memory_pool_t *pool = xqc_create_pool(engine->config->conn_pool_size);
490+
#endif
481491
if (pool == NULL) {
482492
return NULL;
483493
}
484494

495+
#ifdef XQC_PROTECT_POOL_MEM
496+
xqc_log(engine->log, XQC_LOG_DEBUG, "|mempool|protect:%d|page_sz:%z|",
497+
pool->protect_block, pool->page_size);
498+
#endif
499+
485500
xc = xqc_pcalloc(pool, sizeof(xqc_connection_t));
486501
if (xc == NULL) {
487502
goto fail;

tests/test_client.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4477,6 +4477,12 @@ int main(int argc, char *argv[]) {
44774477
.recv_rate_bytes_per_sec = rate_limit,
44784478
};
44794479

4480+
#ifdef XQC_PROTECT_POOL_MEM
4481+
if (g_test_case == 600) {
4482+
conn_settings.protect_pool_mem = 1;
4483+
}
4484+
#endif
4485+
44804486
xqc_stream_settings_t stream_settings = { .recv_rate_bytes_per_sec = 0 };
44814487

44824488
if (g_test_case == 109) {

0 commit comments

Comments
 (0)