Skip to content

Commit

Permalink
netlink: introduce bigendian integer types
Browse files Browse the repository at this point in the history
Jakub reported that the addition of the "network_byte_order"
member in struct nla_policy increases size of 32bit platforms.

Instead of scraping the bit from elsewhere Johannes suggested
to add explicit NLA_BE types instead, so do this here.

NLA_POLICY_MAX_BE() macro is removed again, there is no need
for it: NLA_POLICY_MAX(NLA_BE.., ..) will do the right thing.

NLA_BE64 can be added later.

Fixes: 08724ef ("netlink: introduce NLA_POLICY_MAX_BE")
Reported-by: Jakub Kicinski <kuba@kernel.org>
Suggested-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: Florian Westphal <fw@strlen.de>
Link: https://lore.kernel.org/r/20221031123407.9158-1-fw@strlen.de
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Florian Westphal authored and kuba-moo committed Nov 2, 2022
1 parent fc57062 commit ecaf75f
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 38 deletions.
19 changes: 10 additions & 9 deletions include/net/netlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,8 @@ enum {
NLA_S64,
NLA_BITFIELD32,
NLA_REJECT,
NLA_BE16,
NLA_BE32,
__NLA_TYPE_MAX,
};

Expand Down Expand Up @@ -231,6 +233,7 @@ enum nla_policy_validation {
* NLA_U32, NLA_U64,
* NLA_S8, NLA_S16,
* NLA_S32, NLA_S64,
* NLA_BE16, NLA_BE32,
* NLA_MSECS Leaving the length field zero will verify the
* given type fits, using it verifies minimum length
* just like "All other"
Expand Down Expand Up @@ -261,6 +264,8 @@ enum nla_policy_validation {
* NLA_U16,
* NLA_U32,
* NLA_U64,
* NLA_BE16,
* NLA_BE32,
* NLA_S8,
* NLA_S16,
* NLA_S32,
Expand Down Expand Up @@ -349,7 +354,6 @@ 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 All @@ -374,6 +378,8 @@ struct nla_policy {
(tp == NLA_U8 || tp == NLA_U16 || tp == NLA_U32 || tp == NLA_U64)
#define __NLA_IS_SINT_TYPE(tp) \
(tp == NLA_S8 || tp == NLA_S16 || tp == NLA_S32 || tp == NLA_S64)
#define __NLA_IS_BEINT_TYPE(tp) \
(tp == NLA_BE16 || tp == NLA_BE32)

#define __NLA_ENSURE(condition) BUILD_BUG_ON_ZERO(!(condition))
#define NLA_ENSURE_UINT_TYPE(tp) \
Expand All @@ -387,13 +393,16 @@ struct nla_policy {
#define NLA_ENSURE_INT_OR_BINARY_TYPE(tp) \
(__NLA_ENSURE(__NLA_IS_UINT_TYPE(tp) || \
__NLA_IS_SINT_TYPE(tp) || \
__NLA_IS_BEINT_TYPE(tp) || \
tp == NLA_MSECS || \
tp == NLA_BINARY) + tp)
#define NLA_ENSURE_NO_VALIDATION_PTR(tp) \
(__NLA_ENSURE(tp != NLA_BITFIELD32 && \
tp != NLA_REJECT && \
tp != NLA_NESTED && \
tp != NLA_NESTED_ARRAY) + tp)
#define NLA_ENSURE_BEINT_TYPE(tp) \
(__NLA_ENSURE(__NLA_IS_BEINT_TYPE(tp)) + tp)

#define NLA_POLICY_RANGE(tp, _min, _max) { \
.type = NLA_ENSURE_INT_OR_BINARY_TYPE(tp), \
Expand Down Expand Up @@ -424,14 +433,6 @@ 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
41 changes: 15 additions & 26 deletions lib/nlattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,12 @@ void nla_get_range_unsigned(const struct nla_policy *pt,
range->max = U8_MAX;
break;
case NLA_U16:
case NLA_BE16:
case NLA_BINARY:
range->max = U16_MAX;
break;
case NLA_U32:
case NLA_BE32:
range->max = U32_MAX;
break;
case NLA_U64:
Expand Down Expand Up @@ -159,31 +161,6 @@ 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 @@ -197,16 +174,26 @@ 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);
value = nla_get_u64(nla);
break;
case NLA_MSECS:
value = nla_get_u64(nla);
break;
case NLA_BINARY:
value = nla_len(nla);
break;
case NLA_BE16:
value = ntohs(nla_get_be16(nla));
break;
case NLA_BE32:
value = ntohl(nla_get_be32(nla));
break;
default:
return -EINVAL;
}
Expand Down Expand Up @@ -334,6 +321,8 @@ static int nla_validate_int_range(const struct nla_policy *pt,
case NLA_U64:
case NLA_MSECS:
case NLA_BINARY:
case NLA_BE16:
case NLA_BE32:
return nla_validate_range_unsigned(pt, nla, extack, validate);
case NLA_S8:
case NLA_S16:
Expand Down
6 changes: 3 additions & 3 deletions net/netfilter/nft_payload.c
Original file line number Diff line number Diff line change
Expand Up @@ -173,10 +173,10 @@ static const struct nla_policy nft_payload_policy[NFTA_PAYLOAD_MAX + 1] = {
[NFTA_PAYLOAD_SREG] = { .type = NLA_U32 },
[NFTA_PAYLOAD_DREG] = { .type = NLA_U32 },
[NFTA_PAYLOAD_BASE] = { .type = NLA_U32 },
[NFTA_PAYLOAD_OFFSET] = NLA_POLICY_MAX_BE(NLA_U32, 255),
[NFTA_PAYLOAD_LEN] = NLA_POLICY_MAX_BE(NLA_U32, 255),
[NFTA_PAYLOAD_OFFSET] = NLA_POLICY_MAX(NLA_BE32, 255),
[NFTA_PAYLOAD_LEN] = NLA_POLICY_MAX(NLA_BE32, 255),
[NFTA_PAYLOAD_CSUM_TYPE] = { .type = NLA_U32 },
[NFTA_PAYLOAD_CSUM_OFFSET] = NLA_POLICY_MAX_BE(NLA_U32, 255),
[NFTA_PAYLOAD_CSUM_OFFSET] = NLA_POLICY_MAX(NLA_BE32, 255),
[NFTA_PAYLOAD_CSUM_FLAGS] = { .type = NLA_U32 },
};

Expand Down

0 comments on commit ecaf75f

Please sign in to comment.