Skip to content

Commit

Permalink
netlink: introduce NLA_POLICY_MAX_BE
Browse files Browse the repository at this point in the history
netlink allows to specify allowed ranges for integer types.
Unfortunately, nfnetlink passes integers in big endian, so the existing
NLA_POLICY_MAX() cannot be used.

At the moment, nfnetlink users, such as nf_tables, need to resort to
programmatic checking via helpers such as nft_parse_u32_check().

This is both cumbersome and error prone.  This adds NLA_POLICY_MAX_BE
which adds range check support for BE16, BE32 and BE64 integers.

Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Florian Westphal authored and davem330 committed Sep 7, 2022
1 parent 98ba810 commit 08724ef
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 4 deletions.
9 changes: 9 additions & 0 deletions include/net/netlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,7 @@ struct nla_policy {
struct netlink_range_validation_signed *range_signed;
struct {
s16 min, max;
u8 network_byte_order:1;
};
int (*validate)(const struct nlattr *attr,
struct netlink_ext_ack *extack);
Expand Down Expand Up @@ -418,6 +419,14 @@ struct nla_policy {
.type = NLA_ENSURE_INT_OR_BINARY_TYPE(tp), \
.validation_type = NLA_VALIDATE_MAX, \
.max = _max, \
.network_byte_order = 0, \
}

#define NLA_POLICY_MAX_BE(tp, _max) { \
.type = NLA_ENSURE_UINT_TYPE(tp), \
.validation_type = NLA_VALIDATE_MAX, \
.max = _max, \
.network_byte_order = 1, \
}

#define NLA_POLICY_MASK(tp, _mask) { \
Expand Down
31 changes: 27 additions & 4 deletions lib/nlattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,31 @@ void nla_get_range_unsigned(const struct nla_policy *pt,
}
}

static u64 nla_get_attr_bo(const struct nla_policy *pt,
const struct nlattr *nla)
{
switch (pt->type) {
case NLA_U16:
if (pt->network_byte_order)
return ntohs(nla_get_be16(nla));

return nla_get_u16(nla);
case NLA_U32:
if (pt->network_byte_order)
return ntohl(nla_get_be32(nla));

return nla_get_u32(nla);
case NLA_U64:
if (pt->network_byte_order)
return be64_to_cpu(nla_get_be64(nla));

return nla_get_u64(nla);
}

WARN_ON_ONCE(1);
return 0;
}

static int nla_validate_range_unsigned(const struct nla_policy *pt,
const struct nlattr *nla,
struct netlink_ext_ack *extack,
Expand All @@ -172,12 +197,10 @@ static int nla_validate_range_unsigned(const struct nla_policy *pt,
value = nla_get_u8(nla);
break;
case NLA_U16:
value = nla_get_u16(nla);
break;
case NLA_U32:
value = nla_get_u32(nla);
break;
case NLA_U64:
value = nla_get_attr_bo(pt, nla);
break;
case NLA_MSECS:
value = nla_get_u64(nla);
break;
Expand Down

0 comments on commit 08724ef

Please sign in to comment.