The branch main has been updated by melifaro:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=ba9c815d3076f5a13ab6f9ec3f6d534e7774e83b

commit ba9c815d3076f5a13ab6f9ec3f6d534e7774e83b
Author:     Alexander V. Chernikov <melif...@freebsd.org>
AuthorDate: 2023-05-09 14:45:57 +0000
Commit:     Alexander V. Chernikov <melif...@freebsd.org>
CommitDate: 2023-05-09 14:45:57 +0000

    netlink: use consistent variable lifetime in the default snl(3) parsers.
    
    Currently, parsers use original strings/nla pointers instead of
    duplicating them. These pointers refer to the temporary packet buffer,
     which can be silently rewritten when the next message is read.
    Instead, duplicate all string/nla attributes using snl_allocz(3) to
     give control over variable lifetime to the user.
    
    MFC after:      2 weeks
---
 sys/netlink/netlink_snl.h               | 45 +++++++++++++++++++++++++++++++++
 sys/netlink/netlink_snl_route_parsers.h | 16 ++++++------
 2 files changed, 53 insertions(+), 8 deletions(-)

diff --git a/sys/netlink/netlink_snl.h b/sys/netlink/netlink_snl.h
index 822cec9b4dc4..83892c156273 100644
--- a/sys/netlink/netlink_snl.h
+++ b/sys/netlink/netlink_snl.h
@@ -606,6 +606,23 @@ snl_attr_copy_string(struct snl_state *ss, struct nlattr 
*nla,
        return (false);
 }
 
