Currently, if '--len' option passed to 'netdev-dummy/receive' command,
only 'size' field of dp_packet will changes.

This is incorrect behaviour, because memory for that size is not
allocated and also packet headers not fixed to reflect the new size.
This leads to flow_extract() failure, because it checks the
'ip->tot_len' and stops further parsing if it doesn't match the
dp_packet_size(). As a result packets created while processing of the
'receive' command can't be parsed to the same flow.
Additionally this may lead to wrong memory accesses in case someone
will try to read or modify packets data.

Fix that by creating right packets using recently introduced
'flow_compose_size()'.

CC: Andy Zhou <az...@ovn.org>
Fixes: d8ada2368cbe ("netdev-dummy: Add --len option for netdev-dummy/receive 
command")
Signed-off-by: Ilya Maximets <i.maxim...@samsung.com>
---
 lib/netdev-dummy.c | 25 ++++++++++++++++---------
 1 file changed, 16 insertions(+), 9 deletions(-)

diff --git a/lib/netdev-dummy.c b/lib/netdev-dummy.c
index 51d29d5..83e30b3 100644
--- a/lib/netdev-dummy.c
+++ b/lib/netdev-dummy.c
@@ -1449,7 +1449,7 @@ eth_from_packet(const char *s)
 }
 
 static struct dp_packet *
-eth_from_flow(const char *s)
+eth_from_flow(const char *s, size_t packet_size)
 {
     enum odp_key_fitness fitness;
     struct dp_packet *packet;
@@ -1479,6 +1479,7 @@ eth_from_flow(const char *s)
 
     packet = dp_packet_new(0);
     flow_compose(packet, &flow);
+    flow_compose_size(packet, &flow, packet_size);
 
     ofpbuf_uninit(&odp_key);
     return packet;
@@ -1556,20 +1557,26 @@ netdev_dummy_receive(struct unixctl_conn *conn,
         packet = eth_from_packet(argv[i]);
 
         if (!packet) {
+            int packet_size = 0;
+            const char *flow_str = argv[i];
+
+            /* Parse optional --len argument immediately follows a 'flow'.  */
+            if (argc >= i + 2 && !strcmp(argv[i + 1], "--len")) {
+                packet_size = strtol(argv[i + 2], NULL, 10);
+
+                if (packet_size < ETH_TOTAL_MIN) {
+                    unixctl_command_reply_error(conn, "too small packet len");
+                    goto exit;
+                }
+                i+=2;
+            }
             /* Try parse 'argv[i]' as odp flow. */
-            packet = eth_from_flow(argv[i]);
+            packet = eth_from_flow(flow_str, packet_size);
 
             if (!packet) {
                 unixctl_command_reply_error(conn, "bad packet or flow syntax");
                 goto exit;
             }
-
-            /* Parse optional --len argument immediately follows a 'flow'.  */
-            if (argc >= i + 2 && !strcmp(argv[i + 1], "--len")) {
-                int packet_size = strtol(argv[i + 2], NULL, 10);
-                dp_packet_set_size(packet, packet_size);
-                i+=2;
-            }
         }
 
         netdev_dummy_queue_packet(dummy_dev, packet, rx_qid);
-- 
2.7.4

_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to