netlink: introduce bigendian integer types

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: 08724ef699 ("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>
This commit is contained in:
Florian Westphal 2022-10-31 13:34:07 +01:00 committed by Jakub Kicinski
parent fc57062f98
commit ecaf75ffd5
3 changed files with 28 additions and 38 deletions

View File

@ -181,6 +181,8 @@ enum {
NLA_S64, NLA_S64,
NLA_BITFIELD32, NLA_BITFIELD32,
NLA_REJECT, NLA_REJECT,
NLA_BE16,
NLA_BE32,
__NLA_TYPE_MAX, __NLA_TYPE_MAX,
}; };
@ -231,6 +233,7 @@ enum nla_policy_validation {
* NLA_U32, NLA_U64, * NLA_U32, NLA_U64,
* NLA_S8, NLA_S16, * NLA_S8, NLA_S16,
* NLA_S32, NLA_S64, * NLA_S32, NLA_S64,
* NLA_BE16, NLA_BE32,
* NLA_MSECS Leaving the length field zero will verify the * NLA_MSECS Leaving the length field zero will verify the
* given type fits, using it verifies minimum length * given type fits, using it verifies minimum length
* just like "All other" * just like "All other"
@ -261,6 +264,8 @@ enum nla_policy_validation {
* NLA_U16, * NLA_U16,
* NLA_U32, * NLA_U32,
* NLA_U64, * NLA_U64,
* NLA_BE16,
* NLA_BE32,
* NLA_S8, * NLA_S8,
* NLA_S16, * NLA_S16,
* NLA_S32, * NLA_S32,
@ -349,7 +354,6 @@ struct nla_policy {
struct netlink_range_validation_signed *range_signed; struct netlink_range_validation_signed *range_signed;
struct { struct {
s16 min, max; s16 min, max;
u8 network_byte_order:1;
}; };
int (*validate)(const struct nlattr *attr, int (*validate)(const struct nlattr *attr,
struct netlink_ext_ack *extack); struct netlink_ext_ack *extack);
@ -374,6 +378,8 @@ struct nla_policy {
(tp == NLA_U8 || tp == NLA_U16 || tp == NLA_U32 || tp == NLA_U64) (tp == NLA_U8 || tp == NLA_U16 || tp == NLA_U32 || tp == NLA_U64)
#define __NLA_IS_SINT_TYPE(tp) \ #define __NLA_IS_SINT_TYPE(tp) \
(tp == NLA_S8 || tp == NLA_S16 || tp == NLA_S32 || tp == NLA_S64) (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(condition) BUILD_BUG_ON_ZERO(!(condition))
#define NLA_ENSURE_UINT_TYPE(tp) \ #define NLA_ENSURE_UINT_TYPE(tp) \
@ -387,6 +393,7 @@ struct nla_policy {
#define NLA_ENSURE_INT_OR_BINARY_TYPE(tp) \ #define NLA_ENSURE_INT_OR_BINARY_TYPE(tp) \
(__NLA_ENSURE(__NLA_IS_UINT_TYPE(tp) || \ (__NLA_ENSURE(__NLA_IS_UINT_TYPE(tp) || \
__NLA_IS_SINT_TYPE(tp) || \ __NLA_IS_SINT_TYPE(tp) || \
__NLA_IS_BEINT_TYPE(tp) || \
tp == NLA_MSECS || \ tp == NLA_MSECS || \
tp == NLA_BINARY) + tp) tp == NLA_BINARY) + tp)
#define NLA_ENSURE_NO_VALIDATION_PTR(tp) \ #define NLA_ENSURE_NO_VALIDATION_PTR(tp) \
@ -394,6 +401,8 @@ struct nla_policy {
tp != NLA_REJECT && \ tp != NLA_REJECT && \
tp != NLA_NESTED && \ tp != NLA_NESTED && \
tp != NLA_NESTED_ARRAY) + tp) 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) { \ #define NLA_POLICY_RANGE(tp, _min, _max) { \
.type = NLA_ENSURE_INT_OR_BINARY_TYPE(tp), \ .type = NLA_ENSURE_INT_OR_BINARY_TYPE(tp), \
@ -424,14 +433,6 @@ struct nla_policy {
.type = NLA_ENSURE_INT_OR_BINARY_TYPE(tp), \ .type = NLA_ENSURE_INT_OR_BINARY_TYPE(tp), \
.validation_type = NLA_VALIDATE_MAX, \ .validation_type = NLA_VALIDATE_MAX, \
.max = _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) { \ #define NLA_POLICY_MASK(tp, _mask) { \

View File

@ -124,10 +124,12 @@ void nla_get_range_unsigned(const struct nla_policy *pt,
range->max = U8_MAX; range->max = U8_MAX;
break; break;
case NLA_U16: case NLA_U16:
case NLA_BE16:
case NLA_BINARY: case NLA_BINARY:
range->max = U16_MAX; range->max = U16_MAX;
break; break;
case NLA_U32: case NLA_U32:
case NLA_BE32:
range->max = U32_MAX; range->max = U32_MAX;
break; break;
case NLA_U64: case NLA_U64:
@ -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, static int nla_validate_range_unsigned(const struct nla_policy *pt,
const struct nlattr *nla, const struct nlattr *nla,
struct netlink_ext_ack *extack, struct netlink_ext_ack *extack,
@ -197,9 +174,13 @@ static int nla_validate_range_unsigned(const struct nla_policy *pt,
value = nla_get_u8(nla); value = nla_get_u8(nla);
break; break;
case NLA_U16: case NLA_U16:
value = nla_get_u16(nla);
break;
case NLA_U32: case NLA_U32:
value = nla_get_u32(nla);
break;
case NLA_U64: case NLA_U64:
value = nla_get_attr_bo(pt, nla); value = nla_get_u64(nla);
break; break;
case NLA_MSECS: case NLA_MSECS:
value = nla_get_u64(nla); value = nla_get_u64(nla);
@ -207,6 +188,12 @@ static int nla_validate_range_unsigned(const struct nla_policy *pt,
case NLA_BINARY: case NLA_BINARY:
value = nla_len(nla); value = nla_len(nla);
break; break;
case NLA_BE16:
value = ntohs(nla_get_be16(nla));
break;
case NLA_BE32:
value = ntohl(nla_get_be32(nla));
break;
default: default:
return -EINVAL; return -EINVAL;
} }
@ -334,6 +321,8 @@ static int nla_validate_int_range(const struct nla_policy *pt,
case NLA_U64: case NLA_U64:
case NLA_MSECS: case NLA_MSECS:
case NLA_BINARY: case NLA_BINARY:
case NLA_BE16:
case NLA_BE32:
return nla_validate_range_unsigned(pt, nla, extack, validate); return nla_validate_range_unsigned(pt, nla, extack, validate);
case NLA_S8: case NLA_S8:
case NLA_S16: case NLA_S16:

View File

@ -173,10 +173,10 @@ static const struct nla_policy nft_payload_policy[NFTA_PAYLOAD_MAX + 1] = {
[NFTA_PAYLOAD_SREG] = { .type = NLA_U32 }, [NFTA_PAYLOAD_SREG] = { .type = NLA_U32 },
[NFTA_PAYLOAD_DREG] = { .type = NLA_U32 }, [NFTA_PAYLOAD_DREG] = { .type = NLA_U32 },
[NFTA_PAYLOAD_BASE] = { .type = NLA_U32 }, [NFTA_PAYLOAD_BASE] = { .type = NLA_U32 },
[NFTA_PAYLOAD_OFFSET] = NLA_POLICY_MAX_BE(NLA_U32, 255), [NFTA_PAYLOAD_OFFSET] = NLA_POLICY_MAX(NLA_BE32, 255),
[NFTA_PAYLOAD_LEN] = NLA_POLICY_MAX_BE(NLA_U32, 255), [NFTA_PAYLOAD_LEN] = NLA_POLICY_MAX(NLA_BE32, 255),
[NFTA_PAYLOAD_CSUM_TYPE] = { .type = NLA_U32 }, [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 }, [NFTA_PAYLOAD_CSUM_FLAGS] = { .type = NLA_U32 },
}; };