ofproto: Reject invalid input ports in OFPT_PACKET_OUT requests.
authorBen Pfaff <blp@nicira.com>
Thu, 8 Sep 2011 18:25:29 +0000 (11:25 -0700)
committerBen Pfaff <blp@nicira.com>
Wed, 2 Nov 2011 15:47:28 +0000 (08:47 -0700)
Some invalid ports (those above the maximum port number supported by the
datapath, including OpenFlow reserved ports that are not translated by OVS
into some other number) will be rejected by the datapath.  It's better to
catch these early and send back an appropriate OpenFlow error code, rather
than to just get EINVAL from the kernel and have to guess at the problem.

Reported-by: Aaron Rosen <arosen@clemson.edu>
include/openflow/nicira-ext.h
ofproto/ofproto-dpif.c
ofproto/ofproto.c

index 84060d7912d8b4080482f5db850f8882b2113bb4..875052a93dcc6495bb118e246ba56b3c9db75845 100644 (file)
@@ -110,6 +110,9 @@ enum nx_bad_request_code {
 
     /* NXT_ROLE_REQUEST specified an invalid role. */
     NXBRC_BAD_ROLE = 0x201,
+
+    /* The in_port in an ofp_packet_out request is invalid. */
+    NXBRC_BAD_IN_PORT = 0x202
 };
 
 /* Additional "code" values for OFPET_FLOW_MOD_FAILED. */
index 6c303bba341f7a6deeaac5e5297ba4303bbadb53..93e79a978d07ad6d8afbb5e8e381a380e2360939 100644 (file)
@@ -5077,6 +5077,10 @@ packet_out(struct ofproto *ofproto_, struct ofpbuf *packet,
     struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
     int error;
 
+    if (flow->in_port >= ofproto->max_ports && flow->in_port < OFPP_MAX) {
+        return ofp_mkerr_nicira(OFPET_BAD_REQUEST, NXBRC_BAD_IN_PORT);
+    }
+
     error = validate_actions(ofp_actions, n_ofp_actions, flow,
                              ofproto->max_ports);
     if (!error) {
index 8a2abdc6925d2052622b3f73955a1f4eee6f3d14..b7b31b0228bffd0757d382609df7638a8097b8ee 100644 (file)
@@ -1729,6 +1729,7 @@ handle_packet_out(struct ofconn *ofconn, const struct ofp_header *oh)
     struct ofpbuf request;
     struct flow flow;
     size_t n_ofp_actions;
+    uint16_t in_port;
     int error;
 
     COVERAGE_INC(ofproto_packet_out);
@@ -1762,8 +1763,18 @@ handle_packet_out(struct ofconn *ofconn, const struct ofp_header *oh)
         buffer = NULL;
     }
 
+    /* Get in_port and partially validate it.
+     *
+     * We don't know what range of ports the ofproto actually implements, but
+     * we do know that only certain reserved ports (numbered OFPP_MAX and
+     * above) are valid. */
+    in_port = ntohs(opo->in_port);
+    if (in_port >= OFPP_MAX && in_port != OFPP_LOCAL && in_port != OFPP_NONE) {
+        return ofp_mkerr_nicira(OFPET_BAD_REQUEST, NXBRC_BAD_IN_PORT);
+    }
+
     /* Send out packet. */
-    flow_extract(&payload, 0, 0, ntohs(opo->in_port), &flow);
+    flow_extract(&payload, 0, 0, in_port, &flow);
     error = p->ofproto_class->packet_out(p, &payload, &flow,
                                          ofp_actions, n_ofp_actions);
     ofpbuf_delete(buffer);