diff options
author | Alex Wang <alexw@nicira.com> | 2014-10-10 14:41:10 -0700 |
---|---|---|
committer | Alex Wang <alexw@nicira.com> | 2014-10-10 16:07:32 -0700 |
commit | ff601a08a44c37fa8a6e0e569dc00d6731f55555 (patch) | |
tree | 1df8f7d007cdc5bc61fcc01e3d8701b968a20ba0 | |
parent | d9723d892b590d7bd57fe549216be2edd0dad5cb (diff) |
ofproto-dpif-upcall: Fix out-of-scope use of stack memory.
Commit cc377352d (ofproto: Reorganize in preparation for direct
dpdk upcalls.) introduced the bug that keeps reference to 'struct
flow' defined on the stack inside while loop when running out of
the scope. This causes strange bug like wrong mask extraction
when the part of memory is corrupted, and could lead to even
more serious bug/crash.
This commit fixes the above issue by defining an array of the
'struct flow's on the function stack.
Found by running ovs on RHEL7.
Signed-off-by: Alex Wang <alexw@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
-rw-r--r-- | ofproto/ofproto-dpif-upcall.c | 15 |
1 files changed, 8 insertions, 7 deletions
diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c index 882c067bc..1f9c484e5 100644 --- a/ofproto/ofproto-dpif-upcall.c +++ b/ofproto/ofproto-dpif-upcall.c @@ -577,6 +577,7 @@ recv_upcalls(struct handler *handler) struct ofpbuf recv_bufs[UPCALL_MAX_BATCH]; struct dpif_upcall dupcalls[UPCALL_MAX_BATCH]; struct upcall upcalls[UPCALL_MAX_BATCH]; + struct flow flows[UPCALL_MAX_BATCH]; size_t n_upcalls, i; n_upcalls = 0; @@ -584,8 +585,8 @@ recv_upcalls(struct handler *handler) struct ofpbuf *recv_buf = &recv_bufs[n_upcalls]; struct dpif_upcall *dupcall = &dupcalls[n_upcalls]; struct upcall *upcall = &upcalls[n_upcalls]; + struct flow *flow = &flows[n_upcalls]; struct pkt_metadata md; - struct flow flow; int error; ofpbuf_use_stub(recv_buf, recv_stubs[n_upcalls], @@ -595,13 +596,13 @@ recv_upcalls(struct handler *handler) break; } - if (odp_flow_key_to_flow(dupcall->key, dupcall->key_len, &flow) + if (odp_flow_key_to_flow(dupcall->key, dupcall->key_len, flow) == ODP_FIT_ERROR) { goto free_dupcall; } error = upcall_receive(upcall, udpif->backer, &dupcall->packet, - dupcall->type, dupcall->userdata, &flow); + dupcall->type, dupcall->userdata, flow); if (error) { if (error == ENODEV) { /* Received packet on datapath port for which we couldn't @@ -611,7 +612,7 @@ recv_upcalls(struct handler *handler) dpif_flow_put(udpif->dpif, DPIF_FP_CREATE, dupcall->key, dupcall->key_len, NULL, 0, NULL, 0, NULL); VLOG_INFO_RL(&rl, "received packet on unassociated datapath " - "port %"PRIu32, flow.in_port.odp_port); + "port %"PRIu32, flow->in_port.odp_port); } goto free_dupcall; } @@ -621,12 +622,12 @@ recv_upcalls(struct handler *handler) upcall->out_tun_key = dupcall->out_tun_key; - if (vsp_adjust_flow(upcall->ofproto, &flow, &dupcall->packet)) { + if (vsp_adjust_flow(upcall->ofproto, flow, &dupcall->packet)) { upcall->vsp_adjusted = true; } - md = pkt_metadata_from_flow(&flow); - flow_extract(&dupcall->packet, &md, &flow); + md = pkt_metadata_from_flow(flow); + flow_extract(&dupcall->packet, &md, flow); error = process_upcall(udpif, upcall, NULL); if (error) { |