X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvlibapi%2Fapi_shared.c;h=17560e5de23a7e85ce03202b59258eecacf7b8b0;hb=2ca88ff97884ec9ed20a853b13cee6d86f9c9d0f;hp=52e66f41342f50db16a0bb29cfa97dbe38d2f7ff;hpb=36217e3ca8a1ca2e7a341b6b44ffc25e6497191c;p=vpp.git diff --git a/src/vlibapi/api_shared.c b/src/vlibapi/api_shared.c index 52e66f41342..17560e5de23 100644 --- a/src/vlibapi/api_shared.c +++ b/src/vlibapi/api_shared.c @@ -33,12 +33,11 @@ #include /* *INDENT-OFF* */ -api_main_t api_global_main = - { - .region_name = "/unset", - .api_uid = -1, - .api_gid = -1, - }; +static api_main_t api_global_main = { + .region_name = "/unset", + .api_uid = -1, + .api_gid = -1, +}; /* *INDENT-ON* */ /* Please use vlibapi_get_main() to access my_api_main */ @@ -500,8 +499,8 @@ vl_msg_api_barrier_release (void) } always_inline void -msg_handler_internal (api_main_t * am, - void *the_msg, int trace_it, int do_it, int free_it) +msg_handler_internal (api_main_t *am, void *the_msg, uword msg_len, + int trace_it, int do_it, int free_it) { u16 id = clib_net_to_host_u16 (*((u16 *) the_msg)); u8 *(*print_fp) (void *, void *); @@ -545,8 +544,34 @@ msg_handler_internal (api_main_t * am, } } - if (do_it) + uword calc_size = 0; + uword (*calc_size_fp) (void *); + calc_size_fp = am->msg_calc_size_funcs[id]; + ASSERT (NULL != calc_size_fp); + if (calc_size_fp) { + calc_size = (*calc_size_fp) (the_msg); + if (calc_size > msg_len) + { + clib_warning ( + "Truncated message '%s' (id %u) received, calculated size " + "%lu is bigger than actual size %llu, message dropped.", + am->msg_names[id], id, calc_size, msg_len); + } + } + else + { + clib_warning ("Message '%s' (id %u) has NULL calc_size_func, cannot " + "verify message size is correct", + am->msg_names[id], id); + } + + /* don't process message if it's truncated, otherwise byte swaps + * and stuff could corrupt memory even beyond message if it's malicious + * e.g. VLA length field set to 1M elements, but VLA empty */ + if (do_it && calc_size <= msg_len) + { + if (!am->is_mp_safe[id]) { vl_msg_api_barrier_trace_context (am->msg_names[id]); @@ -569,6 +594,7 @@ msg_handler_internal (api_main_t * am, if (PREDICT_FALSE (vec_len (am->perf_counter_cbs) != 0)) clib_call_callbacks (am->perf_counter_cbs, am, id, 1 /* after */ ); + if (!am->is_mp_safe[id]) vl_msg_api_barrier_release (); } @@ -616,183 +642,31 @@ 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, - void *the_msg, vlib_main_t * vm, - vlib_node_runtime_t * node, u8 is_private) -{ - u16 id = clib_net_to_host_u16 (*((u16 *) the_msg)); - u8 *(*handler) (void *, void *, void *); - u8 *(*print_fp) (void *, void *); - svm_region_t *old_vlib_rp; - void *save_shmem_hdr; - int is_mp_safe = 1; - - if (PREDICT_FALSE (am->elog_trace_api_messages)) - { - /* *INDENT-OFF* */ - ELOG_TYPE_DECLARE (e) = - { - .format = "api-msg: %s", - .format_args = "T4", - }; - /* *INDENT-ON* */ - struct - { - u32 c; - } *ed; - ed = ELOG_DATA (am->elog_main, e); - if (id < vec_len (am->msg_names) && am->msg_names[id]) - ed->c = elog_string (am->elog_main, (char *) am->msg_names[id]); - else - ed->c = elog_string (am->elog_main, "BOGUS"); - } - - if (id < vec_len (am->msg_handlers) && am->msg_handlers[id]) - { - handler = (void *) am->msg_handlers[id]; - - if (PREDICT_FALSE (am->rx_trace && am->rx_trace->enabled)) - vl_msg_api_trace (am, am->rx_trace, the_msg); - - if (PREDICT_FALSE (am->msg_print_flag)) - { - fformat (stdout, "[%d]: %s\n", id, am->msg_names[id]); - print_fp = (void *) am->msg_print_handlers[id]; - if (print_fp == 0) - { - fformat (stdout, " [no registered print fn for msg %d]\n", id); - } - else - { - (*print_fp) (the_msg, vm); - } - } - is_mp_safe = am->is_mp_safe[id]; - - if (!is_mp_safe) - { - vl_msg_api_barrier_trace_context (am->msg_names[id]); - vl_msg_api_barrier_sync (); - } - if (is_private) - { - old_vlib_rp = am->vlib_rp; - save_shmem_hdr = am->shmem_hdr; - 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); - - if (am->is_autoendian[id]) - { - void (*endian_fp) (void *); - endian_fp = am->msg_endian_handlers[id]; - (*endian_fp) (the_msg); - } - if (PREDICT_FALSE (vec_len (am->perf_counter_cbs) != 0)) - clib_call_callbacks (am->perf_counter_cbs, am, id, 0 /* before */ ); - - (*handler) (the_msg, vm, node); - - if (PREDICT_FALSE (vec_len (am->perf_counter_cbs) != 0)) - clib_call_callbacks (am->perf_counter_cbs, am, id, 1 /* after */ ); - if (is_private) - { - am->vlib_rp = old_vlib_rp; - am->shmem_hdr = save_shmem_hdr; - } - if (!is_mp_safe) - vl_msg_api_barrier_release (); - } - else - { - clib_warning ("no handler for msg id %d", id); - } - - /* - * Special-case, so we can e.g. bounce messages off the vnet - * main thread without copying them... - */ - if (id >= vec_len (am->message_bounce) || !(am->message_bounce[id])) - { - if (is_private) - { - old_vlib_rp = am->vlib_rp; - save_shmem_hdr = am->shmem_hdr; - am->vlib_rp = vlib_rp; - am->shmem_hdr = (void *) vlib_rp->user_ctx; - } - vl_msg_api_free (the_msg); - if (is_private) - { - am->vlib_rp = old_vlib_rp; - am->shmem_hdr = save_shmem_hdr; - } - } - - if (PREDICT_FALSE (am->elog_trace_api_messages)) - { - /* *INDENT-OFF* */ - ELOG_TYPE_DECLARE (e) = - { - .format = "api-msg-done(%s): %s", - .format_args = "t4T4", - .n_enum_strings = 2, - .enum_strings = - { - "barrier", - "mp-safe", - } - }; - /* *INDENT-ON* */ - - struct - { - u32 barrier; - u32 c; - } *ed; - ed = ELOG_DATA (am->elog_main, e); - if (id < vec_len (am->msg_names) && am->msg_names[id]) - ed->c = elog_string (am->elog_main, (char *) am->msg_names[id]); - else - ed->c = elog_string (am->elog_main, "BOGUS"); - ed->barrier = is_mp_safe; - } -} - -void -vl_msg_api_handler (void *the_msg) +vl_msg_api_handler (void *the_msg, uword msg_len) { api_main_t *am = vlibapi_get_main (); - msg_handler_internal (am, the_msg, - (am->rx_trace - && am->rx_trace->enabled) /* trace_it */ , - 1 /* do_it */ , 1 /* free_it */ ); + msg_handler_internal (am, the_msg, msg_len, + (am->rx_trace && am->rx_trace->enabled) /* trace_it */, + 1 /* do_it */, 1 /* free_it */); } void -vl_msg_api_handler_no_free (void *the_msg) +vl_msg_api_handler_no_free (void *the_msg, uword msg_len) { api_main_t *am = vlibapi_get_main (); - msg_handler_internal (am, the_msg, - (am->rx_trace - && am->rx_trace->enabled) /* trace_it */ , - 1 /* do_it */ , 0 /* free_it */ ); + msg_handler_internal (am, the_msg, msg_len, + (am->rx_trace && am->rx_trace->enabled) /* trace_it */, + 1 /* do_it */, 0 /* free_it */); } void -vl_msg_api_handler_no_trace_no_free (void *the_msg) +vl_msg_api_handler_no_trace_no_free (void *the_msg, uword msg_len) { api_main_t *am = vlibapi_get_main (); - msg_handler_internal (am, the_msg, 0 /* trace_it */ , 1 /* do_it */ , - 0 /* free_it */ ); + msg_handler_internal (am, the_msg, msg_len, 0 /* trace_it */, 1 /* do_it */, + 0 /* free_it */); } /* @@ -805,14 +679,13 @@ vl_msg_api_handler_no_trace_no_free (void *the_msg) * */ void -vl_msg_api_trace_only (void *the_msg) +vl_msg_api_trace_only (void *the_msg, uword msg_len) { api_main_t *am = vlibapi_get_main (); - msg_handler_internal (am, the_msg, - (am->rx_trace - && am->rx_trace->enabled) /* trace_it */ , - 0 /* do_it */ , 0 /* free_it */ ); + msg_handler_internal (am, the_msg, msg_len, + (am->rx_trace && am->rx_trace->enabled) /* trace_it */, + 0 /* do_it */, 0 /* free_it */); } void @@ -863,14 +736,13 @@ vl_msg_api_get_msg_length (void *msg_arg) * vl_msg_api_socket_handler */ void -vl_msg_api_socket_handler (void *the_msg) +vl_msg_api_socket_handler (void *the_msg, uword msg_len) { api_main_t *am = vlibapi_get_main (); - msg_handler_internal (am, the_msg, - (am->rx_trace - && am->rx_trace->enabled) /* trace_it */ , - 1 /* do_it */ , 0 /* free_it */ ); + msg_handler_internal (am, the_msg, msg_len, + (am->rx_trace && am->rx_trace->enabled) /* trace_it */, + 1 /* do_it */, 0 /* free_it */); } #define foreach_msg_api_vector \ @@ -882,6 +754,7 @@ vl_msg_api_socket_handler (void *the_msg) _ (msg_print_json_handlers) \ _ (msg_tojson_handlers) \ _ (msg_fromjson_handlers) \ + _ (msg_calc_size_funcs) \ _ (api_trace_cfg) \ _ (message_bounce) \ _ (is_mp_safe) \ @@ -927,6 +800,7 @@ vl_msg_api_config (vl_msg_api_msg_config_t * c) am->msg_print_json_handlers[c->id] = c->print_json; am->msg_tojson_handlers[c->id] = c->tojson; am->msg_fromjson_handlers[c->id] = c->fromjson; + am->msg_calc_size_funcs[c->id] = c->calc_size; am->message_bounce[c->id] = c->message_bounce; am->is_mp_safe[c->id] = c->is_mp_safe; am->is_autoendian[c->id] = c->is_autoendian; @@ -948,7 +822,8 @@ vl_msg_api_config (vl_msg_api_msg_config_t * c) void vl_msg_api_set_handlers (int id, char *name, void *handler, void *cleanup, void *endian, void *print, int size, int traced, - void *print_json, void *tojson, void *fromjson) + void *print_json, void *tojson, void *fromjson, + void *calc_size) { vl_msg_api_msg_config_t cfg; vl_msg_api_msg_config_t *c = &cfg; @@ -969,6 +844,7 @@ vl_msg_api_set_handlers (int id, char *name, void *handler, void *cleanup, c->tojson = tojson; c->fromjson = fromjson; c->print_json = print_json; + c->calc_size = calc_size; vl_msg_api_config (c); } @@ -999,8 +875,11 @@ vl_msg_api_queue_handler (svm_queue_t * q) { uword msg; - while (!svm_queue_sub (q, (u8 *) & msg, SVM_Q_WAIT, 0)) - vl_msg_api_handler ((void *) msg); + while (!svm_queue_sub (q, (u8 *) &msg, SVM_Q_WAIT, 0)) + { + msgbuf_t *msgbuf = (msgbuf_t *) ((u8 *) msg - offsetof (msgbuf_t, data)); + vl_msg_api_handler ((void *) msg, ntohl (msgbuf->data_len)); + } } u32 @@ -1081,41 +960,6 @@ vl_msg_api_post_mortem_dump (void) /* Layered message handling support */ -void -vl_msg_api_register_pd_handler (void *fp, u16 msg_id_host_byte_order) -{ - api_main_t *am = vlibapi_get_main (); - - /* Mild idiot proofing */ - if (msg_id_host_byte_order > 10000) - clib_warning ("msg_id_host_byte_order endian issue? %d arg vs %d", - msg_id_host_byte_order, - clib_net_to_host_u16 (msg_id_host_byte_order)); - vec_validate (am->pd_msg_handlers, msg_id_host_byte_order); - am->pd_msg_handlers[msg_id_host_byte_order] = fp; -} - -int -vl_msg_api_pd_handler (void *mp, int rv) -{ - api_main_t *am = vlibapi_get_main (); - int (*fp) (void *, int); - u16 msg_id; - - if (clib_arch_is_little_endian) - msg_id = clib_net_to_host_u16 (*((u16 *) mp)); - else - msg_id = *((u16 *) mp); - - if (msg_id >= vec_len (am->pd_msg_handlers) - || am->pd_msg_handlers[msg_id] == 0) - return rv; - - fp = am->pd_msg_handlers[msg_id]; - rv = (*fp) (mp, rv); - return rv; -} - void vl_msg_api_set_first_available_msg_id (u16 first_avail) {