api: improve api string safety
- Remove vl_api_from_api_string to prevent use of not nul-terminated strings. - Rename vl_api_from_api_to_vec -> vl_api_from_api_to_new_vec to imply a new vector is created. NOT nul terminated. - Add vl_api_from_api_to_new_c_string. Returns nul terminated string in a new vector. - Add vl_api_c_string_to_api_string. Convert nul terminated string to vl_api_string_t - Add vl_api_vec_to_api_string. Convert NON nul terminated vector to vl_api_string_t Type: fix Signed-off-by: Jakub Grajciar <jgrajcia@cisco.com> Change-Id: Iadd59b612c0d960a34ad0dd07a9d17f56435c6ea Signed-off-by: Jakub Grajciar <jgrajcia@cisco.com>
This commit is contained in:
Jakub Grajciar
committed by
Ole Trøan
parent
8e755a16a7
commit
2dbee9361e
@ -111,11 +111,8 @@ api_http_static_enable (vat_main_t * vam)
|
||||
|
||||
/* Construct the API message */
|
||||
M (HTTP_STATIC_ENABLE, mp);
|
||||
vl_api_to_api_string (strnlen ((const char *) www_root, 256),
|
||||
(const char *) www_root,
|
||||
(vl_api_string_t *) & mp->www_root);
|
||||
vl_api_to_api_string (strnlen ((const char *) uri, 256), (const char *) uri,
|
||||
(vl_api_string_t *) & mp->uri);
|
||||
strncpy_s ((char *) mp->www_root, 256, (const char *) www_root, 256);
|
||||
strncpy_s ((char *) mp->uri, 256, (const char *) uri, 256);
|
||||
mp->fifo_size = ntohl (fifo_size);
|
||||
mp->cache_size_limit = ntohl (cache_size_limit);
|
||||
mp->prealloc_fifos = ntohl (prealloc_fifos);
|
||||
|
@ -43,7 +43,7 @@ static void vl_api_pot_profile_add_t_handler
|
||||
pot_profile *profile = NULL;
|
||||
u8 *name = 0;
|
||||
|
||||
name = vl_api_from_api_to_vec(&mp->list_name);
|
||||
name = vl_api_from_api_to_new_vec(&mp->list_name);
|
||||
|
||||
pot_profile_list_init(name);
|
||||
id = mp->id;
|
||||
@ -121,7 +121,7 @@ static void vl_api_pot_profile_activate_t_handler
|
||||
u8 id;
|
||||
u8 *name = NULL;
|
||||
|
||||
name = vl_api_from_api_to_vec(&mp->list_name);
|
||||
name = vl_api_from_api_to_new_vec(&mp->list_name);
|
||||
if (!pot_profile_list_is_enabled(name)) {
|
||||
rv = -1;
|
||||
} else {
|
||||
|
@ -88,7 +88,7 @@ static int api_pot_profile_add (vat_main_t *vam)
|
||||
|
||||
M2(POT_PROFILE_ADD, mp, sizeof(vl_api_string_t) + vec_len(name));
|
||||
|
||||
vl_api_to_api_string(vec_len(name), (const char *)name, &mp->list_name);
|
||||
vl_api_vec_to_api_string(name, &mp->list_name);
|
||||
mp->secret_share = clib_host_to_net_u64(secret_share);
|
||||
mp->polynomial_public = clib_host_to_net_u64(poly2);
|
||||
mp->lpc = clib_host_to_net_u64(lpc);
|
||||
@ -142,7 +142,7 @@ static int api_pot_profile_activate (vat_main_t *vam)
|
||||
}
|
||||
|
||||
M2(POT_PROFILE_ACTIVATE, mp, sizeof(vl_api_string_t) + vec_len(name));
|
||||
vl_api_to_api_string(vec_len(name), (const char *)name, &mp->list_name);
|
||||
vl_api_vec_to_api_string(name, &mp->list_name);
|
||||
mp->id = id;
|
||||
|
||||
S(mp);
|
||||
|
@ -112,9 +112,7 @@ api_memif_socket_filename_add_del (vat_main_t * vam)
|
||||
mp->is_add = is_add;
|
||||
mp->socket_id = htonl (socket_id);
|
||||
char *p = (char *) &mp->socket_filename;
|
||||
p +=
|
||||
vl_api_to_api_string (strlen ((char *) socket_filename),
|
||||
(char *) socket_filename, (vl_api_string_t *) p);
|
||||
p += vl_api_vec_to_api_string (socket_filename, (vl_api_string_t *) p);
|
||||
|
||||
vec_free (socket_filename);
|
||||
|
||||
@ -218,8 +216,7 @@ api_memif_create (vat_main_t * vam)
|
||||
if (secret != 0)
|
||||
{
|
||||
char *p = (char *) &mp->secret;
|
||||
p += vl_api_to_api_string (strlen ((char *) secret), (char *) secret,
|
||||
(vl_api_string_t *) p);
|
||||
p += vl_api_vec_to_api_string (secret, (vl_api_string_t *) p);
|
||||
vec_free (secret);
|
||||
}
|
||||
memcpy (mp->hw_addr, hw_addr, 6);
|
||||
|
@ -136,10 +136,9 @@ class Printfun():
|
||||
if o.modern_vla:
|
||||
write(' if (vl_api_string_len(&a->{f}) > 0) {{\n'
|
||||
.format(f=o.fieldname))
|
||||
write(' s = format(s, "\\n%U{f}: %.*s", '
|
||||
write(' s = format(s, "\\n%U{f}: %U", '
|
||||
'format_white_space, indent, '
|
||||
'vl_api_string_len(&a->{f}) - 1, '
|
||||
'vl_api_from_api_string(&a->{f}));\n'.format(f=o.fieldname))
|
||||
'vl_api_format_string, (&a->{f}));\n'.format(f=o.fieldname))
|
||||
write(' } else {\n')
|
||||
write(' s = format(s, "\\n%U{f}:", '
|
||||
'format_white_space, indent);\n'.format(f=o.fieldname))
|
||||
|
@ -1127,18 +1127,12 @@ vl_api_cli_inband_reply_t_handler (vl_api_cli_inband_reply_t * mp)
|
||||
{
|
||||
vat_main_t *vam = &vat_main;
|
||||
i32 retval = ntohl (mp->retval);
|
||||
u32 length = vl_api_string_len (&mp->reply);
|
||||
|
||||
vec_reset_length (vam->cmd_reply);
|
||||
|
||||
vam->retval = retval;
|
||||
if (retval == 0)
|
||||
{
|
||||
vec_validate (vam->cmd_reply, length);
|
||||
clib_memcpy ((char *) (vam->cmd_reply),
|
||||
vl_api_from_api_string (&mp->reply), length);
|
||||
vam->cmd_reply[length] = 0;
|
||||
}
|
||||
vam->cmd_reply = vl_api_from_api_to_new_vec (&mp->reply);
|
||||
vam->result_ready = 1;
|
||||
}
|
||||
|
||||
@ -1147,16 +1141,18 @@ vl_api_cli_inband_reply_t_handler_json (vl_api_cli_inband_reply_t * mp)
|
||||
{
|
||||
vat_main_t *vam = &vat_main;
|
||||
vat_json_node_t node;
|
||||
u8 *reply = 0; /* reply vector */
|
||||
|
||||
reply = vl_api_from_api_to_new_vec (&mp->reply);
|
||||
vec_reset_length (vam->cmd_reply);
|
||||
|
||||
vat_json_init_object (&node);
|
||||
vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
|
||||
vat_json_object_add_string_copy (&node, "reply",
|
||||
vl_api_from_api_string (&mp->reply));
|
||||
vat_json_object_add_string_copy (&node, "reply", reply);
|
||||
|
||||
vat_json_print (vam->ofp, &node);
|
||||
vat_json_free (&node);
|
||||
vec_free (reply);
|
||||
|
||||
vam->retval = ntohl (mp->retval);
|
||||
vam->result_ready = 1;
|
||||
@ -5638,9 +5634,8 @@ exec_inband (vat_main_t * vam)
|
||||
* must be a vector ending in \n, not a C-string ending
|
||||
* in \n\0.
|
||||
*/
|
||||
u32 len = vec_len (vam->input->buffer);
|
||||
M2 (CLI_INBAND, mp, len);
|
||||
vl_api_to_api_string (len - 1, (const char *) vam->input->buffer, &mp->cmd);
|
||||
M2 (CLI_INBAND, mp, vec_len (vam->input->buffer));
|
||||
vl_api_vec_to_api_string (vam->input->buffer, &mp->cmd);
|
||||
|
||||
S (mp);
|
||||
W (ret);
|
||||
|
@ -1091,15 +1091,19 @@ vl_msg_pop_heap (void *oldheap)
|
||||
vl_msg_pop_heap_w_region (am->vlib_rp, oldheap);
|
||||
}
|
||||
|
||||
/* Must be nul terminated */
|
||||
int
|
||||
vl_api_to_api_string (u32 len, const char *buf, vl_api_string_t * str)
|
||||
vl_api_c_string_to_api_string (const char *buf, vl_api_string_t * str)
|
||||
{
|
||||
if (len)
|
||||
/* copy without nul terminator */
|
||||
u32 len = strlen (buf);
|
||||
if (len > 0)
|
||||
clib_memcpy_fast (str->buf, buf, len);
|
||||
str->length = htonl (len);
|
||||
return len + sizeof (u32);
|
||||
}
|
||||
|
||||
/* Must NOT be nul terminated */
|
||||
int
|
||||
vl_api_vec_to_api_string (const u8 * vec, vl_api_string_t * str)
|
||||
{
|
||||
@ -1109,13 +1113,6 @@ vl_api_vec_to_api_string (const u8 * vec, vl_api_string_t * str)
|
||||
return len + sizeof (u32);
|
||||
}
|
||||
|
||||
/* Return a pointer to the API string (not nul terminated */
|
||||
u8 *
|
||||
vl_api_from_api_string (vl_api_string_t * astr)
|
||||
{
|
||||
return astr->buf;
|
||||
}
|
||||
|
||||
u32
|
||||
vl_api_string_len (vl_api_string_t * astr)
|
||||
{
|
||||
@ -1132,15 +1129,32 @@ vl_api_format_string (u8 * s, va_list * args)
|
||||
|
||||
/*
|
||||
* Returns a new vector. Remember to free it after use.
|
||||
* NOT nul terminated.
|
||||
*/
|
||||
u8 *
|
||||
vl_api_from_api_to_vec (vl_api_string_t * astr)
|
||||
vl_api_from_api_to_new_vec (vl_api_string_t * astr)
|
||||
{
|
||||
u8 *v = 0;
|
||||
vec_add (v, astr->buf, clib_net_to_host_u32 (astr->length));
|
||||
return v;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a new vector. Remember to free it after use.
|
||||
* Nul terminated.
|
||||
*/
|
||||
char *
|
||||
vl_api_from_api_to_new_c_string (vl_api_string_t * astr)
|
||||
{
|
||||
char *v = 0;
|
||||
if (clib_net_to_host_u32 (astr->length) > 0)
|
||||
{
|
||||
vec_add (v, astr->buf, clib_net_to_host_u32 (astr->length));
|
||||
vec_add1 (v, 0);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
void
|
||||
vl_api_set_elog_main (elog_main_t * m)
|
||||
{
|
||||
|
@ -38,11 +38,18 @@ typedef struct
|
||||
u8 buf[0];
|
||||
} __attribute__ ((packed)) vl_api_string_t;
|
||||
|
||||
extern int vl_api_to_api_string (u32 len, const char *buf, vl_api_string_t * str);
|
||||
/* Nul terminated string to vl_api_string_t */
|
||||
extern int vl_api_c_string_to_api_string (const char *buf, vl_api_string_t * str);
|
||||
/* NON nul terminated vector to vl_api_string_t */
|
||||
extern int vl_api_vec_to_api_string (const u8 *vec, vl_api_string_t * str);
|
||||
extern u8 * vl_api_from_api_string (vl_api_string_t * astr);
|
||||
|
||||
extern u32 vl_api_string_len (vl_api_string_t * astr);
|
||||
extern u8 * vl_api_from_api_to_vec (vl_api_string_t *astr);
|
||||
|
||||
/* Returns new vector. NON nul terminated */
|
||||
extern u8 * vl_api_from_api_to_new_vec (vl_api_string_t *astr);
|
||||
/* Returns new vector. Nul terminated */
|
||||
extern char * vl_api_from_api_to_new_c_string (vl_api_string_t *astr);
|
||||
|
||||
extern u8 *vl_api_format_string (u8 *s, va_list *args);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -134,7 +134,7 @@ vl_api_tap_create_v2_t_handler (vl_api_tap_create_v2_t * mp)
|
||||
/* If a tag was supplied... */
|
||||
if (vl_api_string_len (&mp->tag))
|
||||
{
|
||||
u8 *tag = format (0, "%s%c", vl_api_from_api_string (&mp->tag), 0);
|
||||
u8 *tag = vl_api_from_api_to_new_vec (&mp->tag);
|
||||
vnet_set_sw_interface_tag (vnm, tag, ap->sw_if_index);
|
||||
}
|
||||
|
||||
|
@ -358,7 +358,7 @@ vl_api_sw_interface_dump_t_handler (vl_api_sw_interface_dump_t * mp)
|
||||
|
||||
if (mp->name_filter_valid)
|
||||
{
|
||||
filter = vl_api_from_api_to_vec (&mp->name_filter);
|
||||
filter = vl_api_from_api_to_new_vec (&mp->name_filter);
|
||||
vec_add1 (filter, 0); /* Ensure it's a C string for strcasecmp() */
|
||||
}
|
||||
|
||||
|
@ -347,7 +347,7 @@ punt_reason_dump_walk_cb (vlib_punt_reason_t id, const u8 * name, void *args)
|
||||
|
||||
mp->context = ctx->context;
|
||||
mp->reason.id = clib_host_to_net_u32 (id);
|
||||
vl_api_to_api_string (vec_len (name), (char *) name, &mp->reason.name);
|
||||
vl_api_vec_to_api_string (name, &mp->reason.name);
|
||||
|
||||
vl_api_send_msg (ctx->reg, (u8 *) mp);
|
||||
|
||||
@ -366,7 +366,7 @@ vl_api_punt_reason_dump_t_handler (vl_api_punt_reason_dump_t * mp)
|
||||
punt_reason_dump_walk_ctx_t ctx = {
|
||||
.reg = reg,
|
||||
.context = mp->context,
|
||||
.name = vl_api_from_api_to_vec (&mp->reason.name),
|
||||
.name = vl_api_from_api_to_new_vec (&mp->reason.name),
|
||||
};
|
||||
|
||||
punt_reason_walk (punt_reason_dump_walk_cb, &ctx);
|
||||
|
@ -212,7 +212,7 @@ vl_api_cli_inband_t_handler (vl_api_cli_inband_t * mp)
|
||||
vlib_main_t *vm = vlib_get_main ();
|
||||
unformat_input_t input;
|
||||
u8 *out_vec = 0;
|
||||
u32 len = 0;
|
||||
u8 *cmd_vec = 0;
|
||||
|
||||
if (vl_msg_api_get_msg_length (mp) <
|
||||
vl_api_string_len (&mp->cmd) + sizeof (*mp))
|
||||
@ -221,20 +221,21 @@ vl_api_cli_inband_t_handler (vl_api_cli_inband_t * mp)
|
||||
goto error;
|
||||
}
|
||||
|
||||
unformat_init_string (&input, (char *) vl_api_from_api_string (&mp->cmd),
|
||||
cmd_vec = vl_api_from_api_to_new_vec (&mp->cmd);
|
||||
|
||||
unformat_init_string (&input, (char *) cmd_vec,
|
||||
vl_api_string_len (&mp->cmd));
|
||||
rv = vlib_cli_input (vm, &input, inband_cli_output, (uword) & out_vec);
|
||||
|
||||
len = vec_len (out_vec);
|
||||
|
||||
error:
|
||||
/* *INDENT-OFF* */
|
||||
REPLY_MACRO3(VL_API_CLI_INBAND_REPLY, len,
|
||||
REPLY_MACRO3(VL_API_CLI_INBAND_REPLY, vec_len (out_vec),
|
||||
({
|
||||
vl_api_to_api_string(len, (const char *)out_vec, &rmp->reply);
|
||||
vl_api_vec_to_api_string(out_vec, &rmp->reply);
|
||||
}));
|
||||
/* *INDENT-ON* */
|
||||
vec_free (out_vec);
|
||||
vec_free (cmd_vec);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1783,7 +1783,7 @@ static void *vl_api_sw_interface_dump_t_print
|
||||
|
||||
if (mp->name_filter_valid)
|
||||
{
|
||||
u8 *v = vl_api_from_api_to_vec (&mp->name_filter);
|
||||
u8 *v = vl_api_from_api_to_new_vec (&mp->name_filter);
|
||||
s = format (s, "name_filter %v ", v);
|
||||
vec_free (v);
|
||||
}
|
||||
@ -1841,10 +1841,8 @@ static void *vl_api_cli_inband_t_print
|
||||
{
|
||||
u8 *s;
|
||||
u8 *cmd = 0;
|
||||
u32 length = vl_api_string_len (&mp->cmd);
|
||||
|
||||
vec_validate (cmd, length);
|
||||
clib_memcpy (cmd, vl_api_from_api_string (&mp->cmd), length);
|
||||
cmd = vl_api_from_api_to_new_vec (&mp->cmd);
|
||||
|
||||
s = format (0, "SCRIPT: exec %v ", cmd);
|
||||
|
||||
|
@ -29,6 +29,9 @@
|
||||
#include <vapi/l2.api.vapi.h>
|
||||
#include <fake.api.vapi.h>
|
||||
|
||||
#include <vppinfra/vec.h>
|
||||
#include <vppinfra/mem.h>
|
||||
|
||||
DEFINE_VAPI_MSG_IDS_VPE_API_JSON;
|
||||
DEFINE_VAPI_MSG_IDS_INTERFACE_API_JSON;
|
||||
DEFINE_VAPI_MSG_IDS_L2_API_JSON;
|
||||
@ -911,6 +914,66 @@ START_TEST (test_unsupported)
|
||||
|
||||
END_TEST;
|
||||
|
||||
START_TEST (test_api_strings)
|
||||
{
|
||||
printf ("--- Invalid api strings ---\n");
|
||||
|
||||
/* test string 'TEST'
|
||||
* size = 5
|
||||
* length = 4
|
||||
*/
|
||||
const char str[] = "TEST";
|
||||
u8 *vec_str = 0, *vstr = 0;
|
||||
char *cstr;
|
||||
|
||||
vapi_msg_sw_interface_dump *dump =
|
||||
malloc (sizeof (vapi_msg_sw_interface_dump) + strlen (str));
|
||||
clib_mem_init (0, 1 << 20);
|
||||
|
||||
vl_api_c_string_to_api_string (str, &dump->payload.name_filter);
|
||||
/* Assert nul terminator NOT present */
|
||||
ck_assert_int_eq (vl_api_string_len (&dump->payload.name_filter),
|
||||
strlen (str));
|
||||
|
||||
cstr = vl_api_from_api_to_new_c_string (&dump->payload.name_filter);
|
||||
ck_assert_ptr_ne (cstr, NULL);
|
||||
/* Assert nul terminator present */
|
||||
ck_assert_int_eq (vec_len (cstr), sizeof (str));
|
||||
ck_assert_int_eq (strlen (str), strlen (cstr));
|
||||
vec_free (cstr);
|
||||
|
||||
vstr = vl_api_from_api_to_new_vec (&dump->payload.name_filter);
|
||||
ck_assert_ptr_ne (vstr, NULL);
|
||||
/* Assert nul terminator NOT present */
|
||||
ck_assert_int_eq (vec_len (vstr), strlen (str));
|
||||
vec_free (vstr);
|
||||
|
||||
/* vector conaining NON nul terminated string 'TEST' */
|
||||
vec_add (vec_str, str, strlen (str));
|
||||
clib_memset (dump->payload.name_filter.buf, 0, strlen (str));
|
||||
dump->payload.name_filter.length = 0;
|
||||
|
||||
vl_api_vec_to_api_string (vec_str, &dump->payload.name_filter);
|
||||
/* Assert nul terminator NOT present */
|
||||
ck_assert_int_eq (vl_api_string_len (&dump->payload.name_filter),
|
||||
vec_len (vec_str));
|
||||
|
||||
cstr = vl_api_from_api_to_new_c_string (&dump->payload.name_filter);
|
||||
ck_assert_ptr_ne (cstr, NULL);
|
||||
/* Assert nul terminator present */
|
||||
ck_assert_int_eq (vec_len (cstr), sizeof (str));
|
||||
ck_assert_int_eq (strlen (str), strlen (cstr));
|
||||
vec_free (cstr);
|
||||
|
||||
vstr = vl_api_from_api_to_new_vec (&dump->payload.name_filter);
|
||||
ck_assert_ptr_ne (vstr, NULL);
|
||||
/* Assert nul terminator NOT present */
|
||||
ck_assert_int_eq (vec_len (vstr), strlen (str));
|
||||
vec_free (vstr);
|
||||
}
|
||||
|
||||
END_TEST;
|
||||
|
||||
Suite *
|
||||
test_suite (void)
|
||||
{
|
||||
@ -957,6 +1020,10 @@ test_suite (void)
|
||||
tcase_add_test (tc_unsupported, test_unsupported);
|
||||
suite_add_tcase (s, tc_unsupported);
|
||||
|
||||
TCase *tc_dynamic = tcase_create ("Dynamic message size");
|
||||
tcase_add_test (tc_dynamic, test_api_strings);
|
||||
suite_add_tcase (s, tc_dynamic);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
@ -811,6 +811,8 @@ class TestExceptionPuntSocket(TestPuntSocket):
|
||||
rs = self.vapi.punt_reason_dump()
|
||||
for key in cfgs:
|
||||
for r in rs:
|
||||
print(r.reason.name)
|
||||
print(key)
|
||||
if r.reason.name == key:
|
||||
cfgs[key]['id'] = r.reason.id
|
||||
cfgs[key]['vpp'] = copy.deepcopy(
|
||||
|
Reference in New Issue
Block a user