diff mbox

[ovs-dev,v2,2/2] ovs-vswitchd: Avoid segfault for "netdev" datapath.

Message ID 1481133844-120196-2-git-send-email-nic@opencloud.tech
State Accepted
Headers show

Commit Message

nickcooper-zhangtonghao Dec. 7, 2016, 6:04 p.m. UTC
When the datapath, whose type is "netdev", processes packets
in userspce action, it may cause a segmentation fault. In the
dp_execute_userspace_action(), we pass the "wc" argument to
dp_netdev_upcall() using NULL. In the dp_netdev_upcall() call tree,
the "wc" will be used. For example, dp_netdev_upcall() uses the
&wc->masks for debugging, and flow_wildcards_init_for_packet()
uses the  "wc" if we disable megaflow, which is described in
more detail below.

Segmentation fault in flow_wildcards_init_for_packet:

    #0  0x0000000000468fe8 flow_wildcards_init_for_packet lib/flow.c:1275
    #1  0x0000000000436c0b upcall_cb ofproto/ofproto-dpif-upcall.c:1231
    #2  0x000000000045bd96 dp_netdev_upcall lib/dpif-netdev.c:3857
    #3  0x0000000000461bf3 dp_execute_userspace_action lib/dpif-netdev.c:4388
    #4  dp_execute_cb lib/dpif-netdev.c:4521
    #5  0x0000000000486ae2 odp_execute_actions lib/odp-execute.c:538
    #6  0x00000000004607f9 dp_netdev_execute_actions lib/dpif-netdev.c:4627
    #7  packet_batch_per_flow_execute lib/dpif-netdev.c:3927
    #8  dp_netdev_input__ lib/dpif-netdev.c:4229
    #9  0x0000000000460ba8 dp_netdev_input lib/dpif-netdev.c:4238
    #10 dp_netdev_process_rxq_port lib/dpif-netdev.c:2873
    #11 0x000000000046126e dpif_netdev_run lib/dpif-netdev.c:3000
    #12 0x000000000042baf5 type_run ofproto/ofproto-dpif.c:504
    #13 0x00000000004192bf ofproto_type_run ofproto/ofproto.c:1687
    #14 0x0000000000409965 bridge_run__ vswitchd/bridge.c:2875
    #15 0x000000000040f145 bridge_run vswitchd/bridge.c:2938
    #16 0x00000000004062e5 main vswitchd/ovs-vswitchd.c:111

Signed-off-by: nickcooper-zhangtonghao <nic@opencloud.tech>
Signed-off-by: Daniele Di Proietto <diproiettod@ovn.org>
---
 lib/dpif-netdev.c             |  2 +-
 ofproto/ofproto-dpif-upcall.c |  4 ++--
 tests/ofproto-dpif.at         | 34 ++++++++++++++++++++++++++++++++++
 3 files changed, 37 insertions(+), 3 deletions(-)

Comments

Daniele Di Proietto Dec. 9, 2016, 8:09 p.m. UTC | #1
2016-12-07 10:04 GMT-08:00 nickcooper-zhangtonghao <nic@opencloud.tech>:
> When the datapath, whose type is "netdev", processes packets
> in userspce action, it may cause a segmentation fault. In the
> dp_execute_userspace_action(), we pass the "wc" argument to
> dp_netdev_upcall() using NULL. In the dp_netdev_upcall() call tree,
> the "wc" will be used. For example, dp_netdev_upcall() uses the
> &wc->masks for debugging, and flow_wildcards_init_for_packet()
> uses the  "wc" if we disable megaflow, which is described in
> more detail below.
>
> Segmentation fault in flow_wildcards_init_for_packet:
>
>     #0  0x0000000000468fe8 flow_wildcards_init_for_packet lib/flow.c:1275
>     #1  0x0000000000436c0b upcall_cb ofproto/ofproto-dpif-upcall.c:1231
>     #2  0x000000000045bd96 dp_netdev_upcall lib/dpif-netdev.c:3857
>     #3  0x0000000000461bf3 dp_execute_userspace_action lib/dpif-netdev.c:4388
>     #4  dp_execute_cb lib/dpif-netdev.c:4521
>     #5  0x0000000000486ae2 odp_execute_actions lib/odp-execute.c:538
>     #6  0x00000000004607f9 dp_netdev_execute_actions lib/dpif-netdev.c:4627
>     #7  packet_batch_per_flow_execute lib/dpif-netdev.c:3927
>     #8  dp_netdev_input__ lib/dpif-netdev.c:4229
>     #9  0x0000000000460ba8 dp_netdev_input lib/dpif-netdev.c:4238
>     #10 dp_netdev_process_rxq_port lib/dpif-netdev.c:2873
>     #11 0x000000000046126e dpif_netdev_run lib/dpif-netdev.c:3000
>     #12 0x000000000042baf5 type_run ofproto/ofproto-dpif.c:504
>     #13 0x00000000004192bf ofproto_type_run ofproto/ofproto.c:1687
>     #14 0x0000000000409965 bridge_run__ vswitchd/bridge.c:2875
>     #15 0x000000000040f145 bridge_run vswitchd/bridge.c:2938
>     #16 0x00000000004062e5 main vswitchd/ovs-vswitchd.c:111
>
> Signed-off-by: nickcooper-zhangtonghao <nic@opencloud.tech>
> Signed-off-by: Daniele Di Proietto <diproiettod@ovn.org>

