From cefe6a9b3ec5ada6709b431a4bf06ef008b3a283 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Sun, 1 Mar 2015 15:26:46 +0200 Subject: [PATCH 1/4] tcp: fix option parsing Two bugs: 1. get_header(offset) was used with size given as the offset 2. opt_end failed to account for the mandatory tcp header, and thus was 20 bytes to large, resulting in overflow. --- net/tcp.hh | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/net/tcp.hh b/net/tcp.hh index 648846a0cc..188acb6d5b 100644 --- a/net/tcp.hh +++ b/net/tcp.hh @@ -915,8 +915,9 @@ void tcp::tcb::init_from_options(tcp_hdr* th, uint8_t* opt_start, ui template void tcp::tcb::input_handle_listen_state(tcp_hdr* th, packet p) { - auto opt_start = p.get_header(sizeof(tcp_hdr)); - auto opt_end = opt_start + th->data_offset * 4; + auto opt_len = th->data_offset * 4 - sizeof(tcp_hdr); + auto opt_start = reinterpret_cast(p.get_header(0, th->data_offset * 4)) + sizeof(tcp_hdr); + auto opt_end = opt_start + opt_len; p.trim_front(th->data_offset * 4); tcp_seq seg_seq = th->seq; @@ -943,8 +944,9 @@ void tcp::tcb::input_handle_listen_state(tcp_hdr* th, packet p) { template void tcp::tcb::input_handle_syn_sent_state(tcp_hdr* th, packet p) { - auto opt_start = p.get_header(sizeof(tcp_hdr)); - auto opt_end = opt_start + th->data_offset * 4; + auto opt_len = th->data_offset * 4 - sizeof(tcp_hdr); + auto opt_start = reinterpret_cast(p.get_header(0, th->data_offset * 4)) + sizeof(tcp_hdr); + auto opt_end = opt_start + opt_len; p.trim_front(th->data_offset * 4); tcp_seq seg_seq = th->seq; auto seg_ack = th->ack; From e1aa9f85a192b29d432ad4e1a9d878e987526d38 Mon Sep 17 00:00:00 2001 From: Gleb Natapov Date: Sun, 1 Mar 2015 14:25:22 +0200 Subject: [PATCH 2/4] fix xenstore compilation --- core/xen/xenstore.hh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/xen/xenstore.hh b/core/xen/xenstore.hh index fe60682dea..a496a80c59 100644 --- a/core/xen/xenstore.hh +++ b/core/xen/xenstore.hh @@ -22,6 +22,8 @@ #ifndef XENSTORE_HH_ #define XENSTORE_HH_ +#include + extern "C" { #include } From 590d8da4f11fefd4b33d8ceab23d726946aa261a Mon Sep 17 00:00:00 2001 From: Gleb Natapov Date: Sun, 1 Mar 2015 15:54:38 +0200 Subject: [PATCH 3/4] core: provide "void" promise specialization Makes it easier to write generic code. --- core/future.hh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/future.hh b/core/future.hh index 067b384c57..c716840234 100644 --- a/core/future.hh +++ b/core/future.hh @@ -341,6 +341,9 @@ private: friend class future; }; +template<> +class promise : public promise<> {}; + template struct is_future : std::false_type {}; template struct is_future> : std::true_type {}; From 27913013b10b9dcf28bec62996c9ae16bd5a697e Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Sun, 1 Mar 2015 16:40:29 +0200 Subject: [PATCH 4/4] virtio: tighten rx packets for debug mode Allocate exactly the available fragment size in order to catch buffer overflows. We get similar behaviour in dpdk, since without huge pages, it must copy the packet into a newly allocated buffer. --- net/virtio.cc | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/net/virtio.cc b/net/virtio.cc index 0c09543948..72185fddd9 100644 --- a/net/virtio.cc +++ b/net/virtio.cc @@ -554,6 +554,7 @@ protected: private: future<> prepare_buffers(); void complete_buffer(single_buffer&& b, size_t len); + void debug_mode_adjust_fragments(); }; protected: device* _dev; @@ -666,6 +667,22 @@ qp::rxq::prepare_buffers() { }); } +void +qp::rxq::debug_mode_adjust_fragments() { +#ifdef DEBUG + // For debug mode, reallocate last fragment to detect buffer overruns + auto last = _fragments.back(); + auto sz = last.size; + std::unique_ptr buf(reinterpret_cast(malloc(sz))); + if (!buf) { + throw std::bad_alloc(); + } + std::copy_n(last.base, sz, buf.get()); + _fragments.back() = { buf.get(), sz }; + _buffers.back() = std::move(buf); +#endif +} + void qp::rxq::complete_buffer(single_buffer&& bc, size_t len) { auto&& sb = bc[0]; @@ -690,6 +707,7 @@ qp::rxq::complete_buffer(single_buffer&& bc, size_t len) { // Last buffer if (_remaining_buffers == 0) { + debug_mode_adjust_fragments(); deleter del; if (_buffers.size() == 1) { del = make_free_deleter(_buffers[0].release());