mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-06-14 13:22:02 +00:00
bgpd: fix heap buffer overflow in lcom -> str enc
Spaces were not being accounted for in the heap buffer sizing, leading to a heap buffer overflow when encoding large communities to their string representations. This patch also uses safer functions to do the encoding instead of pointer math. Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
This commit is contained in:
parent
91085f974a
commit
73bfd76d65
@ -177,15 +177,14 @@ static void set_lcommunity_string(struct lcommunity *lcom, bool make_json)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int len;
|
int len;
|
||||||
bool first = true;
|
|
||||||
char *str_buf;
|
char *str_buf;
|
||||||
char *str_pnt;
|
|
||||||
uint8_t *pnt;
|
uint8_t *pnt;
|
||||||
uint32_t global, local1, local2;
|
uint32_t global, local1, local2;
|
||||||
json_object *json_lcommunity_list = NULL;
|
json_object *json_lcommunity_list = NULL;
|
||||||
json_object *json_string = NULL;
|
json_object *json_string = NULL;
|
||||||
|
|
||||||
#define LCOMMUNITY_STR_DEFAULT_LEN 32
|
/* 3 32-bit integers, 2 colons, and a space */
|
||||||
|
#define LCOMMUNITY_STRLEN (10 * 3 + 2 + 1)
|
||||||
|
|
||||||
if (!lcom)
|
if (!lcom)
|
||||||
return;
|
return;
|
||||||
@ -196,8 +195,7 @@ static void set_lcommunity_string(struct lcommunity *lcom, bool make_json)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (lcom->size == 0) {
|
if (lcom->size == 0) {
|
||||||
str_buf = XMALLOC(MTYPE_LCOMMUNITY_STR, 1);
|
str_buf = XCALLOC(MTYPE_LCOMMUNITY_STR, 1);
|
||||||
str_buf[0] = '\0';
|
|
||||||
|
|
||||||
if (make_json) {
|
if (make_json) {
|
||||||
json_object_string_add(lcom->json, "string", "");
|
json_object_string_add(lcom->json, "string", "");
|
||||||
@ -209,15 +207,13 @@ static void set_lcommunity_string(struct lcommunity *lcom, bool make_json)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
str_buf = str_pnt =
|
/* 1 space + lcom->size lcom strings + null terminator */
|
||||||
XMALLOC(MTYPE_LCOMMUNITY_STR,
|
size_t str_buf_sz = (LCOMMUNITY_STRLEN * lcom->size) + 2;
|
||||||
(LCOMMUNITY_STR_DEFAULT_LEN * lcom->size) + 1);
|
str_buf = XCALLOC(MTYPE_LCOMMUNITY_STR, str_buf_sz);
|
||||||
|
|
||||||
for (i = 0; i < lcom->size; i++) {
|
for (i = 0; i < lcom->size; i++) {
|
||||||
if (first)
|
if (i > 0)
|
||||||
first = false;
|
strlcat(str_buf, " ", str_buf_sz);
|
||||||
else
|
|
||||||
*str_pnt++ = ' ';
|
|
||||||
|
|
||||||
pnt = lcom->val + (i * LCOMMUNITY_SIZE);
|
pnt = lcom->val + (i * LCOMMUNITY_SIZE);
|
||||||
pnt = ptr_get_be32(pnt, &global);
|
pnt = ptr_get_be32(pnt, &global);
|
||||||
@ -225,19 +221,21 @@ static void set_lcommunity_string(struct lcommunity *lcom, bool make_json)
|
|||||||
pnt = ptr_get_be32(pnt, &local2);
|
pnt = ptr_get_be32(pnt, &local2);
|
||||||
(void)pnt;
|
(void)pnt;
|
||||||
|
|
||||||
len = sprintf(str_pnt, "%u:%u:%u", global, local1, local2);
|
char lcsb[LCOMMUNITY_STRLEN + 1];
|
||||||
|
|
||||||
|
snprintf(lcsb, sizeof(lcsb), "%u:%u:%u", global, local1,
|
||||||
|
local2);
|
||||||
|
|
||||||
|
len = strlcat(str_buf, lcsb, str_buf_sz);
|
||||||
|
assert((unsigned int)len < str_buf_sz);
|
||||||
|
|
||||||
if (make_json) {
|
if (make_json) {
|
||||||
json_string = json_object_new_string(str_pnt);
|
json_string = json_object_new_string(lcsb);
|
||||||
json_object_array_add(json_lcommunity_list,
|
json_object_array_add(json_lcommunity_list,
|
||||||
json_string);
|
json_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
str_pnt += len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
str_buf =
|
|
||||||
XREALLOC(MTYPE_LCOMMUNITY_STR, str_buf, str_pnt - str_buf + 1);
|
|
||||||
|
|
||||||
if (make_json) {
|
if (make_json) {
|
||||||
json_object_string_add(lcom->json, "string", str_buf);
|
json_object_string_add(lcom->json, "string", str_buf);
|
||||||
json_object_object_add(lcom->json, "list",
|
json_object_object_add(lcom->json, "list",
|
||||||
|
Loading…
Reference in New Issue
Block a user