]> git.puffer.fish Git - matthieu/frr.git/commitdiff
zebra: Ensure proper decoding of netlink message
authorDonald Sharp <sharpd@nvidia.com>
Tue, 30 Apr 2024 14:53:48 +0000 (10:53 -0400)
committerDonald Sharp <sharpd@nvidia.com>
Tue, 30 Apr 2024 18:46:08 +0000 (14:46 -0400)
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>
zebra/fpm_listener.c
zebra/kernel_netlink.c

index 5ffc0561bb1a9669b25d9a75dc1a812c2d0cb6d6..b31c5f7ac66a2c86babf3de265ab4ca14e33449d 100644 (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;
index 8a64a1ea48ea80bdfc624d0f6c98a3b6d16e7ac6..d2f1db67ee582aa5bd79543691ca6a210c2201fb 100644 (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);
        }
 }