git: 10f2a38769c7 - main - netlink: fix OOB write when creating attribute bitmask.

From: Alexander V. Chernikov <melifaro_at_FreeBSD.org>
Date: Sat, 21 Jan 2023 18:06:30 UTC
The branch main has been updated by melifaro:

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

commit 10f2a38769c7b2fa210a3ea077d3185448479013
Author:     Alexander V. Chernikov <melifaro@FreeBSD.org>
AuthorDate: 2023-01-21 18:03:47 +0000
Commit:     Alexander V. Chernikov <melifaro@FreeBSD.org>
CommitDate: 2023-01-21 18:03:47 +0000

    netlink: fix OOB write when creating attribute bitmask.
    
    Fix wrong arithmetics by moving to the standard bitset(9) functions.
    
    Reported by:    markj, KASAN
---
 sys/netlink/netlink_message_parser.c | 16 +++++++++++++---
 sys/netlink/netlink_message_parser.h | 16 ++++++----------
 2 files changed, 19 insertions(+), 13 deletions(-)

diff --git a/sys/netlink/netlink_message_parser.c b/sys/netlink/netlink_message_parser.c
index 451d9d497491..dc0c38712613 100644
--- a/sys/netlink/netlink_message_parser.c
+++ b/sys/netlink/netlink_message_parser.c
@@ -152,17 +152,27 @@ nl_get_attrs_bmask_raw(struct nlattr *nla_head, int len, struct nlattr_bmask *bm
 {
 	struct nlattr *nla = NULL;
 
-	bzero(bm->mask, sizeof(bm->mask));
+	BIT_ZERO(NL_ATTR_BMASK_SIZE, bm);
 
 	NLA_FOREACH(nla, nla_head, len) {
 		if (nla->nla_len < sizeof(struct nlattr))
 			return;
 		int nla_type = nla->nla_type & NLA_TYPE_MASK;
-		if (nla_type <= sizeof(bm->mask) * 8)
-			bm->mask[nla_type / 8] |= 1 << (nla_type % 8);
+		if (nla_type < NL_ATTR_BMASK_SIZE)
+			BIT_SET(NL_ATTR_BMASK_SIZE, nla_type, bm);
+		else
+			NL_LOG(LOG_DEBUG2, "Skipping type %d in the mask: too short",
+			    nla_type);
 	}
 }
 
+bool
+nl_has_attr(const struct nlattr_bmask *bm, unsigned int nla_type)
+{
+	MPASS(nla_type < NL_ATTR_BMASK_SIZE);
+
+	return (BIT_ISSET(NL_ATTR_BMASK_SIZE, nla_type, bm));
+}
 
 int
 nlattr_get_flag(struct nlattr *nla, struct nl_pstate *npt, const void *arg, void *target)
diff --git a/sys/netlink/netlink_message_parser.h b/sys/netlink/netlink_message_parser.h
index 3f64c1967f09..94f0ca5260d7 100644
--- a/sys/netlink/netlink_message_parser.h
+++ b/sys/netlink/netlink_message_parser.h
@@ -29,6 +29,9 @@
 #define _NETLINK_NETLINK_MESSAGE_PARSER_H_
 
 #ifdef _KERNEL
+
+#include <sys/bitset.h>
+
 /*
  * It is not meant to be included directly
  */
@@ -152,18 +155,11 @@ static const struct nlhdr_parser _name = {		\
 	.np_size = NL_ARRAY_LEN(_np),			\
 }
 
-struct nlattr_bmask {
-	uint64_t			mask[2];
-};
-
-static inline bool
-nl_has_attr(const struct nlattr_bmask *bm, unsigned int attr_type)
-{
-	MPASS(attr_type < sizeof(bm->mask) * 8);
+#define	NL_ATTR_BMASK_SIZE	128
+BITSET_DEFINE(nlattr_bmask, NL_ATTR_BMASK_SIZE);
 
-	return ((bm->mask[attr_type / 8] & (1 << (attr_type % 8))));
-}
 void nl_get_attrs_bmask_raw(struct nlattr *nla_head, int len, struct nlattr_bmask *bm);
+bool nl_has_attr(const struct nlattr_bmask *bm, unsigned int nla_type);
 
 int nl_parse_attrs_raw(struct nlattr *nla_head, int len, const struct nlattr_parser *ps,
     int pslen, struct nl_pstate *npt, void *target);