[ovs-dev] [PATCH 2/5] datapath: Don't write into IPV4_TUNNEL data when using TUN_ID.

Jesse Gross jesse at nicira.com
Wed Nov 7 00:50:17 UTC 2012


When the IPV4_TUNNEL action is executed, a pointer in the skb is
directly assigned the address of the action, which is protected by
RCU.  If a TUN_ID action is later executed it will write into the
action, which is not allowed by RCU.  This avoids the problem by
making a copy of the data and writing into the copy.

Signed-off-by: Jesse Gross <jesse at nicira.com>
---
 datapath/actions.c |   20 +++++++++++---------
 1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/datapath/actions.c b/datapath/actions.c
index 4649c05..8ec692d 100644
--- a/datapath/actions.c
+++ b/datapath/actions.c
@@ -346,15 +346,17 @@ static int execute_set_action(struct sk_buff *skb,
 		break;
 
 	case OVS_KEY_ATTR_TUN_ID:
-		if (!OVS_CB(skb)->tun_key) {
-			/* If tun_key is NULL for this skb, assign it to
-			 * a value the caller passed in for action processing
-			 * and output. This can disappear once we drop support
-			 * for setting tun_id outside of tun_key.
-			 */
-			memset(tun_key, 0, sizeof(struct ovs_key_ipv4_tunnel));
-			OVS_CB(skb)->tun_key = tun_key;
-		}
+		/* If we're only using the TUN_ID action, store the value in a
+		 * temporary instance of struct ovs_key_ipv4_tunnel on the stack.
+		 * If both IPV4_TUNNEL and TUN_ID are being used together we
+		 * can't write into the IPV4_TUNNEL action, so make a copy and
+		 * write into that version.
+		 */
+		if (!OVS_CB(skb)->tun_key)
+			memset(tun_key, 0, sizeof(*tun_key));
+		else if (OVS_CB(skb)->tun_key != tun_key)
+			memcpy(tun_key, OVS_CB(skb)->tun_key, sizeof(*tun_key));
+		OVS_CB(skb)->tun_key = tun_key;
 
 		OVS_CB(skb)->tun_key->tun_id = nla_get_be64(nested_attr);
 		break;
-- 
1.7.9.5




More information about the dev mailing list