From patchwork Wed Jul 3 13:40:34 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Ananyev, Konstantin" X-Patchwork-Id: 56021 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 44F982956; Wed, 3 Jul 2019 15:40:51 +0200 (CEST) Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) by dpdk.org (Postfix) with ESMTP id B06212AB; Wed, 3 Jul 2019 15:40:47 +0200 (CEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by orsmga103.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 03 Jul 2019 06:40:42 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.63,446,1557212400"; d="scan'208";a="362631942" Received: from sivswdev08.ir.intel.com ([10.237.217.47]) by fmsmga005.fm.intel.com with ESMTP; 03 Jul 2019 06:40:40 -0700 From: Konstantin Ananyev To: dev@dpdk.org Cc: michel@digirati.com.br, Konstantin Ananyev , stable@dpdk.org Date: Wed, 3 Jul 2019 14:40:34 +0100 Message-Id: <20190703134035.4773-2-konstantin.ananyev@intel.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20190703134035.4773-1-konstantin.ananyev@intel.com> References: <20190703134035.4773-1-konstantin.ananyev@intel.com> Subject: [dpdk-dev] [PATCH 1/2] bpf: fix validate for function return value X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" eval_call() blindly calls eval_max_bound() for external function return value for all return types. That causes wrong estimation for returned pointer min and max boundaries. So any attempt to dereference that pointer value causes verifier to fail with error message: "memory boundary violation at pc: ...". To fix - estimate min/max boundaries based on the return value type. For more details please refer to: https://bugs.dpdk.org/show_bug.cgi?id=298 Fixes: 8021917293d0 ("bpf: add extra validation for input BPF program") Cc: stable@dpdk.org Reported-by: Michel Machado Suggested-by: Michel Machado Signed-off-by: Konstantin Ananyev --- lib/librte_bpf/bpf_validate.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/librte_bpf/bpf_validate.c b/lib/librte_bpf/bpf_validate.c index d0e683b5b..0cf41fa27 100644 --- a/lib/librte_bpf/bpf_validate.c +++ b/lib/librte_bpf/bpf_validate.c @@ -925,7 +925,6 @@ eval_func_arg(struct bpf_verifier *bvf, const struct rte_bpf_arg *arg, static const char * eval_call(struct bpf_verifier *bvf, const struct ebpf_insn *ins) { - uint64_t msk; uint32_t i, idx; struct bpf_reg_val *rv; const struct rte_bpf_xsym *xsym; @@ -958,10 +957,11 @@ eval_call(struct bpf_verifier *bvf, const struct ebpf_insn *ins) rv = bvf->evst->rv + EBPF_REG_0; rv->v = xsym->func.ret; - msk = (rv->v.type == RTE_BPF_ARG_RAW) ? - RTE_LEN2MASK(rv->v.size * CHAR_BIT, uint64_t) : UINTPTR_MAX; - eval_max_bound(rv, msk); - rv->mask = msk; + if (rv->v.type == RTE_BPF_ARG_RAW) + eval_fill_max_bound(rv, + RTE_LEN2MASK(rv->v.size * CHAR_BIT, uint64_t)); + else if (RTE_BPF_ARG_PTR_TYPE(rv->v.type) != 0) + eval_fill_imm64(rv, UINTPTR_MAX, 0); return err; } From patchwork Wed Jul 3 13:40:35 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Ananyev, Konstantin" X-Patchwork-Id: 56022 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 650F131FC; Wed, 3 Jul 2019 15:40:53 +0200 (CEST) Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) by dpdk.org (Postfix) with ESMTP id 3B3871BE0 for ; Wed, 3 Jul 2019 15:40:48 +0200 (CEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by orsmga103.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 03 Jul 2019 06:40:43 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.63,446,1557212400"; d="scan'208";a="362631950" Received: from sivswdev08.ir.intel.com ([10.237.217.47]) by fmsmga005.fm.intel.com with ESMTP; 03 Jul 2019 06:40:41 -0700 From: Konstantin Ananyev To: dev@dpdk.org Cc: michel@digirati.com.br, Konstantin Ananyev Date: Wed, 3 Jul 2019 14:40:35 +0100 Message-Id: <20190703134035.4773-3-konstantin.ananyev@intel.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20190703134035.4773-1-konstantin.ananyev@intel.com> References: <20190703134035.4773-1-konstantin.ananyev@intel.com> Subject: [dpdk-dev] [PATCH 2/2] test/bpf: add test-case for function return value X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" New test-case to cover situation when external function returns a pointer the data. Signed-off-by: Konstantin Ananyev --- app/test/test_bpf.c | 130 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) diff --git a/app/test/test_bpf.c b/app/test/test_bpf.c index 1d50401aa..e8841800a 100644 --- a/app/test/test_bpf.c +++ b/app/test/test_bpf.c @@ -1777,6 +1777,118 @@ static const struct rte_bpf_xsym test_call2_xsym[] = { }, }; +static const struct ebpf_insn test_call3_prog[] = { + + { + .code = (BPF_JMP | EBPF_CALL), + .imm = 0, + }, + { + .code = (BPF_LDX | BPF_MEM | BPF_B), + .dst_reg = EBPF_REG_2, + .src_reg = EBPF_REG_0, + .off = offsetof(struct dummy_offset, u8), + }, + { + .code = (BPF_LDX | BPF_MEM | BPF_H), + .dst_reg = EBPF_REG_3, + .src_reg = EBPF_REG_0, + .off = offsetof(struct dummy_offset, u16), + }, + { + .code = (BPF_LDX | BPF_MEM | BPF_W), + .dst_reg = EBPF_REG_4, + .src_reg = EBPF_REG_0, + .off = offsetof(struct dummy_offset, u32), + }, + { + .code = (BPF_LDX | BPF_MEM | EBPF_DW), + .dst_reg = EBPF_REG_0, + .src_reg = EBPF_REG_0, + .off = offsetof(struct dummy_offset, u64), + }, + /* return sum */ + { + .code = (EBPF_ALU64 | BPF_ADD | BPF_X), + .dst_reg = EBPF_REG_0, + .src_reg = EBPF_REG_4, + }, + { + .code = (EBPF_ALU64 | BPF_ADD | BPF_X), + .dst_reg = EBPF_REG_0, + .src_reg = EBPF_REG_3, + }, + { + .code = (EBPF_ALU64 | BPF_ADD | BPF_X), + .dst_reg = EBPF_REG_0, + .src_reg = EBPF_REG_2, + }, + { + .code = (BPF_JMP | EBPF_EXIT), + }, +}; + +static const struct dummy_offset * +dummy_func3(const struct dummy_vect8 *p) +{ + return &p->in[RTE_DIM(p->in) - 1]; +} + +static void +test_call3_prepare(void *arg) +{ + struct dummy_vect8 *pv; + struct dummy_offset *df; + + pv = arg; + df = (struct dummy_offset *)(uintptr_t)dummy_func3(pv); + + memset(pv, 0, sizeof(*pv)); + df->u64 = (int32_t)TEST_FILL_1; + df->u32 = df->u64; + df->u16 = df->u64; + df->u8 = df->u64; +} + +static int +test_call3_check(uint64_t rc, const void *arg) +{ + uint64_t v; + const struct dummy_vect8 *pv; + const struct dummy_offset *dft; + + pv = arg; + dft = dummy_func3(pv); + + v = dft->u64; + v += dft->u32; + v += dft->u16; + v += dft->u8; + + return cmp_res(__func__, v, rc, pv, pv, sizeof(*pv)); +} + +static const struct rte_bpf_xsym test_call3_xsym[] = { + { + .name = RTE_STR(dummy_func3), + .type = RTE_BPF_XTYPE_FUNC, + .func = { + .val = (void *)dummy_func3, + .nb_args = 1, + .args = { + [0] = { + .type = RTE_BPF_ARG_PTR, + .size = sizeof(struct dummy_vect8), + }, + }, + .ret = { + .type = RTE_BPF_ARG_PTR, + .size = sizeof(struct dummy_offset), + }, + }, + }, +}; + static const struct bpf_test tests[] = { { .name = "test_store1", @@ -1968,6 +2080,24 @@ static const struct bpf_test tests[] = { /* for now don't support function calls on 32 bit platform */ .allow_fail = (sizeof(uint64_t) != sizeof(uintptr_t)), }, + { + .name = "test_call3", + .arg_sz = sizeof(struct dummy_vect8), + .prm = { + .ins = test_call3_prog, + .nb_ins = RTE_DIM(test_call3_prog), + .prog_arg = { + .type = RTE_BPF_ARG_PTR, + .size = sizeof(struct dummy_vect8), + }, + .xsym = test_call3_xsym, + .nb_xsym = RTE_DIM(test_call3_xsym), + }, + .prepare = test_call3_prepare, + .check_result = test_call3_check, + /* for now don't support function calls on 32 bit platform */ + .allow_fail = (sizeof(uint64_t) != sizeof(uintptr_t)), + }, }; static int