Page MenuHomeFreeBSD

D56915.id.diff
No OneTemporary

D56915.id.diff

diff --git a/sys/netlink/netlink_message_parser.h b/sys/netlink/netlink_message_parser.h
--- a/sys/netlink/netlink_message_parser.h
+++ b/sys/netlink/netlink_message_parser.h
@@ -222,6 +222,9 @@
void nlmsg_report_cookie(struct nl_pstate *npt, struct nlattr *nla);
void nlmsg_report_cookie_u32(struct nl_pstate *npt, uint32_t val);
+struct nlmsghdr *nl_alloc_compat_hdr(struct nlmsghdr *hdr, uint32_t len,
+ struct nl_pstate *npt);
+
/*
* Have it inline so compiler can optimize field accesses into
* the list of direct function calls without iteration.
@@ -232,27 +235,7 @@
{
int error;
- if (__predict_false(len < parser->nl_hdr_off)) {
- void *tmp_hdr;
-
- if (npt->strict) {
- nlmsg_report_err_msg(npt,
- "header too short: expected %d, got %d",
- parser->nl_hdr_off, len);
- return (EINVAL);
- }
-
- /*
- * Compatibility with older applications:
- * pretend there's a full header.
- */
- tmp_hdr = npt_alloc(npt, parser->nl_hdr_off);
- if (tmp_hdr == NULL)
- return (EINVAL);
- memcpy(tmp_hdr, hdr, len);
- hdr = tmp_hdr;
- len = parser->nl_hdr_off;
- }
+ MPASS(len >= parser->nl_hdr_off);
if (npt->strict && parser->sp != NULL && !parser->sp(hdr, npt))
return (EINVAL);
@@ -320,6 +303,10 @@
nl_parse_nlmsg(struct nlmsghdr *hdr, const struct nlhdr_parser *parser,
struct nl_pstate *npt, void *target)
{
+ if (__predict_false(hdr->nlmsg_len - sizeof(struct nlmsghdr) <
+ parser->nl_hdr_off) &&
+ ((hdr = nl_alloc_compat_hdr(hdr, parser->nl_hdr_off, npt)) == NULL))
+ return (ENOMEM);
return (nl_parse_header(hdr + 1, hdr->nlmsg_len - sizeof(*hdr), parser,
npt, target));
}
diff --git a/sys/netlink/netlink_message_parser.c b/sys/netlink/netlink_message_parser.c
--- a/sys/netlink/netlink_message_parser.c
+++ b/sys/netlink/netlink_message_parser.c
@@ -50,6 +50,38 @@
#include <netlink/netlink_debug.h>
_DECLARE_DEBUG(LOG_INFO);
+/*
+ * Some applications try to provide only the non-zero part of the required
+ * message header instead of a full one. It happens when fetching routes or
+ * interface addresses, where the first header byte is the family.
+ * This behavior is "illegal" under the "strict" Netlink socket option, however
+ * there are many applications out there doing things in the "old" way.
+ * Support this usecase by copying the provided bytes into the temporary
+ * zero-filled header and running the parser on this header instead.
+ */
+struct nlmsghdr *
+nl_alloc_compat_hdr(struct nlmsghdr *hdr, uint32_t len, struct nl_pstate *npt)
+{
+ struct nlmsghdr *tmp;
+
+ MPASS(hdr->nlmsg_len < sizeof(struct nlmsghdr) + len);
+
+ len += sizeof(struct nlmsghdr);
+ if (npt->strict) {
+ nlmsg_report_err_msg(npt,
+ "header too short: expected %d, got %d",
+ len, hdr->nlmsg_len);
+ return (NULL);
+ }
+ tmp = npt_alloc(npt, len);
+ if (tmp == NULL)
+ return (NULL);
+ memcpy(tmp, hdr, hdr->nlmsg_len);
+ tmp->nlmsg_len = len;
+
+ return (tmp);
+}
+
bool
nlmsg_report_err_msg(struct nl_pstate *npt, const char *fmt, ...)
{

File Metadata

Mime Type
text/plain
Expires
Thu, May 21, 5:07 PM (5 h, 35 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
32905835
Default Alt Text
D56915.id.diff (2 KB)

Event Timeline