From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) by dpdk.org (Postfix) with ESMTP id 710297F2D for ; Mon, 10 Nov 2014 10:09:44 +0100 (CET) Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga103.jf.intel.com with ESMTP; 10 Nov 2014 01:17:11 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.07,351,1413270000"; d="scan'208";a="634344076" Received: from sie-lab-212-143.ir.intel.com (HELO silpixa00385294.ir.intel.com) ([10.237.212.143]) by orsmga002.jf.intel.com with ESMTP; 10 Nov 2014 01:19:26 -0800 From: Alan Carew To: dev@dpdk.org Date: Mon, 10 Nov 2014 09:19:06 +0000 Message-Id: <1415611146-32368-1-git-send-email-alan.carew@intel.com> X-Mailer: git-send-email 1.9.3 In-Reply-To: <1412003903-9061-1-git-send-email-alan.carew@intel.com> References: <1412003903-9061-1-git-send-email-alan.carew@intel.com> Subject: [dpdk-dev] [PATCH v2] librte_cmdline: FreeBSD Fix oveflow when size of command result structure is greater than BUFSIZ X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 10 Nov 2014 09:09:45 -0000 When using test-pmd with flow director in FreeBSD, the application will segfault/Bus error while parsing the command-line. This is due to how each commands result structure is represented during parsing, where the offsets for each tokens value is stored in a character array(char result_buf[BUFSIZ]) in cmdline_parse()(./lib/librte_cmdline/cmdline_parse.c). The overflow occurs where BUFSIZ is less than the size of a commands result structure, in this case "struct cmd_pkt_filter_result" (app/test-pmd/cmdline.c) is 1088 bytes and BUFSIZ on FreeBSD is 1024 bytes as opposed to 8192 bytes on Linux. The problem can be reproduced by running test-pmd on FreeBSD: ./testpmd -c 0x3 -n 4 -- -i --portmask=0x3 --pkt-filter-mode=perfect And adding a filter: add_perfect_filter 0 udp src 192.168.0.0 1024 dst 192.168.0.0 1024 flexbytes 0x800 vlan 0 queue 0 soft 0x17 This patch removes the OS dependency on BUFSIZ and defines and uses a library #define CMDLINE_PARSE_RESULT_BUFSIZE 8192 Added boundary checking to ensure this buffer size cannot overflow, with an error message being produced. Suggested-by: Olivier MATZ http://git.droids-corp.org/?p=libcmdline.git;a=commitdiff;h=b1d5b169352e57df3fc14c51ffad4b83f3e5613f Signed-off-by: Alan Carew --- lib/librte_cmdline/cmdline_parse.c | 22 +++++++++++++++------- lib/librte_cmdline/cmdline_parse.h | 3 +++ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/lib/librte_cmdline/cmdline_parse.c b/lib/librte_cmdline/cmdline_parse.c index 940480d..f86f163 100644 --- a/lib/librte_cmdline/cmdline_parse.c +++ b/lib/librte_cmdline/cmdline_parse.c @@ -138,7 +138,7 @@ nb_common_chars(const char * s1, const char * s2) */ static int match_inst(cmdline_parse_inst_t *inst, const char *buf, - unsigned int nb_match_token, void * result_buf) + unsigned int nb_match_token, void *result_buf, unsigned result_buf_size) { unsigned int token_num=0; cmdline_parse_token_hdr_t * token_p; @@ -162,10 +162,18 @@ match_inst(cmdline_parse_inst_t *inst, const char *buf, if ( isendofline(*buf) || iscomment(*buf) ) break; - if (result_buf) + if (result_buf) { + if (token_hdr.offset > result_buf_size) { + printf("Parse error(%s:%d): Token offset(%u) exceeds maximum " + "size(%u)\n", __FILE__, __LINE__, token_hdr.offset, + result_buf_size); + return -ENOBUFS; + } + n = token_hdr.ops->parse(token_p, buf, (char *)result_buf + token_hdr.offset); + } else n = token_hdr.ops->parse(token_p, buf, NULL); @@ -219,7 +227,7 @@ cmdline_parse(struct cmdline *cl, const char * buf) unsigned int inst_num=0; cmdline_parse_inst_t *inst; const char *curbuf; - char result_buf[BUFSIZ]; + char result_buf[CMDLINE_PARSE_RESULT_BUFSIZE]; void (*f)(void *, struct cmdline *, void *) = NULL; void *data = NULL; int comment = 0; @@ -280,7 +288,7 @@ cmdline_parse(struct cmdline *cl, const char * buf) debug_printf("INST %d\n", inst_num); /* fully parsed */ - tok = match_inst(inst, buf, 0, result_buf); + tok = match_inst(inst, buf, 0, result_buf, sizeof(result_buf)); if (tok > 0) /* we matched at least one token */ err = CMDLINE_PARSE_BAD_ARGS; @@ -377,10 +385,10 @@ cmdline_complete(struct cmdline *cl, const char *buf, int *state, inst = ctx[inst_num]; while (inst) { /* parse the first tokens of the inst */ - if (nb_token && match_inst(inst, buf, nb_token, NULL)) + if (nb_token && match_inst(inst, buf, nb_token, NULL, 0)) goto next; - debug_printf("instruction match \n"); + debug_printf("instruction match\n"); token_p = inst->tokens[nb_token]; if (token_p) memcpy(&token_hdr, token_p, sizeof(token_hdr)); @@ -471,7 +479,7 @@ cmdline_complete(struct cmdline *cl, const char *buf, int *state, /* we need to redo it */ inst = ctx[inst_num]; - if (nb_token && match_inst(inst, buf, nb_token, NULL)) + if (nb_token && match_inst(inst, buf, nb_token, NULL, 0)) goto next2; token_p = inst->tokens[nb_token]; diff --git a/lib/librte_cmdline/cmdline_parse.h b/lib/librte_cmdline/cmdline_parse.h index f18836d..dae53ba 100644 --- a/lib/librte_cmdline/cmdline_parse.h +++ b/lib/librte_cmdline/cmdline_parse.h @@ -80,6 +80,9 @@ extern "C" { #define CMDLINE_PARSE_COMPLETE_AGAIN 1 #define CMDLINE_PARSE_COMPLETED_BUFFER 2 +/* maximum buffer size for parsed result */ +#define CMDLINE_PARSE_RESULT_BUFSIZE 8192 + /** * Stores a pointer to the ops struct, and the offset: the place to * write the parsed result in the destination structure. -- 1.9.3