mirror of
https://github.com/open5gs/open5gs.git
synced 2026-10-19 09:44:04 +00:00
core: fix 32-bit TLV decoding and extend GTPv1 fuzzing
Pass short GTPv1 inputs to ogs_gtp1_parse_msg() so the fuzzer also exercises header-length validation. Rename the GTPv2 message variable to distinguish it from the GTPv1 counterpart. The fuzzer exposed undefined behavior in 32-bit TLV decoding when the first octet has its high bit set. It was promoted to int before being shifted by 24, which can overflow a signed int. Cast the first octet to uint32_t before shifting in both decoding paths and add regression coverage for high-bit values. Related PR: #4751
This commit is contained in:
parent
7b7327aa61
commit
cf8d809afb
4 changed files with 49 additions and 14 deletions
|
|
@ -541,7 +541,7 @@ static void test5_func(abts_case *tc, void *data)
|
|||
uint8_t parent_block[4000];
|
||||
uint8_t *pos = NULL;
|
||||
uint16_t c_16 = 0x1122;
|
||||
uint32_t c_32 = 0x11223344;
|
||||
uint32_t c_32 = 0x81223344U;
|
||||
uint8_t mode = (uintptr_t)data;
|
||||
|
||||
/* tlv encoding for test */
|
||||
|
|
@ -571,7 +571,7 @@ static void test5_func(abts_case *tc, void *data)
|
|||
ABTS_INT_EQUAL(tc, *(pos++), 20);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), 0);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), 4);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), 0x11);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), 0x81);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), 0x22);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), 0x33);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), 0x44);
|
||||
|
|
@ -585,7 +585,7 @@ static void test5_func(abts_case *tc, void *data)
|
|||
ABTS_INT_EQUAL(tc, *(pos++), 20);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), 0);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), 4);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), 0x11);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), 0x81);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), 0x22);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), 0x33);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), 0x44);
|
||||
|
|
@ -601,7 +601,7 @@ static void test5_func(abts_case *tc, void *data)
|
|||
ABTS_INT_EQUAL(tc, *(pos++), 0);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), 4);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), 0);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), 0x11);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), 0x81);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), 0x22);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), 0x33);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), 0x44);
|
||||
|
|
@ -613,7 +613,7 @@ static void test5_func(abts_case *tc, void *data)
|
|||
ABTS_INT_EQUAL(tc, *(pos++), 0x22);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), 20);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), 4);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), 0x11);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), 0x81);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), 0x22);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), 0x33);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), 0x44);
|
||||
|
|
@ -627,7 +627,7 @@ static void test5_func(abts_case *tc, void *data)
|
|||
mode);
|
||||
ABTS_INT_EQUAL(tc, ogs_tlv_value_16(p_tlv), 0x1122);
|
||||
p_tlv = parsed_tlv->next;
|
||||
ABTS_INT_EQUAL(tc, ogs_tlv_value_32(p_tlv), 0x11223344);
|
||||
ABTS_SIZE_EQUAL(tc, 0x81223344U, ogs_tlv_value_32(p_tlv));
|
||||
|
||||
ogs_tlv_free_all(parsed_tlv);
|
||||
ABTS_INT_EQUAL(tc, ogs_tlv_pool_avail(), ogs_core()->tlv.pool);
|
||||
|
|
@ -635,6 +635,42 @@ static void test5_func(abts_case *tc, void *data)
|
|||
return;
|
||||
}
|
||||
|
||||
typedef struct _tlv_uint32_message_t {
|
||||
ogs_tlv_uint32_t value;
|
||||
} tlv_uint32_message_t;
|
||||
|
||||
static ogs_tlv_desc_t tlv_desc_uint32_value = {
|
||||
OGS_TLV_UINT32, "UInt32 Value", 1, 4, 0,
|
||||
sizeof(ogs_tlv_uint32_t), { NULL }
|
||||
};
|
||||
|
||||
static ogs_tlv_desc_t tlv_desc_uint32_message = {
|
||||
OGS_TLV_MESSAGE, "UInt32 Message", 0, 0, 0, 0,
|
||||
{ &tlv_desc_uint32_value, NULL }
|
||||
};
|
||||
|
||||
static void test_uint32_func(abts_case *tc, void *data)
|
||||
{
|
||||
static const uint8_t encoded[] =
|
||||
{ 1, 0, 4, 0, 0x81, 0x22, 0x33, 0x44 };
|
||||
tlv_uint32_message_t message;
|
||||
ogs_pkbuf_t *pkbuf = NULL;
|
||||
int rv;
|
||||
|
||||
pkbuf = ogs_pkbuf_alloc(NULL, sizeof(encoded));
|
||||
ABTS_PTR_NOTNULL(tc, pkbuf);
|
||||
ogs_pkbuf_put_data(pkbuf, encoded, sizeof(encoded));
|
||||
|
||||
memset(&message, 0, sizeof(message));
|
||||
rv = ogs_tlv_parse_msg(&message, &tlv_desc_uint32_message, pkbuf,
|
||||
OGS_TLV_MODE_T1_L2_I1);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
ABTS_INT_EQUAL(tc, 1, message.value.presence);
|
||||
ABTS_SIZE_EQUAL(tc, 0x81223344U, message.value.u32);
|
||||
|
||||
ogs_pkbuf_free(pkbuf);
|
||||
}
|
||||
|
||||
/* Sample header for tlv_msg */
|
||||
#define TLV_AUTHORIZATION_POLICY_SUPPORT_TYPE 21
|
||||
#define TLV_AUTHORIZATION_POLICY_SUPPORT_LEN 1
|
||||
|
|
@ -1146,6 +1182,7 @@ abts_suite *test_tlv(abts_suite *suite)
|
|||
abts_run_test(suite, test5_func, (void*)OGS_TLV_MODE_T1_L2_I1);
|
||||
|
||||
abts_run_test(suite, test6_func, NULL);
|
||||
abts_run_test(suite, test_uint32_func, NULL);
|
||||
|
||||
/*
|
||||
* The cases below feed truncated and over-long blocks to the parser
|
||||
|
|
|
|||
|
|
@ -50,14 +50,12 @@ extern int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size)
|
|||
|
||||
if (GTP_VERSION(Data[0]) == OGS_GTP1_VERSION_1) {
|
||||
/* GTPv1 */
|
||||
if (Size >= 8) {
|
||||
ogs_gtp1_message_t gtp1_message;
|
||||
ogs_gtp1_parse_msg(>p1_message, pkbuf);
|
||||
}
|
||||
ogs_gtp1_message_t gtp1_message;
|
||||
ogs_gtp1_parse_msg(>p1_message, pkbuf);
|
||||
} else {
|
||||
/* GTPv2 */
|
||||
ogs_gtp2_message_t gtp_message;
|
||||
ogs_gtp2_parse_msg(>p_message, pkbuf);
|
||||
ogs_gtp2_message_t gtp2_message;
|
||||
ogs_gtp2_parse_msg(>p2_message, pkbuf);
|
||||
}
|
||||
|
||||
ogs_pkbuf_free(pkbuf);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue