Commit 2f8cc49d authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'net-introduce-nlmsg_payload-helper'

Breno Leitao says:

====================
net: Introduce nlmsg_payload helper

In the current codebase, there are multiple instances where the
structure size is checked before assigning it to a Netlink message. This
check is crucial for ensuring that the structure is correctly mapped
onto the Netlink message, providing a layer of security.

To streamline this process, Jakub Kicinski suggested creating a helper
function, `nlmsg_payload`, which verifies if the structure fits within
the message. If it does, the function returns the data; otherwise, it
returns NULL. This approach simplifies the code and reduces redundancy.

This patchset introduces the `nlmsg_payload` helper and updates several
parts of the code to use it. Further updates will follow in subsequent
patchsets.

v1: https://lore.kernel.org/20250411-nlmsg-v1-0-ddd4e065cb15@debian.org
====================

Link: https://patch.msgid.link/20250414-nlmsg-v2-0-3d90cb42c6af@debian.org


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 0418711f 8ff95303
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -611,6 +611,22 @@ static inline int nlmsg_len(const struct nlmsghdr *nlh)
	return nlh->nlmsg_len - NLMSG_HDRLEN;
}

/**
 * nlmsg_payload - message payload if the data fits in the len
 * @nlh: netlink message header
 * @len: struct length
 *
 * Returns: The netlink message payload/data if the length is sufficient,
 * otherwise NULL.
 */
static inline void *nlmsg_payload(const struct nlmsghdr *nlh, size_t len)
{
	if (nlh->nlmsg_len < nlmsg_msg_size(len))
		return NULL;

	return nlmsg_data(nlh);
}

/**
 * nlmsg_attrdata - head of attributes data
 * @nlh: netlink message header
+8 −6
Original line number Diff line number Diff line
@@ -852,13 +852,14 @@ int fib_newrule(struct net *net, struct sk_buff *skb, struct nlmsghdr *nlh,
		struct netlink_ext_ack *extack, bool rtnl_held)
{
	struct fib_rule *rule = NULL, *r, *last = NULL;
	struct fib_rule_hdr *frh = nlmsg_data(nlh);
	int err = -EINVAL, unresolved = 0;
	struct fib_rules_ops *ops = NULL;
	struct nlattr *tb[FRA_MAX + 1];
	bool user_priority = false;
	struct fib_rule_hdr *frh;

	if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh))) {
	frh = nlmsg_payload(nlh, sizeof(*frh));
	if (!frh) {
		NL_SET_ERR_MSG(extack, "Invalid msg length");
		goto errout;
	}
@@ -980,13 +981,14 @@ int fib_delrule(struct net *net, struct sk_buff *skb, struct nlmsghdr *nlh,
		struct netlink_ext_ack *extack, bool rtnl_held)
{
	struct fib_rule *rule = NULL, *nlrule = NULL;
	struct fib_rule_hdr *frh = nlmsg_data(nlh);
	struct fib_rules_ops *ops = NULL;
	struct nlattr *tb[FRA_MAX+1];
	bool user_priority = false;
	struct fib_rule_hdr *frh;
	int err = -EINVAL;

	if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh))) {
	frh = nlmsg_payload(nlh, sizeof(*frh));
	if (!frh) {
		NL_SET_ERR_MSG(extack, "Invalid msg length");
		goto errout;
	}
@@ -1238,12 +1240,12 @@ static int fib_valid_dumprule_req(const struct nlmsghdr *nlh,
{
	struct fib_rule_hdr *frh;

	if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh))) {
	frh = nlmsg_payload(nlh, sizeof(*frh));
	if (!frh) {
		NL_SET_ERR_MSG(extack, "Invalid header for fib rule dump request");
		return -EINVAL;
	}

	frh = nlmsg_data(nlh);
	if (frh->dst_len || frh->src_len || frh->tos || frh->table ||
	    frh->res1 || frh->res2 || frh->action || frh->flags) {
		NL_SET_ERR_MSG(extack,
+4 −4
Original line number Diff line number Diff line
@@ -2430,12 +2430,12 @@ static int neightbl_valid_dump_info(const struct nlmsghdr *nlh,
{
	struct ndtmsg *ndtm;

	if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ndtm))) {
	ndtm = nlmsg_payload(nlh, sizeof(*ndtm));
	if (!ndtm) {
		NL_SET_ERR_MSG(extack, "Invalid header for neighbor table dump request");
		return -EINVAL;
	}

	ndtm = nlmsg_data(nlh);
	if (ndtm->ndtm_pad1  || ndtm->ndtm_pad2) {
		NL_SET_ERR_MSG(extack, "Invalid values in header for neighbor table dump request");
		return -EINVAL;
@@ -2855,12 +2855,12 @@ static int neigh_valid_get_req(const struct nlmsghdr *nlh,
	struct ndmsg *ndm;
	int err, i;

	if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ndm))) {
	ndm = nlmsg_payload(nlh, sizeof(*ndm));
	if (!ndm) {
		NL_SET_ERR_MSG(extack, "Invalid header for neighbor get request");
		return -EINVAL;
	}

	ndm = nlmsg_data(nlh);
	if (ndm->ndm_pad1  || ndm->ndm_pad2  || ndm->ndm_state ||
	    ndm->ndm_type) {
		NL_SET_ERR_MSG(extack, "Invalid values in header for neighbor get request");
+2 −2
Original line number Diff line number Diff line
@@ -4887,12 +4887,12 @@ static int valid_fdb_dump_strict(const struct nlmsghdr *nlh,
	struct ndmsg *ndm;
	int err, i;

	if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ndm))) {
	ndm = nlmsg_payload(nlh, sizeof(*ndm));
	if (!ndm) {
		NL_SET_ERR_MSG(extack, "Invalid header for fdb dump request");
		return -EINVAL;
	}

	ndm = nlmsg_data(nlh);
	if (ndm->ndm_pad1  || ndm->ndm_pad2  || ndm->ndm_state ||
	    ndm->ndm_flags || ndm->ndm_type) {
		NL_SET_ERR_MSG(extack, "Invalid values in header for fdb dump request");
+4 −4
Original line number Diff line number Diff line
@@ -5346,12 +5346,12 @@ static int inet6_valid_dump_ifaddr_req(const struct nlmsghdr *nlh,
	struct ifaddrmsg *ifm;
	int err, i;

	if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ifm))) {
	ifm = nlmsg_payload(nlh, sizeof(*ifm));
	if (!ifm) {
		NL_SET_ERR_MSG_MOD(extack, "Invalid header for address dump request");
		return -EINVAL;
	}

	ifm = nlmsg_data(nlh);
	if (ifm->ifa_prefixlen || ifm->ifa_flags || ifm->ifa_scope) {
		NL_SET_ERR_MSG_MOD(extack, "Invalid values in header for address dump request");
		return -EINVAL;
@@ -5484,7 +5484,8 @@ static int inet6_rtm_valid_getaddr_req(struct sk_buff *skb,
	struct ifaddrmsg *ifm;
	int i, err;

	if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ifm))) {
	ifm = nlmsg_payload(nlh, sizeof(*ifm));
	if (!ifm) {
		NL_SET_ERR_MSG_MOD(extack, "Invalid header for get address request");
		return -EINVAL;
	}
@@ -5493,7 +5494,6 @@ static int inet6_rtm_valid_getaddr_req(struct sk_buff *skb,
		return nlmsg_parse_deprecated(nlh, sizeof(*ifm), tb, IFA_MAX,
					      ifa_ipv6_policy, extack);

	ifm = nlmsg_data(nlh);
	if (ifm->ifa_prefixlen || ifm->ifa_flags || ifm->ifa_scope) {
		NL_SET_ERR_MSG_MOD(extack, "Invalid values in header for get address request");
		return -EINVAL;
Loading