netfilter: ipset: Improve skbinfo get/init helpers
authorJozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Tue, 5 May 2015 15:13:28 +0000 (17:13 +0200)
committerJozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Thu, 10 Nov 2016 12:28:42 +0000 (13:28 +0100)
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>
include/linux/netfilter/ipset/ip_set.h
net/netfilter/ipset/ip_set_core.c
net/netfilter/xt_set.c

index 1ea28e30a6dd08cbd63a751a0f9c1725c9072ed2..780262124632246cd784fac4f9a9f798e157265f 100644 (file)
@@ -92,17 +92,6 @@ struct ip_set_ext_type {
 
 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 {
        atomic64_t bytes;
        atomic64_t packets;
@@ -122,6 +111,15 @@ struct ip_set_skbinfo {
        u32 skbmarkmask;
        u32 skbprio;
        u16 skbqueue;
+       u16 __pad;
+};
+
+struct ip_set_ext {
+       struct ip_set_skbinfo skbinfo;
+       u64 packets;
+       u64 bytes;
+       char *comment;
+       u32 timeout;
 };
 
 struct ip_set;
@@ -360,10 +358,7 @@ ip_set_get_skbinfo(struct ip_set_skbinfo *skbinfo,
                   const struct ip_set_ext *ext,
                   struct ip_set_ext *mext, u32 flags)
 {
-       mext->skbmark = skbinfo->skbmark;
-       mext->skbmarkmask = skbinfo->skbmarkmask;
-       mext->skbprio = skbinfo->skbprio;
-       mext->skbqueue = skbinfo->skbqueue;
+       mext->skbinfo = *skbinfo;
 }
 
 static inline bool
@@ -387,10 +382,7 @@ static inline void
 ip_set_init_skbinfo(struct ip_set_skbinfo *skbinfo,
                    const struct ip_set_ext *ext)
 {
-       skbinfo->skbmark = ext->skbmark;
-       skbinfo->skbmarkmask = ext->skbmarkmask;
-       skbinfo->skbprio = ext->skbprio;
-       skbinfo->skbqueue = ext->skbqueue;
+       *skbinfo = ext->skbinfo;
 }
 
 /* Netlink CB args */
index 3f1b945a24d5cfa5d36fb6b30cfa6bd965b6db04..bfacccff7196c3e791daf66af5e37425395e0ccd 100644 (file)
@@ -426,20 +426,20 @@ ip_set_get_extensions(struct ip_set *set, struct nlattr *tb[],
                if (!SET_WITH_SKBINFO(set))
                        return -IPSET_ERR_SKBINFO;
                fullmark = be64_to_cpu(nla_get_be64(tb[IPSET_ATTR_SKBMARK]));
-               ext->skbmark = fullmark >> 32;
-               ext->skbmarkmask = fullmark & 0xffffffff;
+               ext->skbinfo.skbmark = fullmark >> 32;
+               ext->skbinfo.skbmarkmask = fullmark & 0xffffffff;
        }
        if (tb[IPSET_ATTR_SKBPRIO]) {
                if (!SET_WITH_SKBINFO(set))
                        return -IPSET_ERR_SKBINFO;
-               ext->skbprio = be32_to_cpu(nla_get_be32(
-                                           tb[IPSET_ATTR_SKBPRIO]));
+               ext->skbinfo.skbprio =
+                       be32_to_cpu(nla_get_be32(tb[IPSET_ATTR_SKBPRIO]));
        }
        if (tb[IPSET_ATTR_SKBQUEUE]) {
                if (!SET_WITH_SKBINFO(set))
                        return -IPSET_ERR_SKBINFO;
-               ext->skbqueue = be16_to_cpu(nla_get_be16(
-                                           tb[IPSET_ATTR_SKBQUEUE]));
+               ext->skbinfo.skbqueue =
+                       be16_to_cpu(nla_get_be16(tb[IPSET_ATTR_SKBQUEUE]));
        }
        return 0;
 }
index 1bfede7be4183cc4bf3a9f060ba8effb6cc1df1d..64285702afd54421e00f512860d9f1896df62969 100644 (file)
@@ -423,6 +423,8 @@ set_target_v2(struct sk_buff *skb, const struct xt_action_param *par)
 
 /* Revision 3 target */
 
+#define MOPT(opt, member)      ((opt).ext.skbinfo.member)
+
 static unsigned int
 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)
                        return XT_CONTINUE;
                if (map_opt.cmdflags & IPSET_FLAG_MAP_SKBMARK)
-                       skb->mark = (skb->mark & ~(map_opt.ext.skbmarkmask))
-                                   ^ (map_opt.ext.skbmark);
+                       skb->mark = (skb->mark & ~MOPT(map_opt,skbmarkmask))
+                                   ^ MOPT(map_opt, skbmark);
                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) &&
                    skb->dev &&
-                   skb->dev->real_num_tx_queues > map_opt.ext.skbqueue)
-                       skb_set_queue_mapping(skb, map_opt.ext.skbqueue);
+                   skb->dev->real_num_tx_queues > MOPT(map_opt, skbqueue))
+                       skb_set_queue_mapping(skb, MOPT(map_opt, skbqueue));
        }
        return XT_CONTINUE;
 }