From 7784140f2bd2d5ae44f2be1507ac25f102006155 Mon Sep 17 00:00:00 2001 From: Dave Barach Date: Wed, 29 Apr 2020 17:04:10 -0400 Subject: misc: binary api fuzz test fixes Add a hook to src/vlibapi/api_shared.c to fuzz (screw up) binary API messages, e.g. by xoring random data into them before processing. We specifically exempt client connection messages, and inband debug CLI messages. We step over msg_id, client index, client context, and sw_if_index. Otherwise, "make test" vectors fail too rapidly to learn anything. The goal is to reduce the number of crashes caused to zero. We're fairly close with this patch. Add vl_msg_api_max_length(void *mp), which returns the maximum plausible length for a binary API message. Use it to hardern vl_api_from_api_to_new_vec(...) which takes an additional argument - message pointer - so it can verify that astr->length is sane. If it's not sane, return a u8 *vector of the form "insane astr->length nnnn\0". Verify array lengths in vl_api_dhcp6_send_client_message_t_handler(...) and vl_api_dhcp6_pd_send_client_message_t_handler(...). Add a fairly effective binary API fuzz hook to the unittest plugin, and modify the "make test" framework.py to pass "api-fuzz { on|off }" to enable API fuzzing: "make API_FUZZ=on TEST=xxx test-debug" or similar Type: improvement Signed-off-by: Dave Barach Change-Id: I0157267652a163c01553d5267620f719cc6c3bde --- src/vlibapi/api_shared.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) (limited to 'src/vlibapi/api_shared.c') diff --git a/src/vlibapi/api_shared.c b/src/vlibapi/api_shared.c index 28e9f481650..fbaa9c9e013 100644 --- a/src/vlibapi/api_shared.c +++ b/src/vlibapi/api_shared.c @@ -533,6 +533,8 @@ msg_handler_internal (api_main_t * am, } } +void (*vl_msg_api_fuzz_hook) (u16, void *); + /* This is only to be called from a vlib/vnet app */ void vl_msg_api_handler_with_vm_node (api_main_t * am, svm_region_t * vlib_rp, @@ -600,6 +602,10 @@ vl_msg_api_handler_with_vm_node (api_main_t * am, svm_region_t * vlib_rp, am->vlib_rp = vlib_rp; am->shmem_hdr = (void *) vlib_rp->user_ctx; } + + if (PREDICT_FALSE (vl_msg_api_fuzz_hook != 0)) + (*vl_msg_api_fuzz_hook) (id, the_msg); + (*handler) (the_msg, vm, node); if (is_private) { @@ -870,6 +876,21 @@ vl_msg_api_queue_handler (svm_queue_t * q) vl_msg_api_handler ((void *) msg); } +u32 +vl_msg_api_max_length (void *mp) +{ + msgbuf_t *mb; + u32 data_len = ~0; + + /* Work out the maximum sane message length, and return it */ + if (PREDICT_TRUE (mp != 0)) + { + mb = (msgbuf_t *) (((u8 *) mp) - offsetof (msgbuf_t, data)); + data_len = clib_net_to_host_u32 (mb->data_len); + } + return data_len; +} + vl_api_trace_t * vl_msg_api_trace_get (api_main_t * am, vl_api_trace_which_t which) { @@ -1132,9 +1153,13 @@ vl_api_format_string (u8 * s, va_list * args) * NOT nul terminated. */ u8 * -vl_api_from_api_to_new_vec (vl_api_string_t * astr) +vl_api_from_api_to_new_vec (void *mp, vl_api_string_t * astr) { u8 *v = 0; + + if (vl_msg_api_max_length (mp) < clib_net_to_host_u32 (astr->length)) + return format (0, "insane astr->length %u%c", + clib_net_to_host_u32 (astr->length), 0); vec_add (v, astr->buf, clib_net_to_host_u32 (astr->length)); return v; } -- cgit 1.2.3-korg