+static inline bool
+snl_attr_dup_string(struct snl_state *ss __unused, struct nlattr *nla,
+    const void *arg __unused, void *target)
+{
+       size_t maxlen = NLA_DATA_LEN(nla);
+
+       if (strnlen((char *)NLA_DATA(nla), maxlen) < maxlen) {
+               char *buf = snl_allocz(ss, maxlen);
+               if (buf == NULL)
+                       return (false);
+               memcpy(buf, NLA_DATA(nla), maxlen);
+               *((char **)target) = buf;
+               return (true);
+       }
+       return (false);
+}
+
 static inline bool
 snl_attr_get_nested(struct snl_state *ss, struct nlattr *nla, const void *arg, 
void *target)
 {
@@ -623,6 +640,20 @@ snl_attr_get_nla(struct snl_state *ss __unused, struct 
nlattr *nla,
        return (true);
 }
 
+static inline bool
+snl_attr_dup_nla(struct snl_state *ss __unused, struct nlattr *nla,
+    const void *arg __unused, void *target)
+{
+       void *ptr = snl_allocz(ss, nla->nla_len);
+
+       if (ptr != NULL) {
+               memcpy(ptr, nla, nla->nla_len);
+               *((void **)target) = ptr;
+               return (true);
+       }
+       return (false);
+}
+
 static inline bool
 snl_attr_copy_struct(struct snl_state *ss, struct nlattr *nla,
     const void *arg __unused, void *target)
@@ -637,6 +668,20 @@ snl_attr_copy_struct(struct snl_state *ss, struct nlattr 
*nla,
        return (false);
 }
 
+static inline bool
+snl_attr_dup_struct(struct snl_state *ss, struct nlattr *nla,
+    const void *arg __unused, void *target)
+{
+       void *ptr = snl_allocz(ss, NLA_DATA_LEN(nla));
+
+       if (ptr != NULL) {
+               memcpy(ptr, NLA_DATA(nla), NLA_DATA_LEN(nla));
+               *((void **)target) = ptr;
+               return (true);
+       }
+       return (false);
+}
+
 static inline void
 snl_field_get_uint8(struct snl_state *ss __unused, void *src, void *target)
 {
diff --git a/sys/netlink/netlink_snl_route_parsers.h 
b/sys/netlink/netlink_snl_route_parsers.h
index 94dc20861c3f..1afbe3feeeb9 100644
--- a/sys/netlink/netlink_snl_route_parsers.h
+++ b/sys/netlink/netlink_snl_route_parsers.h
@@ -177,13 +177,13 @@ struct snl_parsed_link {
 #define        _IN(_field)     offsetof(struct ifinfomsg, _field)
 #define        _OUT(_field)    offsetof(struct snl_parsed_link, _field)
 static const struct snl_attr_parser _nla_p_link[] = {
-       { .type = IFLA_ADDRESS, .off = _OUT(ifla_address), .cb = 
snl_attr_get_nla },
-       { .type = IFLA_BROADCAST, .off = _OUT(ifla_broadcast), .cb = 
snl_attr_get_nla },
-       { .type = IFLA_IFNAME, .off = _OUT(ifla_ifname), .cb = 
snl_attr_get_string },
+       { .type = IFLA_ADDRESS, .off = _OUT(ifla_address), .cb = 
snl_attr_dup_nla },
+       { .type = IFLA_BROADCAST, .off = _OUT(ifla_broadcast), .cb = 
snl_attr_dup_nla },
+       { .type = IFLA_IFNAME, .off = _OUT(ifla_ifname), .cb = 
snl_attr_dup_string },
        { .type = IFLA_MTU, .off = _OUT(ifla_mtu), .cb = snl_attr_get_uint32 },
        { .type = IFLA_OPERSTATE, .off = _OUT(ifla_operstate), .cb = 
snl_attr_get_uint8 },
-       { .type = IFLA_IFALIAS, .off = _OUT(ifla_ifalias), .cb = 
snl_attr_get_string },
-       { .type = IFLA_STATS64, .off = _OUT(ifla_stats64), .cb = 
snl_attr_copy_struct },
+       { .type = IFLA_IFALIAS, .off = _OUT(ifla_ifalias), .cb = 
snl_attr_dup_string },
+       { .type = IFLA_STATS64, .off = _OUT(ifla_stats64), .cb = 
snl_attr_dup_struct },
        { .type = IFLA_PROMISCUITY, .off = _OUT(ifla_promiscuity), .cb = 
snl_attr_get_uint32 },
        { .type = IFLA_CARRIER, .off = _OUT(ifla_carrier), .cb = 
snl_attr_get_uint8 },
 };
@@ -208,7 +208,7 @@ struct snl_parsed_link_simple {
 #define        _IN(_field)     offsetof(struct ifinfomsg, _field)
 #define        _OUT(_field)    offsetof(struct snl_parsed_link_simple, _field)
 static struct snl_attr_parser _nla_p_link_s[] = {
-       { .type = IFLA_IFNAME, .off = _OUT(ifla_ifname), .cb = 
snl_attr_get_string },
+       { .type = IFLA_IFNAME, .off = _OUT(ifla_ifname), .cb = 
snl_attr_dup_string },
        { .type = IFLA_MTU, .off = _OUT(ifla_mtu), .cb = snl_attr_get_uint32 },
 };
 static struct snl_field_parser _fp_p_link_s[] = {
@@ -240,7 +240,7 @@ SNL_DECLARE_ATTR_PARSER(_neigh_fbsd_parser, 
_nla_p_neigh_fbsd);
 
 static struct snl_attr_parser _nla_p_neigh_s[] = {
        { .type = NDA_DST, .off = _OUT(nda_dst), .cb = snl_attr_get_ip },
-       { .type = NDA_LLADDR , .off = _OUT(nda_lladdr), .cb = snl_attr_get_nla 
},
+       { .type = NDA_LLADDR , .off = _OUT(nda_lladdr), .cb = snl_attr_dup_nla 
},
        { .type = NDA_PROBES, .off = _OUT(nda_probes), .cb = 
snl_attr_get_uint32 },
        { .type = NDA_IFINDEX, .off = _OUT(nda_ifindex), .cb = 
snl_attr_get_uint32 },
        { .type = NDA_FREEBSD, .arg = &_neigh_fbsd_parser, .cb = 
snl_attr_get_nested },
@@ -270,7 +270,7 @@ struct snl_parsed_addr {
 static struct snl_attr_parser _nla_p_addr_s[] = {
        { .type = IFA_ADDRESS, .off = _OUT(ifa_address), .cb = snl_attr_get_ip 
},
        { .type = IFA_LOCAL, .off = _OUT(ifa_local), .cb = snl_attr_get_ip },
-       { .type = IFA_LABEL, .off = _OUT(ifa_label), .cb = snl_attr_get_string 
},
+       { .type = IFA_LABEL, .off = _OUT(ifa_label), .cb = snl_attr_dup_string 
},
        { .type = IFA_BROADCAST, .off = _OUT(ifa_broadcast), .cb = 
snl_attr_get_ip },
 };
 static struct snl_field_parser _fp_p_addr_s[] = {

Reply via email to