zebra: Ensure proper decoding of netlink message

As part of the kernel netlink functionality, it is
possible that a bit of nested attributes can be
passed up.  This attribute has a type value which
is stored in the lower 8 bits and in the upper 8
bits are a couple control flags that can be used.
FRR can parse this data and then just throw away
the value unless we mask off the upper 8 bits.
Let's ensure that it can be properly parsed.

Signed-off-by: Donald Sharp <sharpd@nvidia.com>
This commit is contained in:
Donald Sharp 2024-04-30 10:53:48 -04:00
parent 65c2593a12
commit 26595e3162
2 changed files with 22 additions and 4 deletions

View File

@ -344,17 +344,19 @@ static int parse_rtattrs_(struct rtattr *rta, size_t len, struct rtattr **rtas,
memset(rtas, 0, num_rtas * sizeof(rtas[0]));
for (; len > 0; rta = RTA_NEXT(rta, len)) {
uint16_t type = rta->rta_type & NLA_TYPE_MASK;
if (!RTA_OK(rta, len)) {
*err_msg = "Malformed rta";
return 0;
}
if (rta->rta_type >= num_rtas) {
if (type >= num_rtas) {
warn("Unknown rtattr type %d", rta->rta_type);
continue;
}
rtas[rta->rta_type] = rta;
rtas[type] = rta;
}
return 1;

View File

@ -619,6 +619,11 @@ static void netlink_install_filter(int sock, uint32_t pid, uint32_t dplane_pid)
safe_strerror(errno));
}
/*
* Please note, the assumption with this function is that the
* flags passed in that are bit masked with type, we are implicitly
* assuming that this is handling the NLA_F_NESTED ilk.
*/
void netlink_parse_rtattr_flags(struct rtattr **tb, int max, struct rtattr *rta,
int len, unsigned short flags)
{
@ -638,8 +643,19 @@ void netlink_parse_rtattr(struct rtattr **tb, int max, struct rtattr *rta,
{
memset(tb, 0, sizeof(struct rtattr *) * (max + 1));
while (RTA_OK(rta, len)) {
if (rta->rta_type <= max)
tb[rta->rta_type] = rta;
/*
* The type may be &'ed with NLA_F_NESTED
* which puts data in the upper 8 bits of the
* rta_type. Mask it off and save the actual
* underlying value to be placed into the array.
* This way we don't accidently crash in the future
* when the kernel sends us new data and we try
* to write well beyond the end of the array.
*/
uint16_t type = rta->rta_type & NLA_TYPE_MASK;
if (type <= max)
tb[type] = rta;
rta = RTA_NEXT(rta, len);
}
}