netdev-vport: Make netdev_vport_patch_peer() return a malloc()'d string.
authorBen Pfaff <blp@nicira.com>
Wed, 31 Jul 2013 21:09:30 +0000 (14:09 -0700)
committerBen Pfaff <blp@nicira.com>
Sat, 10 Aug 2013 04:23:19 +0000 (21:23 -0700)
When threading comes into the picture there arises the possibility of a
race between netdev_vport_patch_peer()'s caller using the returned string
and another caller changing the peer.  It is safer to return a copy.

Signed-off-by: Ben Pfaff <blp@nicira.com>
lib/netdev-vport.c
lib/netdev-vport.h
ofproto/ofproto-dpif.c

index ac3da63..287edae 100644 (file)
@@ -553,12 +553,23 @@ get_tunnel_config(const struct netdev *dev, struct smap *args)
 \f
 /* Code specific to patch ports. */
 
-const char *
-netdev_vport_patch_peer(const struct netdev *netdev)
+/* If 'netdev' is a patch port, returns the name of its peer as a malloc()'d
+ * string that the caller must free.
+ *
+ * If 'netdev' is not a patch port, returns NULL. */
+char *
+netdev_vport_patch_peer(const struct netdev *netdev_)
 {
-    return (netdev_vport_is_patch(netdev)
-            ? netdev_vport_cast(netdev)->peer
-            : NULL);
+    char *peer = NULL;
+
+    if (netdev_vport_is_patch(netdev_)) {
+        struct netdev_vport *netdev = netdev_vport_cast(netdev_);
+        if (netdev->peer) {
+            peer = xstrdup(netdev->peer);
+        }
+    }
+
+    return peer;
 }
 
 void
index 5394966..dc49097 100644 (file)
@@ -31,7 +31,7 @@ void netdev_vport_patch_register(void);
 
 bool netdev_vport_is_patch(const struct netdev *);
 
-const char *netdev_vport_patch_peer(const struct netdev *netdev);
+char *netdev_vport_patch_peer(const struct netdev *netdev);
 
 void netdev_vport_inc_rx(const struct netdev *,
                          const struct dpif_flow_stats *);
index 1582619..13faad6 100644 (file)
@@ -2905,7 +2905,7 @@ ofport_update_peer(struct ofport_dpif *ofport)
 {
     const struct ofproto_dpif *ofproto;
     struct dpif_backer *backer;
-    const char *peer_name;
+    char *peer_name;
 
     if (!netdev_vport_is_patch(ofport->up.netdev)) {
         return;
@@ -2927,7 +2927,7 @@ ofport_update_peer(struct ofport_dpif *ofport)
     HMAP_FOR_EACH (ofproto, all_ofproto_dpifs_node, &all_ofproto_dpifs) {
         struct ofport *peer_ofport;
         struct ofport_dpif *peer;
-        const char *peer_peer;
+        char *peer_peer;
 
         if (ofproto->backer != backer) {
             continue;
@@ -2945,9 +2945,11 @@ ofport_update_peer(struct ofport_dpif *ofport)
             ofport->peer = peer;
             ofport->peer->peer = ofport;
         }
+        free(peer_peer);
 
-        return;
+        break;
     }
+    free(peer_name);
 }
 
 static void