From patchwork Wed Nov 7 20:42:17 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yifeng Sun X-Patchwork-Id: 994487 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="ITvwJZXe"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 42qz0L5JDNz9s8r for ; Thu, 8 Nov 2018 07:43:46 +1100 (AEDT) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 2EC81C58; Wed, 7 Nov 2018 20:42:28 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 0CC89BDB for ; Wed, 7 Nov 2018 20:42:27 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pf1-f193.google.com (mail-pf1-f193.google.com [209.85.210.193]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 6A91E76F for ; Wed, 7 Nov 2018 20:42:26 +0000 (UTC) Received: by mail-pf1-f193.google.com with SMTP id e22-v6so8202385pfn.8 for ; Wed, 07 Nov 2018 12:42:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=SKFf6z8pS1acdUcyTIkFt2SUeeTwY4fhfWl5TGYUGFs=; b=ITvwJZXehOahpt3S8H0hWQv++ubaaUkTKIqyxF+Roc433uiI58pR9czwBy2Qtz3vgL KZxmkyglWpbPOrYm4adGJG52N7XguhbDzU0LBGda4Kn2t0qWa2G8hbu2Bb6opC4GrMep Q34yht4JPDW3Cllm2c8u1kPbnkPrRZzxSKtafcvMZgVWYTYrrtyUMASgA5iaWqwYpX9X yJp6xBwcDgcnCPxDyzv6AFmNatB9Y1/Hx0PiKfB4c5R7JdXtHK+MO7NBoZYPgKMNlinp keneLnrPWJwlAQaClL8ss1VKQTDmrHuR8nAIbKA7r5ClriTNsaznuCTIJRm8Da7GCc2p 3SuQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=SKFf6z8pS1acdUcyTIkFt2SUeeTwY4fhfWl5TGYUGFs=; b=NOLNd/60XDNDvYNOv2PA7+ffX1npJATflyYUHpylKFFV8Eo1/A1wjOSJL2H1v3DUIo mX7pMLOyvsuPCume8qxSH/qCPQsvOEMF/NPlBz1iTl+hPFZiV7fF+W/poA8k5TbnOYqo TrlbnVC1r6rMUQN6gA4simOShnjfnYyXIAut7T/vvrkYAFEZ9gQHhCJJsNc9QgOja3bo 1WsffdQWE6rZ4QbEvykx/l3cUQxMe89sf2H4yzxppYGChU4K1tpaLn9sDCOe3vMfwKT7 5byr+75K/AySqqGAd/LcsdrxGSP+to2qWnLEzi7xjlc9JHn/2zJ0NAMLHqwP+mpMOxde HIPA== X-Gm-Message-State: AGRZ1gIVFAqmn6pdnZ5cTaqGkgdK9bXGBZ2pJVhvrEOKOYzKwo2Pce+A n3hsjdwuCloIOesE2dZFisQTpASa X-Google-Smtp-Source: AJdET5fj5AV9SpbMJD1WFxqHU4/e3BpyrRUq9POsiHGCWGXxbbSDU1CePxOrv8WM9tVEEpMTs+Djqg== X-Received: by 2002:a62:3707:: with SMTP id e7-v6mr1786573pfa.70.1541623345788; Wed, 07 Nov 2018 12:42:25 -0800 (PST) Received: from kern417.eng.vmware.com ([66.170.99.1]) by smtp.gmail.com with ESMTPSA id 123sm1359037pgd.75.2018.11.07.12.42.24 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 07 Nov 2018 12:42:24 -0800 (PST) From: Yifeng Sun To: dev@openvswitch.org Date: Wed, 7 Nov 2018 12:42:17 -0800 Message-Id: <1541623337-16025-3-git-send-email-pkusunyifeng@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1541623337-16025-1-git-send-email-pkusunyifeng@gmail.com> References: <1541623337-16025-1-git-send-email-pkusunyifeng@gmail.com> X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH] odp-util: Set a limit for nested parse_odp_key_mask_attr call X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org This patch puts a limit on the nested depth in flow key string to avoid stackoverflow. An example to show this issue is a key string contains thousands of nested encaps. In addition, a new test is added for this fix. Reported-at: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=11149 Signed-off-by: Yifeng Sun --- lib/odp-util.c | 36 +++++++++++++++++++++++++++++------- tests/odp.at | 9 +++++++++ 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/lib/odp-util.c b/lib/odp-util.c index f50de7fd275c..627baaa397ed 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c @@ -57,8 +57,15 @@ VLOG_DEFINE_THIS_MODULE(odp_util); static const char *delimiters = ", \t\r\n"; static const char *delimiters_end = ", \t\r\n)"; -static int parse_odp_key_mask_attr(const char *, const struct simap *port_names, - struct ofpbuf *, struct ofpbuf *); +#define MAX_ODP_NESTED 32 + +struct parse_odp_context { + const struct simap *port_names; + int depth; /* Current nested depth of odp string. */ +}; + +static int parse_odp_key_mask_attr(struct parse_odp_context *, const char *, + struct ofpbuf *, struct ofpbuf *); static void format_odp_key_attr(const struct nlattr *a, const struct nlattr *ma, const struct hmap *portno_names, struct ds *ds, @@ -2216,9 +2223,12 @@ parse_odp_action(const char *s, const struct simap *port_names, struct ofpbuf maskbuf = OFPBUF_STUB_INITIALIZER(mask); struct nlattr *nested, *key; size_t size; + struct parse_odp_context context = (struct parse_odp_context) { + .port_names = port_names, + }; start_ofs = nl_msg_start_nested(actions, OVS_ACTION_ATTR_SET); - retval = parse_odp_key_mask_attr(s + 4, port_names, actions, &maskbuf); + retval = parse_odp_key_mask_attr(&context, s + 4, actions, &maskbuf); if (retval < 0) { ofpbuf_uninit(&maskbuf); return retval; @@ -5268,7 +5278,8 @@ erspan_to_attr(struct ofpbuf *a, const void *data_) /* scan_port needs one extra argument. */ #define SCAN_SINGLE_PORT(NAME, TYPE, ATTR) \ SCAN_BEGIN(NAME, TYPE) { \ - len = scan_port(s, &skey, &smask, port_names); \ + len = scan_port(s, &skey, &smask, \ + context->port_names); \ if (len == 0) { \ return -EINVAL; \ } \ @@ -5404,7 +5415,7 @@ parse_odp_nsh_key_mask_attr(const char *s, struct ofpbuf *key, } static int -parse_odp_key_mask_attr(const char *s, const struct simap *port_names, +parse_odp_key_mask_attr(struct parse_odp_context *context, const char *s, struct ofpbuf *key, struct ofpbuf *mask) { SCAN_SINGLE("skb_priority(", uint32_t, u32, OVS_KEY_ATTR_PRIORITY); @@ -5557,6 +5568,11 @@ parse_odp_key_mask_attr(const char *s, const struct simap *port_names, const char *start = s; size_t encap, encap_mask = 0; + if (context->depth + 1 == MAX_ODP_NESTED) { + return -EINVAL; + } + context->depth++; + encap = nl_msg_start_nested(key, OVS_KEY_ATTR_ENCAP); if (mask) { encap_mask = nl_msg_start_nested(mask, OVS_KEY_ATTR_ENCAP); @@ -5568,13 +5584,15 @@ parse_odp_key_mask_attr(const char *s, const struct simap *port_names, s += strspn(s, delimiters); if (!*s) { + context->depth--; return -EINVAL; } else if (*s == ')') { break; } - retval = parse_odp_key_mask_attr(s, port_names, key, mask); + retval = parse_odp_key_mask_attr(context, s, key, mask); if (retval < 0) { + context->depth--; return retval; } s += retval; @@ -5585,6 +5603,7 @@ parse_odp_key_mask_attr(const char *s, const struct simap *port_names, if (mask) { nl_msg_end_nested(mask, encap_mask); } + context->depth--; return s - start; } @@ -5611,6 +5630,9 @@ odp_flow_from_string(const char *s, const struct simap *port_names, struct ofpbuf *key, struct ofpbuf *mask) { const size_t old_size = key->size; + struct parse_odp_context context = (struct parse_odp_context) { + .port_names = port_names, + }; for (;;) { int retval; @@ -5630,7 +5652,7 @@ odp_flow_from_string(const char *s, const struct simap *port_names, s += s[0] == ' ' ? 1 : 0; } - retval = parse_odp_key_mask_attr(s, port_names, key, mask); + retval = parse_odp_key_mask_attr(&context, s, key, mask); if (retval < 0) { key->size = old_size; return -retval; diff --git a/tests/odp.at b/tests/odp.at index aad89e80aee2..1cff727aead6 100644 --- a/tests/odp.at +++ b/tests/odp.at @@ -394,3 +394,12 @@ AT_CHECK([echo 'encap_nsh@:{@' | ovstest test-odp parse-actions odp_actions_from_string: error ]) AT_CLEANUP + +AT_SETUP([OVS datapath keys parsing and formatting - 33 nested encap ]) +AT_DATA([odp-in.txt], [dnl +encap(encap(encap(encap(encap(encap(encap(encap(encap(encap(encap(encap(encap(encap(encap(encap(encap(encap(encap(encap(encap(encap(encap(encap(encap(encap(encap(encap(encap(encap(encap(encap(encap())))))))))))))))))))))))))))))))) +]) +AT_CHECK_UNQUOTED([ovstest test-odp parse-keys < odp-in.txt], [0], [dnl +odp_flow_from_string: error +]) +AT_CLEANUP