[ovs-dev] [ovs-security] RFC: Adding OvS to fuzzer test suite
Bhargava Shastry
bshastry at sec.t-labs.tu-berlin.de
Fri Sep 1 15:31:33 UTC 2017
Dear all,
I suppose the following are the agenda points for adding OvS to OSS-Fuzz.
1. [Easy] Write Docker file for getting OvS to build. Feel this should
be easy as I don't see any non-default dependencies
2. [Easy] Add a project.yaml that documents project metadata such as
contact persons, project homepage etc.
3. [Medium] Add a build script to get OSS tests to compile.
4. [Medium] Add relevant OSS tests to OvS trunk/branch. These tests
should ideally cover 100% of the codebase but we most likely start with
a handful I guess. The tests that uncovered CVEs in OvS over previous
months is a good starting point?
dev at OvS is best equipped to handle (1) and (2). As for (3) and (4), you
could use my commit here [1] as a starting point. Like I said, I am
happy to help write more tests with oversight from dev at OvS/KCC. Let me
know how this plan sounds. BTW, here is a reference OSS-Fuzz template
from Wireshark [2] that you could use I guess.
[1]:
https://github.com/bshastry/fuzzer-test-suite/tree/master/openvswitch-2.7.2
[2]: https://github.com/google/oss-fuzz/tree/master/projects/wireshark
Regards,
Bhargava
On 09/01/2017 03:16 PM, Bhargava Shastry wrote:
> Here's another test harness for connection tracking code. This is over
> 30x slower than the other two test cases (speed=2700 exec/s vs 85000
> exec/s for the other two test cases). Just to clarify, I am not testing
> on trunk (as I incorrectly claimed earlier). Rather, I am testing the
> latest release v2.7.2.
>
> ====== target-ct.c =====
>
> #include "flow.h"
> #include "dp-packet.h"
> #include "conntrack.h"
>
> int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
> {
> struct conntrack ct;
> conntrack_init(&ct);
> struct dp_packet_batch pkt_batch;
> struct flow flow;
> struct dp_packet pkt;
> dp_packet_use_const(&pkt, data, size);
>
> packet_batch_init_packet(&pkt_batch, &pkt);
> flow_extract(pkt_batch.packets[0], &flow);
>
> conntrack_execute(&ct, &pkt_batch, flow.dl_type, true, 0, NULL,
> NULL, NULL);
>
> conntrack_destroy(&ct);
> return 0;
> }
>
> ====== target-ct.c =====
>
> On 09/01/2017 02:04 PM, Bhargava Shastry wrote:
>> Here is another test harness for fuzzing Openflow packet parsing on
>> trunk. Feedback welcome!
>>
>> ===== target-ofp.c =====
>>
>> #include "flow.h"
>> #include "dp-packet.h"
>> #include "pcap-file.h"
>> #include "odp-util.h"
>>
>> static bool
>> is_openflow_port(ovs_be16 port_)
>> {
>> uint16_t port = ntohs(port_);
>> return port == OFP_PORT || port == OFP_OLD_PORT;
>> }
>>
>> int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
>> {
>> struct dp_packet packet;
>> struct flow flow;
>> struct tcp_reader *reader;
>> dp_packet_use_const(&packet, data, size);
>>
>> pkt_metadata_init(&packet.md, ODPP_NONE);
>> flow_extract(&packet, &flow);
>> if (flow.dl_type == htons(ETH_TYPE_IP)
>> && flow.nw_proto == IPPROTO_TCP
>> && (is_openflow_port(flow.tp_src) ||
>> is_openflow_port(flow.tp_dst))) {
>> struct dp_packet *payload = tcp_reader_run(reader, &flow,
>> &packet);
>> if (payload) {
>> while (dp_packet_size(payload) >= sizeof(struct
>> ofp_header)) {
>> const struct ofp_header *oh;
>> void *pdata = dp_packet_data(payload);
>> int length;
>>
>> /* Align OpenFlow on 8-byte boundary for safe access. */
>> dp_packet_shift(payload, -((intptr_t) pdata & 7));
>>
>> oh = dp_packet_data(payload);
>> length = ntohs(oh->length);
>> if (dp_packet_size(payload) < length) {
>> break;
>> }
>>
>> ofp_print(stdout, dp_packet_data(payload), length, 4);
>> dp_packet_pull(payload, length);
>> }
>> }
>> tcp_reader_close(reader);
>> }
>> return 0;
>> }
>>
>> ===== target-ofp.c =====
>>
>> P.S. Fuzzing for ~10h didn't result in anything. Test coverage saturates
>> early but that's possibly because this isn't doing any deep processing.
>>
>> Regards,
>> Bhargava
>>
>> On 08/31/2017 11:18 PM, Kostya Serebryany wrote:
>>> For the version Bhargava is testing I guess this reads as
>>> int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
>>> {
>>> struct ofpbuf packet;
>>> ofpbuf_use_const(&packet, data, size);
>>>
>>> struct flow flow;
>>>
>>> flow_extract(&packet, NULL, &flow);
>>>
>>> return 0;
>>> }
>>>
>>> Looks great, and runs fast.
>>>
>>>
>>> On Thu, Aug 31, 2017 at 2:05 PM, Bhargava Shastry
>>> <bshastry at sec.t-labs.tu-berlin.de
>>> <mailto:bshastry at sec.t-labs.tu-berlin.de>> wrote:
>>>
>>> Hi,
>>>
>>> > I didn't look at the actual code before, but now that I have, I don't
>>> > understand at all why it was doing file I/O just to write a packet to
>>> > disk and then read it back.
>>>
>>> Sorry, this was due to my ignorance. I was not aware of something like
>>> dp_packet_use_const(). This should speed things up. I am working on it.
>>>
>>> >
>>> > Here is a more natural way to do this:
>>> >
>>> > int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
>>> > {
>>> > struct dp_packet packet;
>>> > dp_packet_use_const(&packet, data, size);
>>> >
>>> > struct flow flow;
>>> > flow_extract(&packet, &flow);
>>> >
>>> > return 0;
>>> > }
>>> >
>>>
>>> --
>>> Bhargava Shastry <bshastry at sec.t-labs.tu-berlin.de
>>> <mailto:bshastry at sec.t-labs.tu-berlin.de>>
>>> Security in Telecommunications
>>> TU Berlin / Telekom Innovation Laboratories
>>> Ernst-Reuter-Platz 7, Sekr TEL 17 / D - 10587 Berlin, Germany
>>> phone: +49 30 8353 58235 <tel:%2B49%2030%208353%2058235>
>>> Keybase: https://keybase.io/bshastry
>>>
>>>
>>
>
--
Bhargava Shastry <bshastry at sec.t-labs.tu-berlin.de>
Security in Telecommunications
TU Berlin / Telekom Innovation Laboratories
Ernst-Reuter-Platz 7, Sekr TEL 17 / D - 10587 Berlin, Germany
phone: +49 30 8353 58235
Keybase: https://keybase.io/bshastry
More information about the dev
mailing list