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)

Reply via email to