Hi, It seems that in at least one case[1], nla_put_string() is being used on an NLA_STRING, which lacks a NULL terminator, which leads to silliness when nla_put_string() uses strlen() to figure out the size:
/** * nla_put_string - Add a string netlink attribute to a socket buffer * @skb: socket buffer to add attribute to * @attrtype: attribute type * @str: NUL terminated string */ static inline int nla_put_string(struct sk_buff *skb, int attrtype, const char *str) { return nla_put(skb, attrtype, strlen(str) + 1, str); } This is a problem at least here: struct regulatory_request { ... char alpha2[2]; ... static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { ... [NL80211_ATTR_REG_ALPHA2] = { .type = NLA_STRING, .len = 2 }, ... AIUI, working with NLA_STRING needs nla_strlcpy() to "extract" them, and that takes the nla_policy size normally to bounds-check the copy. So, this specific problem needs fixing (in at least two places calling nla_put_string(msg, NL80211_ATTR_REG_ALPHA2, ...)). While I suspect it's only ever written an extra byte from the following variable in the structure which is an enum nl80211_dfs_regions, I worry there might be a lot more of these (though I'd hope unterminated strings are uncommon for internal representation). And more generally, it seems like only the NLA _input_ functions actually check nla_policy details. It seems that the output functions should do the same too, yes? -Kees [1] https://github.com/copperhead/linux-hardened/issues/72 -- Kees Cook Pixel Security