Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netfilter: ipset: Improve skbinfo get/init helpers

Use struct ip_set_skbinfo in struct ip_set_ext instead of open
coded fields and assign structure members in get/init helpers
instead of copying members one by one. Explicitly note that
struct ip_set_skbinfo must be padded to prevent non-aligned
access in the extension blob.

Ported from a patch proposed by Sergey Popovich <popovich_sergei@mail.ua>.

Suggested-by: Sergey Popovich <popovich_sergei@mail.ua>
Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>

+24 -30
+11 -19
include/linux/netfilter/ipset/ip_set.h
··· 92 92 93 93 extern const struct ip_set_ext_type ip_set_extensions[]; 94 94 95 - struct ip_set_ext { 96 - u64 packets; 97 - u64 bytes; 98 - u32 timeout; 99 - u32 skbmark; 100 - u32 skbmarkmask; 101 - u32 skbprio; 102 - u16 skbqueue; 103 - char *comment; 104 - }; 105 - 106 95 struct ip_set_counter { 107 96 atomic64_t bytes; 108 97 atomic64_t packets; ··· 111 122 u32 skbmarkmask; 112 123 u32 skbprio; 113 124 u16 skbqueue; 125 + u16 __pad; 126 + }; 127 + 128 + struct ip_set_ext { 129 + struct ip_set_skbinfo skbinfo; 130 + u64 packets; 131 + u64 bytes; 132 + char *comment; 133 + u32 timeout; 114 134 }; 115 135 116 136 struct ip_set; ··· 358 360 const struct ip_set_ext *ext, 359 361 struct ip_set_ext *mext, u32 flags) 360 362 { 361 - mext->skbmark = skbinfo->skbmark; 362 - mext->skbmarkmask = skbinfo->skbmarkmask; 363 - mext->skbprio = skbinfo->skbprio; 364 - mext->skbqueue = skbinfo->skbqueue; 363 + mext->skbinfo = *skbinfo; 365 364 } 366 365 367 366 static inline bool ··· 382 387 ip_set_init_skbinfo(struct ip_set_skbinfo *skbinfo, 383 388 const struct ip_set_ext *ext) 384 389 { 385 - skbinfo->skbmark = ext->skbmark; 386 - skbinfo->skbmarkmask = ext->skbmarkmask; 387 - skbinfo->skbprio = ext->skbprio; 388 - skbinfo->skbqueue = ext->skbqueue; 390 + *skbinfo = ext->skbinfo; 389 391 } 390 392 391 393 /* Netlink CB args */
+6 -6
net/netfilter/ipset/ip_set_core.c
··· 426 426 if (!SET_WITH_SKBINFO(set)) 427 427 return -IPSET_ERR_SKBINFO; 428 428 fullmark = be64_to_cpu(nla_get_be64(tb[IPSET_ATTR_SKBMARK])); 429 - ext->skbmark = fullmark >> 32; 430 - ext->skbmarkmask = fullmark & 0xffffffff; 429 + ext->skbinfo.skbmark = fullmark >> 32; 430 + ext->skbinfo.skbmarkmask = fullmark & 0xffffffff; 431 431 } 432 432 if (tb[IPSET_ATTR_SKBPRIO]) { 433 433 if (!SET_WITH_SKBINFO(set)) 434 434 return -IPSET_ERR_SKBINFO; 435 - ext->skbprio = be32_to_cpu(nla_get_be32( 436 - tb[IPSET_ATTR_SKBPRIO])); 435 + ext->skbinfo.skbprio = 436 + be32_to_cpu(nla_get_be32(tb[IPSET_ATTR_SKBPRIO])); 437 437 } 438 438 if (tb[IPSET_ATTR_SKBQUEUE]) { 439 439 if (!SET_WITH_SKBINFO(set)) 440 440 return -IPSET_ERR_SKBINFO; 441 - ext->skbqueue = be16_to_cpu(nla_get_be16( 442 - tb[IPSET_ATTR_SKBQUEUE])); 441 + ext->skbinfo.skbqueue = 442 + be16_to_cpu(nla_get_be16(tb[IPSET_ATTR_SKBQUEUE])); 443 443 } 444 444 return 0; 445 445 }
+7 -5
net/netfilter/xt_set.c
··· 423 423 424 424 /* Revision 3 target */ 425 425 426 + #define MOPT(opt, member) ((opt).ext.skbinfo.member) 427 + 426 428 static unsigned int 427 429 set_target_v3(struct sk_buff *skb, const struct xt_action_param *par) 428 430 { ··· 455 453 if (!ret) 456 454 return XT_CONTINUE; 457 455 if (map_opt.cmdflags & IPSET_FLAG_MAP_SKBMARK) 458 - skb->mark = (skb->mark & ~(map_opt.ext.skbmarkmask)) 459 - ^ (map_opt.ext.skbmark); 456 + skb->mark = (skb->mark & ~MOPT(map_opt,skbmarkmask)) 457 + ^ MOPT(map_opt, skbmark); 460 458 if (map_opt.cmdflags & IPSET_FLAG_MAP_SKBPRIO) 461 - skb->priority = map_opt.ext.skbprio; 459 + skb->priority = MOPT(map_opt, skbprio); 462 460 if ((map_opt.cmdflags & IPSET_FLAG_MAP_SKBQUEUE) && 463 461 skb->dev && 464 - skb->dev->real_num_tx_queues > map_opt.ext.skbqueue) 465 - skb_set_queue_mapping(skb, map_opt.ext.skbqueue); 462 + skb->dev->real_num_tx_queues > MOPT(map_opt, skbqueue)) 463 + skb_set_queue_mapping(skb, MOPT(map_opt, skbqueue)); 466 464 } 467 465 return XT_CONTINUE; 468 466 }