Commit ecaf75ff authored by Florian Westphal's avatar Florian Westphal Committed by Jakub Kicinski
Browse files

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: 08724ef6 ("netlink: introduce NLA_POLICY_MAX_BE")
Reported-by: default avatarJakub Kicinski <kuba@kernel.org>
Suggested-by: default avatarJohannes Berg <johannes@sipsolutions.net>
Signed-off-by: default avatarFlorian Westphal <fw@strlen.de>
Link: https://lore.kernel.org/r/20221031123407.9158-1-fw@strlen.de


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent fc57062f
Loading
Loading
Loading
Loading
+10 −9
Original line number Diff line number Diff line
@@ -181,6 +181,8 @@ enum {
	NLA_S64,
	NLA_BITFIELD32,
	NLA_REJECT,
	NLA_BE16,
	NLA_BE32,
	__NLA_TYPE_MAX,
};

@@ -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"
@@ -261,6 +264,8 @@ enum nla_policy_validation {
 *    NLA_U16,
 *    NLA_U32,
 *    NLA_U64,
 *    NLA_BE16,
 *    NLA_BE32,
 *    NLA_S8,
 *    NLA_S16,
 *    NLA_S32,
@@ -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);
@@ -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)			\
@@ -387,6 +393,7 @@ 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)		\
@@ -394,6 +401,8 @@ struct nla_policy {
		      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),	\
@@ -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) {			\
+15 −26
Original line number Diff line number Diff line
@@ -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:
@@ -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,
@@ -197,9 +174,13 @@ 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);
@@ -207,6 +188,12 @@ static int nla_validate_range_unsigned(const struct nla_policy *pt,
	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;
	}
@@ -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:
+3 −3
Original line number Diff line number Diff line
@@ -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 },
};