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>
This commit is contained in:
Jozsef Kadlecsik 2015-05-05 17:13:28 +02:00
parent 7ffea37957
commit bec810d973
3 changed files with 24 additions and 30 deletions

View file

@ -92,17 +92,6 @@ struct ip_set_ext_type {
extern const struct ip_set_ext_type ip_set_extensions[]; extern const struct ip_set_ext_type ip_set_extensions[];
struct ip_set_ext {
u64 packets;
u64 bytes;
u32 timeout;
u32 skbmark;
u32 skbmarkmask;
u32 skbprio;
u16 skbqueue;
char *comment;
};
struct ip_set_counter { struct ip_set_counter {
atomic64_t bytes; atomic64_t bytes;
atomic64_t packets; atomic64_t packets;
@ -122,6 +111,15 @@ struct ip_set_skbinfo {
u32 skbmarkmask; u32 skbmarkmask;
u32 skbprio; u32 skbprio;
u16 skbqueue; u16 skbqueue;
u16 __pad;
};
struct ip_set_ext {
struct ip_set_skbinfo skbinfo;
u64 packets;
u64 bytes;
char *comment;
u32 timeout;
}; };
struct ip_set; struct ip_set;
@ -360,10 +358,7 @@ ip_set_get_skbinfo(struct ip_set_skbinfo *skbinfo,
const struct ip_set_ext *ext, const struct ip_set_ext *ext,
struct ip_set_ext *mext, u32 flags) struct ip_set_ext *mext, u32 flags)
{ {
mext->skbmark = skbinfo->skbmark; mext->skbinfo = *skbinfo;
mext->skbmarkmask = skbinfo->skbmarkmask;
mext->skbprio = skbinfo->skbprio;
mext->skbqueue = skbinfo->skbqueue;
} }
static inline bool static inline bool
@ -387,10 +382,7 @@ static inline void
ip_set_init_skbinfo(struct ip_set_skbinfo *skbinfo, ip_set_init_skbinfo(struct ip_set_skbinfo *skbinfo,
const struct ip_set_ext *ext) const struct ip_set_ext *ext)
{ {
skbinfo->skbmark = ext->skbmark; *skbinfo = ext->skbinfo;
skbinfo->skbmarkmask = ext->skbmarkmask;
skbinfo->skbprio = ext->skbprio;
skbinfo->skbqueue = ext->skbqueue;
} }
/* Netlink CB args */ /* Netlink CB args */

View file

@ -426,20 +426,20 @@ ip_set_get_extensions(struct ip_set *set, struct nlattr *tb[],
if (!SET_WITH_SKBINFO(set)) if (!SET_WITH_SKBINFO(set))
return -IPSET_ERR_SKBINFO; return -IPSET_ERR_SKBINFO;
fullmark = be64_to_cpu(nla_get_be64(tb[IPSET_ATTR_SKBMARK])); fullmark = be64_to_cpu(nla_get_be64(tb[IPSET_ATTR_SKBMARK]));
ext->skbmark = fullmark >> 32; ext->skbinfo.skbmark = fullmark >> 32;
ext->skbmarkmask = fullmark & 0xffffffff; ext->skbinfo.skbmarkmask = fullmark & 0xffffffff;
} }
if (tb[IPSET_ATTR_SKBPRIO]) { if (tb[IPSET_ATTR_SKBPRIO]) {
if (!SET_WITH_SKBINFO(set)) if (!SET_WITH_SKBINFO(set))
return -IPSET_ERR_SKBINFO; return -IPSET_ERR_SKBINFO;
ext->skbprio = be32_to_cpu(nla_get_be32( ext->skbinfo.skbprio =
tb[IPSET_ATTR_SKBPRIO])); be32_to_cpu(nla_get_be32(tb[IPSET_ATTR_SKBPRIO]));
} }
if (tb[IPSET_ATTR_SKBQUEUE]) { if (tb[IPSET_ATTR_SKBQUEUE]) {
if (!SET_WITH_SKBINFO(set)) if (!SET_WITH_SKBINFO(set))
return -IPSET_ERR_SKBINFO; return -IPSET_ERR_SKBINFO;
ext->skbqueue = be16_to_cpu(nla_get_be16( ext->skbinfo.skbqueue =
tb[IPSET_ATTR_SKBQUEUE])); be16_to_cpu(nla_get_be16(tb[IPSET_ATTR_SKBQUEUE]));
} }
return 0; return 0;
} }

View file

@ -423,6 +423,8 @@ set_target_v2(struct sk_buff *skb, const struct xt_action_param *par)
/* Revision 3 target */ /* Revision 3 target */
#define MOPT(opt, member) ((opt).ext.skbinfo.member)
static unsigned int static unsigned int
set_target_v3(struct sk_buff *skb, const struct xt_action_param *par) set_target_v3(struct sk_buff *skb, const struct xt_action_param *par)
{ {
@ -453,14 +455,14 @@ set_target_v3(struct sk_buff *skb, const struct xt_action_param *par)
if (!ret) if (!ret)
return XT_CONTINUE; return XT_CONTINUE;
if (map_opt.cmdflags & IPSET_FLAG_MAP_SKBMARK) if (map_opt.cmdflags & IPSET_FLAG_MAP_SKBMARK)
skb->mark = (skb->mark & ~(map_opt.ext.skbmarkmask)) skb->mark = (skb->mark & ~MOPT(map_opt,skbmarkmask))
^ (map_opt.ext.skbmark); ^ MOPT(map_opt, skbmark);
if (map_opt.cmdflags & IPSET_FLAG_MAP_SKBPRIO) if (map_opt.cmdflags & IPSET_FLAG_MAP_SKBPRIO)
skb->priority = map_opt.ext.skbprio; skb->priority = MOPT(map_opt, skbprio);
if ((map_opt.cmdflags & IPSET_FLAG_MAP_SKBQUEUE) && if ((map_opt.cmdflags & IPSET_FLAG_MAP_SKBQUEUE) &&
skb->dev && skb->dev &&
skb->dev->real_num_tx_queues > map_opt.ext.skbqueue) skb->dev->real_num_tx_queues > MOPT(map_opt, skbqueue))
skb_set_queue_mapping(skb, map_opt.ext.skbqueue); skb_set_queue_mapping(skb, MOPT(map_opt, skbqueue));
} }
return XT_CONTINUE; return XT_CONTINUE;
} }