[ovs-dev] [PATCH] ossfuzz: Add new target for ODP parsing

Ben Pfaff blp at ovn.org
Thu Oct 11 22:11:54 UTC 2018


On Thu, Oct 04, 2018 at 11:55:30AM +0200, Bhargava Shastry wrote:
> Hi,
> 
> Sorry that I was vague about this. The bug manifests as follows:
> 
> There is a function in test-odp.c called "parse_filter" that looks like so:
> 
> ```
> 1. static int
> 2. parse_filter(char *filter_parse)
> 3. {
> 4.     struct ds in;
> 5.     struct flow flow_filter;
> 6.     struct flow_wildcards wc_filter;
> 7.     char *error, *filter = NULL;
> 
> 8.     vlog_set_levels_from_string_assert("odp_util:console:dbg");
> 9.     if (filter_parse && !strncmp(filter_parse, "filter=", 7)) {
> 10.       filter = xstrdup(filter_parse + 7);
> 11.       memset(&flow_filter, 0, sizeof(flow_filter));
> 12.       memset(&wc_filter, 0, sizeof(wc_filter));
> 13.       error = parse_ofp_exact_flow(&flow_filter, &wc_filter, NULL,
> 14.                                    filter, NULL);
> 15.       if (error) {
> 16.           ovs_fatal(0, "Failed to parse filter (%s)", error);
> 17.       }
> 18.       else {
> 19.           ovs_fatal(0, "No filter to parse.");
> 20.       }
> ```
> 
> My understanding of this function is as follows:
>   - it takes a filter string and an ODP flow as string as inputs (ODP
> string is fetched via stdin and hence not seen in the code above)
>   - before dealing with the ODP string it invokes the
> `parse_ofp_exact_flow` function passing the filter string as input
>   - if there is an error in `parse_ofp_exact_flow`, the `parse_filter`
> function aborts with a "Failed to parse filter" error printed to stdout.
> 
> Now, I experimented with several filter strings such as the following
> (copied from odp.at)
> 
> const char *filters[num_filters] = {
>     "filter=\'dl_type=0x1235\'",
>     "filter=\'dl_vlan=99\'",
>     "filter=\'dl_vlan=99,ip\'",
>     "filter=\'ip,nw_src=35.8.2.199\'",
>     "filter=\'ip,nw_dst=172.16.0.199\'",
>     "filter=\'dl_type=0x0800,nw_src=35.8.2.199,nw_dst=172.16.0.199\'",
>     "filter=\'icmp,nw_src=35.8.2.199\'",
>     "filter=\'arp,arp_spa=1.2.3.5\'",
>     "filter=\'tcp,tp_src=90\'",
>     "filter=\'tcp6,tp_src=90\'"
> };
> 
> For example, when we feed the filter string "filter=\'dl_vlan=99,ip\'"
> to the function `parse_ofp_exact_flow` we get the following error:
> 
> ```
> unknown field `dl_van`
> ```
> 
> and aborts the test.
> 
> I don't know how `parse_ofp_exact_flow` is implemented so I don't know
> what I am doing wrong. Any suggestions?
> 
> ==== Test integration ====
> 
> My original idea was to integrate parse_filter as follows:
> 
> - Take one random filter string from the const char array above
> - Feed this to a modified parse_filter function declaration like so
> 
> parse_filter(const char *filter, const char *input)
> 
> where
> - filter is a randomly chosen filter string from the list above (see
> filters[])
> - input is the fuzzed input
> 
> A simple way to make selection random is to use the modulo operator like so
> ```
> int
> LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
> {
> ...
>     /* Parse filter. */
>     int idx = size % 10;
>     parse_filter(filters[idx], input);
> ```
> 
> Does this make sense?

I see what you're saying.

If it's valuable, we can work around these problems.

Do you expect to see much improvement in coverage from fuzzing this?
Does it use OVS functions that don't get called from the other tests?

Thanks,

Ben.


More information about the dev mailing list