Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os 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: 08724ef69907 ("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>

authored by

Florian Westphal and committed by
Jakub Kicinski
ecaf75ff fc57062f

+28 -38
+10 -9
include/net/netlink.h
··· 181 181 NLA_S64, 182 182 NLA_BITFIELD32, 183 183 NLA_REJECT, 184 + NLA_BE16, 185 + NLA_BE32, 184 186 __NLA_TYPE_MAX, 185 187 }; 186 188 ··· 233 231 * NLA_U32, NLA_U64, 234 232 * NLA_S8, NLA_S16, 235 233 * NLA_S32, NLA_S64, 234 + * NLA_BE16, NLA_BE32, 236 235 * NLA_MSECS Leaving the length field zero will verify the 237 236 * given type fits, using it verifies minimum length 238 237 * just like "All other" ··· 264 261 * NLA_U16, 265 262 * NLA_U32, 266 263 * NLA_U64, 264 + * NLA_BE16, 265 + * NLA_BE32, 267 266 * NLA_S8, 268 267 * NLA_S16, 269 268 * NLA_S32, ··· 354 349 struct netlink_range_validation_signed *range_signed; 355 350 struct { 356 351 s16 min, max; 357 - u8 network_byte_order:1; 358 352 }; 359 353 int (*validate)(const struct nlattr *attr, 360 354 struct netlink_ext_ack *extack); ··· 378 374 (tp == NLA_U8 || tp == NLA_U16 || tp == NLA_U32 || tp == NLA_U64) 379 375 #define __NLA_IS_SINT_TYPE(tp) \ 380 376 (tp == NLA_S8 || tp == NLA_S16 || tp == NLA_S32 || tp == NLA_S64) 377 + #define __NLA_IS_BEINT_TYPE(tp) \ 378 + (tp == NLA_BE16 || tp == NLA_BE32) 381 379 382 380 #define __NLA_ENSURE(condition) BUILD_BUG_ON_ZERO(!(condition)) 383 381 #define NLA_ENSURE_UINT_TYPE(tp) \ ··· 393 387 #define NLA_ENSURE_INT_OR_BINARY_TYPE(tp) \ 394 388 (__NLA_ENSURE(__NLA_IS_UINT_TYPE(tp) || \ 395 389 __NLA_IS_SINT_TYPE(tp) || \ 390 + __NLA_IS_BEINT_TYPE(tp) || \ 396 391 tp == NLA_MSECS || \ 397 392 tp == NLA_BINARY) + tp) 398 393 #define NLA_ENSURE_NO_VALIDATION_PTR(tp) \ ··· 401 394 tp != NLA_REJECT && \ 402 395 tp != NLA_NESTED && \ 403 396 tp != NLA_NESTED_ARRAY) + tp) 397 + #define NLA_ENSURE_BEINT_TYPE(tp) \ 398 + (__NLA_ENSURE(__NLA_IS_BEINT_TYPE(tp)) + tp) 404 399 405 400 #define NLA_POLICY_RANGE(tp, _min, _max) { \ 406 401 .type = NLA_ENSURE_INT_OR_BINARY_TYPE(tp), \ ··· 433 424 .type = NLA_ENSURE_INT_OR_BINARY_TYPE(tp), \ 434 425 .validation_type = NLA_VALIDATE_MAX, \ 435 426 .max = _max, \ 436 - .network_byte_order = 0, \ 437 - } 438 - 439 - #define NLA_POLICY_MAX_BE(tp, _max) { \ 440 - .type = NLA_ENSURE_UINT_TYPE(tp), \ 441 - .validation_type = NLA_VALIDATE_MAX, \ 442 - .max = _max, \ 443 - .network_byte_order = 1, \ 444 427 } 445 428 446 429 #define NLA_POLICY_MASK(tp, _mask) { \
+15 -26
lib/nlattr.c
··· 124 124 range->max = U8_MAX; 125 125 break; 126 126 case NLA_U16: 127 + case NLA_BE16: 127 128 case NLA_BINARY: 128 129 range->max = U16_MAX; 129 130 break; 130 131 case NLA_U32: 132 + case NLA_BE32: 131 133 range->max = U32_MAX; 132 134 break; 133 135 case NLA_U64: ··· 161 159 } 162 160 } 163 161 164 - static u64 nla_get_attr_bo(const struct nla_policy *pt, 165 - const struct nlattr *nla) 166 - { 167 - switch (pt->type) { 168 - case NLA_U16: 169 - if (pt->network_byte_order) 170 - return ntohs(nla_get_be16(nla)); 171 - 172 - return nla_get_u16(nla); 173 - case NLA_U32: 174 - if (pt->network_byte_order) 175 - return ntohl(nla_get_be32(nla)); 176 - 177 - return nla_get_u32(nla); 178 - case NLA_U64: 179 - if (pt->network_byte_order) 180 - return be64_to_cpu(nla_get_be64(nla)); 181 - 182 - return nla_get_u64(nla); 183 - } 184 - 185 - WARN_ON_ONCE(1); 186 - return 0; 187 - } 188 - 189 162 static int nla_validate_range_unsigned(const struct nla_policy *pt, 190 163 const struct nlattr *nla, 191 164 struct netlink_ext_ack *extack, ··· 174 197 value = nla_get_u8(nla); 175 198 break; 176 199 case NLA_U16: 200 + value = nla_get_u16(nla); 201 + break; 177 202 case NLA_U32: 203 + value = nla_get_u32(nla); 204 + break; 178 205 case NLA_U64: 179 - value = nla_get_attr_bo(pt, nla); 206 + value = nla_get_u64(nla); 180 207 break; 181 208 case NLA_MSECS: 182 209 value = nla_get_u64(nla); 183 210 break; 184 211 case NLA_BINARY: 185 212 value = nla_len(nla); 213 + break; 214 + case NLA_BE16: 215 + value = ntohs(nla_get_be16(nla)); 216 + break; 217 + case NLA_BE32: 218 + value = ntohl(nla_get_be32(nla)); 186 219 break; 187 220 default: 188 221 return -EINVAL; ··· 321 334 case NLA_U64: 322 335 case NLA_MSECS: 323 336 case NLA_BINARY: 337 + case NLA_BE16: 338 + case NLA_BE32: 324 339 return nla_validate_range_unsigned(pt, nla, extack, validate); 325 340 case NLA_S8: 326 341 case NLA_S16:
+3 -3
net/netfilter/nft_payload.c
··· 173 173 [NFTA_PAYLOAD_SREG] = { .type = NLA_U32 }, 174 174 [NFTA_PAYLOAD_DREG] = { .type = NLA_U32 }, 175 175 [NFTA_PAYLOAD_BASE] = { .type = NLA_U32 }, 176 - [NFTA_PAYLOAD_OFFSET] = NLA_POLICY_MAX_BE(NLA_U32, 255), 177 - [NFTA_PAYLOAD_LEN] = NLA_POLICY_MAX_BE(NLA_U32, 255), 176 + [NFTA_PAYLOAD_OFFSET] = NLA_POLICY_MAX(NLA_BE32, 255), 177 + [NFTA_PAYLOAD_LEN] = NLA_POLICY_MAX(NLA_BE32, 255), 178 178 [NFTA_PAYLOAD_CSUM_TYPE] = { .type = NLA_U32 }, 179 - [NFTA_PAYLOAD_CSUM_OFFSET] = NLA_POLICY_MAX_BE(NLA_U32, 255), 179 + [NFTA_PAYLOAD_CSUM_OFFSET] = NLA_POLICY_MAX(NLA_BE32, 255), 180 180 [NFTA_PAYLOAD_CSUM_FLAGS] = { .type = NLA_U32 }, 181 181 }; 182 182