Thanks!

I added another check for 'wc' in ukey_create_from_upcall().

I pushed this to master, branch-2.6 and branch-2.5

> ---
>  lib/dpif-netdev.c             |  2 +-
>  ofproto/ofproto-dpif-upcall.c |  4 ++--
>  tests/ofproto-dpif.at         | 34 ++++++++++++++++++++++++++++++++++
>  3 files changed, 37 insertions(+), 3 deletions(-)
>
> diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
> index 1400511..0b73056 100644
> --- a/lib/dpif-netdev.c
> +++ b/lib/dpif-netdev.c
> @@ -3834,7 +3834,7 @@ dp_netdev_upcall(struct dp_netdev_pmd_thread *pmd, struct dp_packet *packet_,
>          struct ofpbuf key;
>          struct odp_flow_key_parms odp_parms = {
>              .flow = flow,
> -            .mask = &wc->masks,
> +            .mask = wc ? &wc->masks : NULL,
>              .support = dp_netdev_support,
>          };
>
> diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c
> index 6cb9c2e..aa7eabf 100644
> --- a/ofproto/ofproto-dpif-upcall.c
> +++ b/ofproto/ofproto-dpif-upcall.c
> @@ -1227,7 +1227,7 @@ upcall_cb(const struct dp_packet *packet, const struct flow *flow, ovs_u128 *ufi
>                     upcall.put_actions.size);
>      }
>
> -    if (OVS_UNLIKELY(!megaflow)) {
> +    if (OVS_UNLIKELY(!megaflow && wc)) {
>          flow_wildcards_init_for_packet(wc, flow);
>      }
>
> @@ -1504,7 +1504,7 @@ ukey_create_from_upcall(struct upcall *upcall, struct flow_wildcards *wc)
>      bool megaflow;
>      struct odp_flow_key_parms odp_parms = {
>          .flow = upcall->flow,
> -        .mask = &wc->masks,
> +        .mask = wc ? &wc->masks : NULL,
>      };
>
>      odp_parms.support = ofproto_dpif_get_support(upcall->ofproto)->odp;
> diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at
> index cd90424..6d57445 100644
> --- a/tests/ofproto-dpif.at
> +++ b/tests/ofproto-dpif.at
> @@ -1627,6 +1627,40 @@ NXST_FLOW reply:
>  OVS_VSWITCHD_STOP
>  AT_CLEANUP
>
> +AT_SETUP([ofproto-dpif - controller action without megaflows])
> +OVS_VSWITCHD_START
> +add_of_ports br0 1
> +
> +AT_CHECK([ovs-ofctl add-flow br0 in_port=1,action=controller])
> +AT_CHECK([ovs-appctl upcall/disable-megaflows], [0], [dnl
> +megaflows disabled
> +])
> +
> +AT_CAPTURE_FILE([ofctl_monitor.log])
> +AT_CHECK([ovs-ofctl monitor br0 65534 invalid_ttl -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])
> +
> +for i in 1 2; do
> +    AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x1234)'])
> +done
> +
> +OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 4])
> +OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
> +
> +AT_CHECK([ovs-appctl dpctl/dump-flows | sed 's/.*\(packets:\)/\1/' | sed 's/used:[[0-9]].[[0-9]]*s/used:0.001s/'], [0], [dnl
> +flow-dump from non-dpdk interfaces:
> +packets:1, bytes:14, used:0.001s, actions:userspace(pid=0,slow_path(controller))
> +])
> +
> +AT_CHECK([cat ofctl_monitor.log], [0], [dnl
> +NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=14 in_port=1 (via action) data_len=14 (unbuffered)
> +vlan_tci=0x0000,dl_src=50:54:00:00:00:09,dl_dst=50:54:00:00:00:0a,dl_type=0x1234
> +NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=14 in_port=1 (via action) data_len=14 (unbuffered)
> +vlan_tci=0x0000,dl_src=50:54:00:00:00:09,dl_dst=50:54:00:00:00:0a,dl_type=0x1234
> +])
> +
> +OVS_VSWITCHD_STOP
> +AT_CLEANUP
> +
>  AT_SETUP([ofproto-dpif - MPLS handling])
>  OVS_VSWITCHD_START([dnl
>     add-port br0 p1 -- set Interface p1 type=dummy
> --
> 1.8.3.1
>
>
>
diff mbox

Patch

diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index 1400511..0b73056 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -3834,7 +3834,7 @@  dp_netdev_upcall(struct dp_netdev_pmd_thread *pmd, struct dp_packet *packet_,
         struct ofpbuf key;
         struct odp_flow_key_parms odp_parms = {
             .flow = flow,
-            .mask = &wc->masks,
+            .mask = wc ? &wc->masks : NULL,
             .support = dp_netdev_support,
         };
 
diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c
index 6cb9c2e..aa7eabf 100644
--- a/ofproto/ofproto-dpif-upcall.c
+++ b/ofproto/ofproto-dpif-upcall.c
@@ -1227,7 +1227,7 @@  upcall_cb(const struct dp_packet *packet, const struct flow *flow, ovs_u128 *ufi
                    upcall.put_actions.size);
     }
 
-    if (OVS_UNLIKELY(!megaflow)) {
+    if (OVS_UNLIKELY(!megaflow && wc)) {
         flow_wildcards_init_for_packet(wc, flow);
     }
 
@@ -1504,7 +1504,7 @@  ukey_create_from_upcall(struct upcall *upcall, struct flow_wildcards *wc)
     bool megaflow;
     struct odp_flow_key_parms odp_parms = {
         .flow = upcall->flow,
-        .mask = &wc->masks,
+        .mask = wc ? &wc->masks : NULL,
     };
 
     odp_parms.support = ofproto_dpif_get_support(upcall->ofproto)->odp;
diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at
index cd90424..6d57445 100644
--- a/tests/ofproto-dpif.at
+++ b/tests/ofproto-dpif.at
@@ -1627,6 +1627,40 @@  NXST_FLOW reply:
 OVS_VSWITCHD_STOP
 AT_CLEANUP
 
+AT_SETUP([ofproto-dpif - controller action without megaflows])
+OVS_VSWITCHD_START
+add_of_ports br0 1
+
+AT_CHECK([ovs-ofctl add-flow br0 in_port=1,action=controller])
+AT_CHECK([ovs-appctl upcall/disable-megaflows], [0], [dnl
+megaflows disabled
+])
+
+AT_CAPTURE_FILE([ofctl_monitor.log])
+AT_CHECK([ovs-ofctl monitor br0 65534 invalid_ttl -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])
+
+for i in 1 2; do
+    AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x1234)'])
+done
+
+OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 4])
+OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
+
+AT_CHECK([ovs-appctl dpctl/dump-flows | sed 's/.*\(packets:\)/\1/' | sed 's/used:[[0-9]].[[0-9]]*s/used:0.001s/'], [0], [dnl
+flow-dump from non-dpdk interfaces:
+packets:1, bytes:14, used:0.001s, actions:userspace(pid=0,slow_path(controller))
+])
+
+AT_CHECK([cat ofctl_monitor.log], [0], [dnl
+NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=14 in_port=1 (via action) data_len=14 (unbuffered)
+vlan_tci=0x0000,dl_src=50:54:00:00:00:09,dl_dst=50:54:00:00:00:0a,dl_type=0x1234
+NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=14 in_port=1 (via action) data_len=14 (unbuffered)
+vlan_tci=0x0000,dl_src=50:54:00:00:00:09,dl_dst=50:54:00:00:00:0a,dl_type=0x1234
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
 AT_SETUP([ofproto-dpif - MPLS handling])
 OVS_VSWITCHD_START([dnl
    add-port br0 p1 -- set Interface p1 type=dummy