diff options
author | Marek Lindner <lindner_marek@yahoo.de> | 2011-04-20 09:40:58 -0400 |
---|---|---|
committer | Sven Eckelmann <sven@narfation.org> | 2011-05-01 16:49:03 -0400 |
commit | 32ae9b221e788413ce68feaae2ca39e406211a0a (patch) | |
tree | d827f989976a28fea5cdcb349c308baa98182c35 /net/batman-adv/routing.c | |
parent | 71e4aa9c465fd66c110667ab5d620fb6a4ef2157 (diff) |
batman-adv: Make bat_priv->primary_if an rcu protected pointer
The rcu protected macros rcu_dereference() and rcu_assign_pointer()
for the bat_priv->primary_if need to be used, as well as spin/rcu locking.
Otherwise we might end up using a primary_if pointer pointing to already
freed memory.
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Diffstat (limited to 'net/batman-adv/routing.c')
-rw-r--r-- | net/batman-adv/routing.c | 18 |
1 files changed, 12 insertions, 6 deletions
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index 2d77bd3a3e9a..49f571553050 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c | |||
@@ -904,6 +904,7 @@ int recv_bat_packet(struct sk_buff *skb, struct hard_iface *hard_iface) | |||
904 | static int recv_my_icmp_packet(struct bat_priv *bat_priv, | 904 | static int recv_my_icmp_packet(struct bat_priv *bat_priv, |
905 | struct sk_buff *skb, size_t icmp_len) | 905 | struct sk_buff *skb, size_t icmp_len) |
906 | { | 906 | { |
907 | struct hard_iface *primary_if = NULL; | ||
907 | struct orig_node *orig_node = NULL; | 908 | struct orig_node *orig_node = NULL; |
908 | struct neigh_node *router = NULL; | 909 | struct neigh_node *router = NULL; |
909 | struct icmp_packet_rr *icmp_packet; | 910 | struct icmp_packet_rr *icmp_packet; |
@@ -917,7 +918,8 @@ static int recv_my_icmp_packet(struct bat_priv *bat_priv, | |||
917 | goto out; | 918 | goto out; |
918 | } | 919 | } |
919 | 920 | ||
920 | if (!bat_priv->primary_if) | 921 | primary_if = primary_if_get_selected(bat_priv); |
922 | if (!primary_if) | ||
921 | goto out; | 923 | goto out; |
922 | 924 | ||
923 | /* answer echo request (ping) */ | 925 | /* answer echo request (ping) */ |
@@ -937,8 +939,7 @@ static int recv_my_icmp_packet(struct bat_priv *bat_priv, | |||
937 | icmp_packet = (struct icmp_packet_rr *)skb->data; | 939 | icmp_packet = (struct icmp_packet_rr *)skb->data; |
938 | 940 | ||
939 | memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN); | 941 | memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN); |
940 | memcpy(icmp_packet->orig, | 942 | memcpy(icmp_packet->orig, primary_if->net_dev->dev_addr, ETH_ALEN); |
941 | bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); | ||
942 | icmp_packet->msg_type = ECHO_REPLY; | 943 | icmp_packet->msg_type = ECHO_REPLY; |
943 | icmp_packet->ttl = TTL; | 944 | icmp_packet->ttl = TTL; |
944 | 945 | ||
@@ -946,6 +947,8 @@ static int recv_my_icmp_packet(struct bat_priv *bat_priv, | |||
946 | ret = NET_RX_SUCCESS; | 947 | ret = NET_RX_SUCCESS; |
947 | 948 | ||
948 | out: | 949 | out: |
950 | if (primary_if) | ||
951 | hardif_free_ref(primary_if); | ||
949 | if (router) | 952 | if (router) |
950 | neigh_node_free_ref(router); | 953 | neigh_node_free_ref(router); |
951 | if (orig_node) | 954 | if (orig_node) |
@@ -956,6 +959,7 @@ out: | |||
956 | static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv, | 959 | static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv, |
957 | struct sk_buff *skb) | 960 | struct sk_buff *skb) |
958 | { | 961 | { |
962 | struct hard_iface *primary_if = NULL; | ||
959 | struct orig_node *orig_node = NULL; | 963 | struct orig_node *orig_node = NULL; |
960 | struct neigh_node *router = NULL; | 964 | struct neigh_node *router = NULL; |
961 | struct icmp_packet *icmp_packet; | 965 | struct icmp_packet *icmp_packet; |
@@ -971,7 +975,8 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv, | |||
971 | goto out; | 975 | goto out; |
972 | } | 976 | } |
973 | 977 | ||
974 | if (!bat_priv->primary_if) | 978 | primary_if = primary_if_get_selected(bat_priv); |
979 | if (!primary_if) | ||
975 | goto out; | 980 | goto out; |
976 | 981 | ||
977 | /* get routing information */ | 982 | /* get routing information */ |
@@ -990,8 +995,7 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv, | |||
990 | icmp_packet = (struct icmp_packet *)skb->data; | 995 | icmp_packet = (struct icmp_packet *)skb->data; |
991 | 996 | ||
992 | memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN); | 997 | memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN); |
993 | memcpy(icmp_packet->orig, | 998 | memcpy(icmp_packet->orig, primary_if->net_dev->dev_addr, ETH_ALEN); |
994 | bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); | ||
995 | icmp_packet->msg_type = TTL_EXCEEDED; | 999 | icmp_packet->msg_type = TTL_EXCEEDED; |
996 | icmp_packet->ttl = TTL; | 1000 | icmp_packet->ttl = TTL; |
997 | 1001 | ||
@@ -999,6 +1003,8 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv, | |||
999 | ret = NET_RX_SUCCESS; | 1003 | ret = NET_RX_SUCCESS; |
1000 | 1004 | ||
1001 | out: | 1005 | out: |
1006 | if (primary_if) | ||
1007 | hardif_free_ref(primary_if); | ||
1002 | if (router) | 1008 | if (router) |
1003 | neigh_node_free_ref(router); | 1009 | neigh_node_free_ref(router); |
1004 | if (orig_node) | 1010 | if (orig_node) |