summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesse Gross <jesse@nicira.com>2015-09-11 09:01:05 -0700
committerJesse Gross <jesse@nicira.com>2015-09-13 08:13:11 -0700
commitf41256d709d1733262b7538613237b34e801f457 (patch)
treefb6100bbd18d8995d749cf8585b1204aa1631846
parent9d4aeccaf69861616cb0715d10e3f1f3e2a14e51 (diff)
downloadopenvswitch-f41256d709d1733262b7538613237b34e801f457.tar.gz
tunnel: Validate IP header for userspace tunneling.
Currently, when doing userspace tunneling we don't perform much in the way of integrity checks on the incoming IP header. The case of tunneling is different from the usual case of switching since we are acting as the endpoint here and should not allow invalid packets to pass. This adds checks for IP checksum, version, total length, and options and drops packets that don't pass. Signed-off-by: Jesse Gross <jesse@nicira.com> Acked-by: Pravin B Shelar <pshelar@nicira.com>
-rw-r--r--lib/netdev-vport.c27
-rw-r--r--tests/tunnel-push-pop.at6
2 files changed, 30 insertions, 3 deletions
diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c
index eceaa813e..ff505637e 100644
--- a/lib/netdev-vport.c
+++ b/lib/netdev-vport.c
@@ -844,6 +844,7 @@ ip_extract_tnl_md(struct dp_packet *packet, struct flow_tnl *tnl)
{
struct ip_header *nh;
void *l4;
+ int l3_size;
nh = dp_packet_l3(packet);
l4 = dp_packet_l4(packet);
@@ -852,6 +853,32 @@ ip_extract_tnl_md(struct dp_packet *packet, struct flow_tnl *tnl)
return NULL;
}
+ if (csum(nh, IP_IHL(nh->ip_ihl_ver) * 4)) {
+ VLOG_WARN_RL(&err_rl, "ip packet has invalid checksum");
+ return NULL;
+ }
+
+ if (IP_VER(nh->ip_ihl_ver) != 4) {
+ VLOG_WARN_RL(&err_rl, "ipv4 packet has invalid version (%d)",
+ IP_VER(nh->ip_ihl_ver));
+ return NULL;
+ }
+
+ l3_size = dp_packet_size(packet) -
+ ((char *)nh - (char *)dp_packet_data(packet));
+
+ if (ntohs(nh->ip_tot_len) > l3_size) {
+ VLOG_WARN_RL(&err_rl, "ip packet is truncated (IP length %d, actual %d)",
+ ntohs(nh->ip_tot_len), l3_size);
+ return NULL;
+ }
+
+ if (IP_IHL(nh->ip_ihl_ver) * 4 > sizeof(struct ip_header)) {
+ VLOG_WARN_RL(&err_rl, "ip options not supported on tunnel packets "
+ "(%d bytes)", IP_IHL(nh->ip_ihl_ver) * 4);
+ return NULL;
+ }
+
tnl->ip_src = get_16aligned_be32(&nh->ip_src);
tnl->ip_dst = get_16aligned_be32(&nh->ip_dst);
tnl->ip_tos = nh->ip_tos;
diff --git a/tests/tunnel-push-pop.at b/tests/tunnel-push-pop.at
index 502e41fe1..98f22ea2b 100644
--- a/tests/tunnel-push-pop.at
+++ b/tests/tunnel-push-pop.at
@@ -109,7 +109,7 @@ AT_CHECK([tail -1 stdout], [0],
])
dnl Check decapsulation of GRE packet
-AT_CHECK([ovs-appctl netdev-dummy/receive p0 'aa55aa550000001b213cab6408004500007e79464000402f99080101025c0101025820006558000001c8fe71d883724fbeb6f4e1494a080045000054ba200000400184861e0000011e00000200004227e75400030af3195500000000f265010000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637'])
+AT_CHECK([ovs-appctl netdev-dummy/receive p0 'aa55aa550000001b213cab6408004500007e79464000402fba550101025c0101025820006558000001c8fe71d883724fbeb6f4e1494a080045000054ba200000400184861e0000011e00000200004227e75400030af3195500000000f265010000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637'])
ovs-appctl time/warp 1000
AT_CHECK([ovs-ofctl dump-ports int-br | grep 'port 3'], [0], [dnl
@@ -117,7 +117,7 @@ AT_CHECK([ovs-ofctl dump-ports int-br | grep 'port 3'], [0], [dnl
])
dnl Check GRE only accepts encapsulated Ethernet frames
-AT_CHECK([ovs-appctl netdev-dummy/receive p0 'aa55aa550000001b213cab6408004500007e79464000402f99080101025c0101025820000800000001c8fe71d883724fbeb6f4e1494a080045000054ba200000400184861e0000011e00000200004227e75400030af3195500000000f265010000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637'])
+AT_CHECK([ovs-appctl netdev-dummy/receive p0 'aa55aa550000001b213cab6408004500007e79464000402fba550101025c0101025820000800000001c8fe71d883724fbeb6f4e1494a080045000054ba200000400184861e0000011e00000200004227e75400030af3195500000000f265010000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637'])
ovs-appctl time/warp 1000
AT_CHECK([ovs-ofctl dump-ports int-br | grep 'port 3'], [0], [dnl
@@ -130,7 +130,7 @@ AT_CHECK([ovs-ofctl monitor int-br 65534 --detach --no-chdir --pidfile 2> ofctl_
AT_CHECK([ovs-ofctl del-flows int-br])
AT_CHECK([ovs-ofctl add-flow int-br "tun_metadata0=0xa/0xf,actions=5,controller"])
-AT_CHECK([ovs-appctl netdev-dummy/receive p0 'aa55aa550000001b213cab64080045000096794640004011ba630101025c01010258308817c1008200000400655800007b00ffff80010000000affff00010000000bfe71d883724fbeb6f4e1494a080045000054ba200000400184861e0000011e00000200004227e75400030af3195500000000f265010000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637'])
+AT_CHECK([ovs-appctl netdev-dummy/receive p0 'aa55aa550000001b213cab64080045000096794640004011ba5b0101025c01010258308817c1008200000400655800007b00ffff80010000000affff00010000000bfe71d883724fbeb6f4e1494a080045000054ba200000400184861e0000011e00000200004227e75400030af3195500000000f265010000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637'])
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 2])
OVS_APP_EXIT_AND_WAIT(ovs-ofctl)