diff --git a/projects/openvpn/fuzz_randomizer.cpp b/projects/openvpn/fuzz_randomizer.cpp index deeb0ee98..367c55862 100644 --- a/projects/openvpn/fuzz_randomizer.cpp +++ b/projects/openvpn/fuzz_randomizer.cpp @@ -75,3 +75,33 @@ extern "C" size_t fuzz_get_random_data(void *buf, size_t len) { return ret_val; } + +// Simple garbage collector +#define GB_SIZE 100 +void *pointer_arr[GB_SIZE]; +static int pointer_idx = 0; + +// If the garbage collector is used then this must be called as first thing +// during a fuzz run. +extern "C" void gb_init() { + pointer_idx = 0; + + for (int i = 0; i < GB_SIZE; i++) { + pointer_arr[i] = NULL; + } +} + +extern "C" void gb_cleanup() { + for(int i = 0; i < GB_SIZE; i++) { + if (pointer_arr[i] != NULL) { + free(pointer_arr[i]); + } + } +} + +extern "C" char *gb_get_random_string() { + char *tmp = get_random_string(); + pointer_arr[pointer_idx++] = (void*)tmp; + return tmp; +} + diff --git a/projects/openvpn/fuzz_randomizer.h b/projects/openvpn/fuzz_randomizer.h index 1de4f7758..90d3e26d0 100644 --- a/projects/openvpn/fuzz_randomizer.h +++ b/projects/openvpn/fuzz_randomizer.h @@ -19,3 +19,7 @@ char *get_random_string(); int fuzz_randomizer_get_int(int min, int max); size_t fuzz_get_random_data(void *buf, size_t len); char *fuzz_random_get_string_max_length(int max_len); + +void gb_init(); +void gb_cleanup(); +char *gb_get_random_string(); diff --git a/projects/openvpn/fuzz_route.c b/projects/openvpn/fuzz_route.c index fe2a18008..2ca27a39a 100644 --- a/projects/openvpn/fuzz_route.c +++ b/projects/openvpn/fuzz_route.c @@ -20,16 +20,17 @@ limitations under the License. #include "fuzz_randomizer.h" - int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { fuzz_random_init(data, size); - struct route_option_list opt; + gb_init(); + + struct route_option_list *opt; struct route_list rl; - // Initialisation - memset(&opt, 0, sizeof(opt)); + int route_list_inited = 0; + int route_list_ipv6_inited = 0; struct context c; memset(&c, 0, sizeof(struct context)); @@ -40,60 +41,161 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { init_verb_mute(&c, IVM_LEVEL_1); init_options_dev(&c.options); - - //options_postprocess(&c.options); + + // options_postprocess(&c.options); pre_setup(&c.options); setenv_settings(c.es, &c.options); - ALLOC_OBJ_CLEAR_GC(c.options.connection_list, struct connection_list, &c.options.gc); + ALLOC_OBJ_CLEAR_GC(c.options.connection_list, struct connection_list, + &c.options.gc); context_init_1(&c); in_addr_t remote_host; ssize_t default_metric; - char *tmp0 = get_random_string(); - const char* remote_endpoint = tmp0; - // init - memset(&rl, 0, sizeof(struct route_list)); - init_route_list(&rl, &opt, remote_endpoint,default_metric, remote_host, c.es, &c); + struct route_ipv6_list rl6; + struct route_ipv6_option_list *opt6; - // call 1 - in_addr_t addr; - route_list_add_vpn_gateway(&rl, c.es, addr); + memset(&rl, 0, sizeof(rl)); + memset(&rl6, 0, sizeof(rl6)); + memset(&opt, 0, sizeof(opt)); + memset(&opt6, 0, sizeof(opt6)); - // call 2 - struct route_ipv4 r; - struct route_option ro; - char *tmp1 = get_random_string(); - char *tmp2 = get_random_string(); - char *tmp3 = get_random_string(); - char *tmp4 = get_random_string(); - ro.network = tmp1; - ro.netmask = tmp2; - ro.gateway = tmp3; - ro.metric = tmp4; - ro.next = NULL; + opt6 = new_route_ipv6_option_list(&c.gc); + opt = new_route_option_list(&c.gc); - memset(&r, 0, sizeof(struct route_ipv4)); - r.option = &ro; - r.flags = RT_DEFINED; - add_route(&r, NULL, 0, NULL, c.es, &c); - + int total_to_fuzz = fuzz_randomizer_get_int(1, 20); + for (int i = 0; i < total_to_fuzz; i++) { + int selector = fuzz_randomizer_get_int(0, 13); + switch (selector) { + case 0: + if (route_list_inited == 0) { + const char *remote_endpoint = gb_get_random_string(); + memset(&rl, 0, sizeof(struct route_list)); + rl.flags = fuzz_randomizer_get_int(0, 0xffffff); + init_route_list(&rl, opt, remote_endpoint, default_metric, remote_host, + c.es, &c); + route_list_inited = 1; + } + break; + case 1: + if (route_list_inited) { + in_addr_t addr; + route_list_add_vpn_gateway(&rl, c.es, addr); + } + break; + case 2: + if (route_list_inited && route_list_ipv6_inited) { + struct tuntap tt; + memset(&tt, 0, sizeof(tt)); + add_routes(&rl, &rl6, &tt, 0, c.es, &c); + } + break; + case 3: + if (route_list_inited) { + setenv_routes(c.es, &rl); + } + break; + case 4: + if (route_list_inited) { + struct route_ipv4 r; + struct route_option ro; + ro.network = gb_get_random_string(); + ro.netmask = gb_get_random_string(); + ro.gateway = gb_get_random_string(); + ro.metric = gb_get_random_string(); + ro.next = NULL; - gc_free(&rl.gc); + memset(&r, 0, sizeof(struct route_ipv4)); + r.option = &ro; + r.flags = RT_DEFINED; + add_route(&r, NULL, 0, NULL, c.es, &c); + } + break; + case 5: + if (route_list_inited) { + char *s1 = get_random_string(); + is_special_addr(s1); + free(s1); + } + break; + case 6: + if (route_list_ipv6_inited == 0) { + const char *remote_endpoint = gb_get_random_string(); + memset(&rl, 0, sizeof(struct route_list)); + struct in6_addr remote_host; + + rl6.rgi6.flags = fuzz_randomizer_get_int(0, 0xffffff); + fuzz_get_random_data(&rl6.rgi6.hwaddr, 6); + + char *t1 = gb_get_random_string(); + if (strlen(t1) > 16) { + memcpy(rl6.rgi6.iface, t1, 16); + } else { + memcpy(rl6.rgi6.iface, t1, strlen(t1)); + } + + init_route_ipv6_list(&rl6, opt6, remote_endpoint, 0, &remote_host, c.es, + &c); + route_list_ipv6_inited = 1; + } + break; + case 7: { + unsigned int flags; + struct route_ipv6 r6; + struct tuntap tt; + memset(&tt, 0, sizeof(tt)); + tt.actual_name = gb_get_random_string(); + r6.iface = gb_get_random_string(); + r6.flags = fuzz_randomizer_get_int(0, 0xfffff); + r6.netbits = fuzz_randomizer_get_int(0, 0xfffff); + r6.metric = fuzz_randomizer_get_int(0, 0xfffff); + + r6.next = NULL; + + add_route_ipv6(&r6, &tt, 0, c.es, &c); + } break; + case 8: + if (route_list_ipv6_inited && route_list_inited) { + delete_routes(&rl, &rl6, NULL, 0, c.es, &c); + route_list_ipv6_inited = 0; + route_list_inited = 0; + } + break; + case 9: + if (route_list_ipv6_inited) { + setenv_routes_ipv6(c.es, &rl6); + } + break; + case 10: { + add_route_ipv6_to_option_list(opt6, gb_get_random_string(), + gb_get_random_string(), + gb_get_random_string()); + } break; + case 11: { + print_route_options(opt, M_NONFATAL); + } break; + case 12: { + add_route_to_option_list(opt, gb_get_random_string(), + gb_get_random_string(), gb_get_random_string(), + gb_get_random_string()); + } break; + default: + break; + } + } + + if (route_list_inited) { + gc_free(&rl.gc); + } env_set_destroy(c.es); context_gc_free(&c); - free(tmp0); - free(tmp1); - free(tmp2); - free(tmp3); - free(tmp4); - fuzz_random_destroy(); + gb_cleanup(); + return 0; } -