From: Jesse Gross Date: Mon, 5 Nov 2012 19:30:35 +0000 (-0800) Subject: datapath: Don't write into IPV4_TUNNEL data when using TUN_ID. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?p=openvswitch;a=commitdiff_plain;h=dee54b830c3d43facf96c129b04265f31f503200 datapath: Don't write into IPV4_TUNNEL data when using TUN_ID. 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 Acked-by: Kyle Mestery --- diff --git a/datapath/actions.c b/datapath/actions.c index 4649c050..8ec692d1 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;