action_block_parse() and apply_block_parse() build instruction strings by concatenating untrusted tokens into a fixed-size stack buffer. Replace the open-coded strcat() loop with a helper that tracks the remaining capacity and fails when the assembled instruction would exceed RTE_SWX_INSTRUCTION_SIZE.
Signed-off-by: Pengpeng Hou <[email protected]> --- lib/pipeline/rte_swx_pipeline.c | 30 ++++++++++++--------- lib/pipeline/rte_swx_pipeline_spec.c | 40 ++++++++++++++++++---------- 2 files changed, 43 insertions(+), 27 deletions(-) diff --git a/lib/pipeline/rte_swx_pipeline.c b/lib/pipeline/rte_swx_pipeline.c index a915781..500b9d7 100644 --- a/lib/pipeline/rte_swx_pipeline.c +++ b/lib/pipeline/rte_swx_pipeline.c @@ -11,6 +11,7 @@ #include <rte_eal_memconfig.h> #include <rte_jhash.h> #include <rte_hash_crc.h> +#include <rte_string_fns.h> #include <rte_swx_port_ethdev.h> #include <rte_swx_port_fd.h> @@ -42,6 +43,9 @@ do { \ RTE_SWX_INSTRUCTION_SIZE), \ err_code) +#define CHECK_STRLCPY(dst, src, err_code) \ + CHECK(strlcpy((dst), (src), sizeof(dst)) < sizeof(dst), err_code) + /* * Environment. */ @@ -5680,7 +5684,7 @@ instr_jmp_translate(struct rte_swx_pipeline *p __rte_unused, { CHECK(n_tokens == 2, EINVAL); - strcpy(data->jmp_label, tokens[1]); + CHECK_STRLCPY(data->jmp_label, tokens[1], EINVAL); instr->type = INSTR_JMP; instr->jmp.ip = NULL; /* Resolved later. */ @@ -5699,7 +5703,7 @@ instr_jmp_valid_translate(struct rte_swx_pipeline *p, CHECK(n_tokens == 3, EINVAL); - strcpy(data->jmp_label, tokens[1]); + CHECK_STRLCPY(data->jmp_label, tokens[1], EINVAL); h = header_parse(p, tokens[2]); CHECK(h, EINVAL); @@ -5722,7 +5726,7 @@ instr_jmp_invalid_translate(struct rte_swx_pipeline *p, CHECK(n_tokens == 3, EINVAL); - strcpy(data->jmp_label, tokens[1]); + CHECK_STRLCPY(data->jmp_label, tokens[1], EINVAL); h = header_parse(p, tokens[2]); CHECK(h, EINVAL); @@ -5744,7 +5748,7 @@ instr_jmp_hit_translate(struct rte_swx_pipeline *p __rte_unused, CHECK(!action, EINVAL); CHECK(n_tokens == 2, EINVAL); - strcpy(data->jmp_label, tokens[1]); + CHECK_STRLCPY(data->jmp_label, tokens[1], EINVAL); instr->type = INSTR_JMP_HIT; instr->jmp.ip = NULL; /* Resolved later. */ @@ -5762,7 +5766,7 @@ instr_jmp_miss_translate(struct rte_swx_pipeline *p __rte_unused, CHECK(!action, EINVAL); CHECK(n_tokens == 2, EINVAL); - strcpy(data->jmp_label, tokens[1]); + CHECK_STRLCPY(data->jmp_label, tokens[1], EINVAL); instr->type = INSTR_JMP_MISS; instr->jmp.ip = NULL; /* Resolved later. */ @@ -5782,7 +5786,7 @@ instr_jmp_action_hit_translate(struct rte_swx_pipeline *p, CHECK(!action, EINVAL); CHECK(n_tokens == 3, EINVAL); - strcpy(data->jmp_label, tokens[1]); + CHECK_STRLCPY(data->jmp_label, tokens[1], EINVAL); a = action_find(p, tokens[2]); CHECK(a, EINVAL); @@ -5806,7 +5810,7 @@ instr_jmp_action_miss_translate(struct rte_swx_pipeline *p, CHECK(!action, EINVAL); CHECK(n_tokens == 3, EINVAL); - strcpy(data->jmp_label, tokens[1]); + CHECK_STRLCPY(data->jmp_label, tokens[1], EINVAL); a = action_find(p, tokens[2]); CHECK(a, EINVAL); @@ -5832,7 +5836,7 @@ instr_jmp_eq_translate(struct rte_swx_pipeline *p, CHECK(n_tokens == 4, EINVAL); - strcpy(data->jmp_label, tokens[1]); + CHECK_STRLCPY(data->jmp_label, tokens[1], EINVAL); fa = struct_field_parse(p, action, a, &a_struct_id); CHECK(fa, EINVAL); @@ -5892,7 +5896,7 @@ instr_jmp_neq_translate(struct rte_swx_pipeline *p, CHECK(n_tokens == 4, EINVAL); - strcpy(data->jmp_label, tokens[1]); + CHECK_STRLCPY(data->jmp_label, tokens[1], EINVAL); fa = struct_field_parse(p, action, a, &a_struct_id); CHECK(fa, EINVAL); @@ -5952,7 +5956,7 @@ instr_jmp_lt_translate(struct rte_swx_pipeline *p, CHECK(n_tokens == 4, EINVAL); - strcpy(data->jmp_label, tokens[1]); + CHECK_STRLCPY(data->jmp_label, tokens[1], EINVAL); fa = struct_field_parse(p, action, a, &a_struct_id); CHECK(fa, EINVAL); @@ -6012,7 +6016,7 @@ instr_jmp_gt_translate(struct rte_swx_pipeline *p, CHECK(n_tokens == 4, EINVAL); - strcpy(data->jmp_label, tokens[1]); + CHECK_STRLCPY(data->jmp_label, tokens[1], EINVAL); fa = struct_field_parse(p, action, a, &a_struct_id); CHECK(fa, EINVAL); @@ -6437,7 +6441,7 @@ instr_translate(struct rte_swx_pipeline *p, /* Handle the optional instruction label. */ if ((n_tokens >= 2) && !strcmp(tokens[1], ":")) { - strcpy(data->label, tokens[0]); + CHECK_STRLCPY(data->label, tokens[0], EINVAL); tpos += 2; CHECK(n_tokens - tpos, EINVAL); @@ -8541,7 +8545,7 @@ rte_swx_pipeline_table_config(struct rte_swx_pipeline *p, /* Node initialization. */ strcpy(t->name, name); if (args && args[0]) - strcpy(t->args, args); + CHECK_STRLCPY(t->args, args, EINVAL); t->type = type; for (i = 0; i < params->n_fields; i++) { diff --git a/lib/pipeline/rte_swx_pipeline_spec.c b/lib/pipeline/rte_swx_pipeline_spec.c index 986bbe5..3df191e 100644 --- a/lib/pipeline/rte_swx_pipeline_spec.c +++ b/lib/pipeline/rte_swx_pipeline_spec.c @@ -39,6 +39,28 @@ #define LEARNER_TIMEOUT_BLOCK 10 #define APPLY_BLOCK 11 +static int +buffer_append_tokens(char *buffer, size_t buffer_size, char **tokens, + uint32_t n_tokens) +{ + size_t len = 0; + uint32_t i; + + buffer[0] = 0; + for (i = 0; i < n_tokens; i++) { + int ret; + + ret = snprintf(buffer + len, buffer_size - len, "%s%s", + i ? " " : "", tokens[i]); + if ((ret < 0) || ((size_t)ret >= buffer_size - len)) + return -ENAMETOOLONG; + + len += (size_t)ret; + } + + return 0; +} + /* * extobj. */ @@ -454,7 +476,6 @@ action_block_parse(struct action_spec *s, { char buffer[RTE_SWX_INSTRUCTION_SIZE], *instr; const char **new_instructions; - uint32_t i; /* Handle end of block. */ if ((n_tokens == 1) && !strcmp(tokens[0], "}")) { @@ -463,12 +484,8 @@ action_block_parse(struct action_spec *s, } /* spec. */ - buffer[0] = 0; - for (i = 0; i < n_tokens; i++) { - if (i) - strcat(buffer, " "); - strcat(buffer, tokens[i]); - } + if (buffer_append_tokens(buffer, sizeof(buffer), tokens, n_tokens)) + return -ENAMETOOLONG; instr = strdup(buffer); if (!instr) { @@ -2142,7 +2159,6 @@ apply_block_parse(struct apply_spec *s, { char buffer[RTE_SWX_INSTRUCTION_SIZE], *instr; const char **new_instructions; - uint32_t i; /* Handle end of block. */ if ((n_tokens == 1) && !strcmp(tokens[0], "}")) { @@ -2151,12 +2167,8 @@ apply_block_parse(struct apply_spec *s, } /* spec. */ - buffer[0] = 0; - for (i = 0; i < n_tokens; i++) { - if (i) - strcat(buffer, " "); - strcat(buffer, tokens[i]); - } + if (buffer_append_tokens(buffer, sizeof(buffer), tokens, n_tokens)) + return -ENAMETOOLONG; instr = strdup(buffer); if (!instr) { -- 2.50.1 (Apple Git-155)

