]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
batman-adv: Make DAT capability changes atomic
authorLinus Lüssing <linus.luessing@c0d3.blue>
Tue, 16 Jun 2015 15:10:22 +0000 (17:10 +0200)
committerLuis Henriques <luis.henriques@canonical.com>
Wed, 30 Sep 2015 12:20:40 +0000 (13:20 +0100)
commit 65d7d46050704bcdb8121ddbf4110bfbf2b38baa upstream.

Bitwise OR/AND assignments in C aren't guaranteed to be atomic. One
OGM handler might undo the set/clear of a specific bit from another
handler run in between.

Fix this by using the atomic set_bit()/clear_bit()/test_bit() functions.

Fixes: 17cf0ea455f1 ("batman-adv: tvlv - add distributed arp table container")
Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue>
Signed-off-by: Marek Lindner <mareklindner@neomailbox.ch>
Signed-off-by: Antonio Quartulli <antonio@meshcoding.com>
[ luis: backported to 3.16: adjusted context ]
Signed-off-by: Luis Henriques <luis.henriques@canonical.com>
net/batman-adv/distributed-arp-table.c
net/batman-adv/types.h

index f2c066b2171640c4092a60bc6fc8ef603baa5c09..28d70b941bb59f1029b8018c2a8ef1c1664c7cdc 100644 (file)
@@ -15,6 +15,7 @@
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/bitops.h>
 #include <linux/if_ether.h>
 #include <linux/if_arp.h>
 #include <linux/if_vlan.h>
@@ -422,7 +423,7 @@ static bool batadv_is_orig_node_eligible(struct batadv_dat_candidate *res,
        int j;
 
        /* check if orig node candidate is running DAT */
-       if (!(candidate->capabilities & BATADV_ORIG_CAPA_HAS_DAT))
+       if (!test_bit(BATADV_ORIG_CAPA_HAS_DAT, &candidate->capabilities))
                goto out;
 
        /* Check if this node has already been selected... */
@@ -681,9 +682,9 @@ static void batadv_dat_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv,
                                           uint16_t tvlv_value_len)
 {
        if (flags & BATADV_TVLV_HANDLER_OGM_CIFNOTFND)
-               orig->capabilities &= ~BATADV_ORIG_CAPA_HAS_DAT;
+               clear_bit(BATADV_ORIG_CAPA_HAS_DAT, &orig->capabilities);
        else
-               orig->capabilities |= BATADV_ORIG_CAPA_HAS_DAT;
+               set_bit(BATADV_ORIG_CAPA_HAS_DAT, &orig->capabilities);
 }
 
 /**
index 8854c05622a9bae2b8f30b0cf91686e8c629a849..3d316c8d340cea79f88992c9fa1c2ce456f581ab 100644 (file)
@@ -258,7 +258,7 @@ struct batadv_orig_node {
        struct hlist_node mcast_want_all_ipv4_node;
        struct hlist_node mcast_want_all_ipv6_node;
 #endif
-       uint8_t capabilities;
+       unsigned long capabilities;
        uint8_t capa_initialized;
        atomic_t last_ttvn;
        unsigned char *tt_buff;
@@ -298,7 +298,7 @@ struct batadv_orig_node {
  *  (= orig node announces a tvlv of type BATADV_TVLV_MCAST)
  */
 enum batadv_orig_capabilities {
-       BATADV_ORIG_CAPA_HAS_DAT = BIT(0),
+       BATADV_ORIG_CAPA_HAS_DAT,
        BATADV_ORIG_CAPA_HAS_NC = BIT(1),
        BATADV_ORIG_CAPA_HAS_TT = BIT(2),
        BATADV_ORIG_CAPA_HAS_MCAST = BIT(3),