]> granicus.if.org Git - ipset/commitdiff
Make sure bitmap:ip,mac detects the proper MAC even when it's overwritten
authorJozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Sun, 29 Mar 2015 14:34:52 +0000 (16:34 +0200)
committerJozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Sun, 29 Mar 2015 14:56:00 +0000 (16:56 +0200)
Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
kernel/net/netfilter/ipset/ip_set_bitmap_gen.h
kernel/net/netfilter/ipset/ip_set_bitmap_ip.c
kernel/net/netfilter/ipset/ip_set_bitmap_ipmac.c
kernel/net/netfilter/ipset/ip_set_bitmap_port.c

index 381a011327f088dcf1246c4976d95840919ced03..d05e759ed0fafe62ef299e6f097f0d18f08ec567 100644 (file)
@@ -144,10 +144,12 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext,
 
        if (ret == IPSET_ADD_FAILED) {
                if (SET_WITH_TIMEOUT(set) &&
-                   ip_set_timeout_expired(ext_timeout(x, set)))
+                   ip_set_timeout_expired(ext_timeout(x, set))) {
                        ret = 0;
-               else if (!(flags & IPSET_FLAG_EXIST))
+               } else if (!(flags & IPSET_FLAG_EXIST)) {
+                       set_bit(e->id, map->members);
                        return -IPSET_ERR_EXIST;
+               }
                /* Element is re-added, cleanup extensions */
                ip_set_ext_destroy(set, x);
        }
@@ -165,6 +167,10 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext,
                ip_set_init_comment(ext_comment(x, set), ext);
        if (SET_WITH_SKBINFO(set))
                ip_set_init_skbinfo(ext_skbinfo(x, set), ext);
+
+       /* Activate element */
+       set_bit(e->id, map->members);
+
        return 0;
 }
 
index fc4538e29ceb724d33a47f7148f3429fa2e1150d..1f4a20bf5dd7cdc92ce28a57f26e065dc178a398 100644 (file)
@@ -81,7 +81,7 @@ static inline int
 bitmap_ip_do_add(const struct bitmap_ip_adt_elem *e, struct bitmap_ip *map,
                 u32 flags, size_t dsize)
 {
-       return !!test_and_set_bit(e->id, map->members);
+       return !!test_bit(e->id, map->members);
 }
 
 static inline int
index 3eaba9736d78c452bd884469a04f64aeaecee941..3e60d3fa20dbebfa8d0b23e8bd4a36112805c32c 100644 (file)
@@ -148,15 +148,23 @@ bitmap_ipmac_do_add(const struct bitmap_ipmac_adt_elem *e,
        struct bitmap_ipmac_elem *elem;
 
        elem = get_elem(map->extensions, e->id, dsize);
-       if (test_and_set_bit(e->id, map->members)) {
+       if (test_bit(e->id, map->members)) {
                if (elem->filled == MAC_FILLED) {
-                       if (e->ether && (flags & IPSET_FLAG_EXIST))
+                       if (e->ether &&
+                           (flags & IPSET_FLAG_EXIST) &&
+                           !ether_addr_equal(e->ether, elem->ether)) {
+                               /* memcpy isn't atomic */
+                               clear_bit(e->id, map->members);
+                               smp_mb__after_atomic();
                                memcpy(elem->ether, e->ether, ETH_ALEN);
+                       }
                        return IPSET_ADD_FAILED;
                } else if (!e->ether)
                        /* Already added without ethernet address */
                        return IPSET_ADD_FAILED;
                /* Fill the MAC address and trigger the timer activation */
+               clear_bit(e->id, map->members);
+               smp_mb__after_atomic();
                memcpy(elem->ether, e->ether, ETH_ALEN);
                elem->filled = MAC_FILLED;
                return IPSET_ADD_START_STORED_TIMEOUT;
index 020b850d5a9a3a2915c3398691a3814a0f0f9ac0..a467a4f452b1bad78b18ac8dac4121cb3d8848ba 100644 (file)
@@ -73,7 +73,7 @@ static inline int
 bitmap_port_do_add(const struct bitmap_port_adt_elem *e,
                   struct bitmap_port *map, u32 flags, size_t dsize)
 {
-       return !!test_and_set_bit(e->id, map->members);
+       return !!test_bit(e->id, map->members);
 }
 
 static inline int