forked from Minki/linux
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:
parent
fc57062f98
commit
ecaf75ffd5
@ -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) { \
|
||||||
|
41
lib/nlattr.c
41
lib/nlattr.c
@ -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:
|
||||||
|
@ -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 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user