Received: by 2002:a25:ad19:0:0:0:0:0 with SMTP id y25csp3051827ybi; Tue, 2 Jul 2019 01:10:58 -0700 (PDT) X-Google-Smtp-Source: APXvYqwdCCnnmKrlryaLAWqzGYdMhyzTWSjtBnAyIv3MONaQIeihHEV4oo9QnCPxNJD60Sc3/7AX X-Received: by 2002:a63:f342:: with SMTP id t2mr27454518pgj.83.1562055057855; Tue, 02 Jul 2019 01:10:57 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1562055057; cv=none; d=google.com; s=arc-20160816; b=cP15ShX6DCcMcRdm1ANpU3zs8mdM7rotkpyGAz+UhzH1QoCmTzf0IB0A0/jsST/HUX lGDwkbswmwhchUeHM2CUaYKG5hndq0+CPW1ty1qWdeDIMLQ8LJk8vl0oEXkS3Zaixowi jGpwJ//y1ukmXiGWjG45dv7QZ4Qi1aMjeE4KvVQ8i0nKD9C5kABNvT0M7gFvQQXt/ftf gNd41RTAWV33hUkluYb0k++j7ww8YUzYQe4x9Lo0F4tkRTq6VB9sFjO7f+BMqWYQTDcW hhd928nGYazn7M/JpvMOEyKcYBJKixpYp9bM4PxoZlZDjn9Bk67EI7c9X9z+vwpKrbdz 5yNw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=Dva31ejOsSgnY7rWPwqgqW2tQbHY71I9BAiN+Ht/qd8=; b=XXTTMy1Ll/FdxgHEQR0wRl4cSBKJ51HPCfWlyvc2S0Rv/Pme7EWWrNpP73foxXFcWf 874/Nk+CvgdgUVgCaE7TwTdGkT+zafZZLOWDau1jdq/Yxkwg/sbNiqjgvvchYuudlZdY OSypGyJzxTbFsz0yd7YDwAUPgEqweSHkBDT1Ein6SibIUQrMLx9e+zzWqaMsPYtD9L2E kKs0WVeLSrDkqRiHh6KtSDAWSp/Jki5Y7KaNcN9WhDNtYvAFBeq8ARtgscivNcHOip6g scRZLHFcAZcUXUMOI1nfDAnX+dhIlqbUrMu+ghs0obtn06nWGUMK5R59lTKhtBqMSoTp S8NA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=cRImkELO; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id j63si5866319pgd.493.2019.07.02.01.10.43; Tue, 02 Jul 2019 01:10:57 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=cRImkELO; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728420AbfGBIIW (ORCPT + 99 others); Tue, 2 Jul 2019 04:08:22 -0400 Received: from mail.kernel.org ([198.145.29.99]:55834 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728399AbfGBIIT (ORCPT ); Tue, 2 Jul 2019 04:08:19 -0400 Received: from localhost (83-86-89-107.cable.dynamic.v4.ziggo.nl [83.86.89.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id A74AB2184B; Tue, 2 Jul 2019 08:08:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1562054898; bh=14ukgQom7JtUl1cIW/opqbVyCji9tdCo6pVFLxIp2SI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=cRImkELOFgB/iEYf948xU4czDzMOw/wXk4HFj0eLG9kcR6k9fNIZaKU3BJOSP47VJ /ZlfetkjFLxxIg+tSfdcWyCxqi3y4FlPabYQp9oZFCb/cn8VhpzEJBaD6KKBRM5jSd S72siOR/pc+Tz1AHYQO6z9egV99LoY4X9tSriW78= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Jonathan Lemon , Martin KaFai Lau , Daniel Borkmann Subject: [PATCH 4.19 63/72] bpf: lpm_trie: check left child of last leftmost node for NULL Date: Tue, 2 Jul 2019 10:02:04 +0200 Message-Id: <20190702080127.900689440@linuxfoundation.org> X-Mailer: git-send-email 2.22.0 In-Reply-To: <20190702080124.564652899@linuxfoundation.org> References: <20190702080124.564652899@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Jonathan Lemon commit da2577fdd0932ea4eefe73903f1130ee366767d2 upstream. If the leftmost parent node of the tree has does not have a child on the left side, then trie_get_next_key (and bpftool map dump) will not look at the child on the right. This leads to the traversal missing elements. Lookup is not affected. Update selftest to handle this case. Reproducer: bpftool map create /sys/fs/bpf/lpm type lpm_trie key 6 \ value 1 entries 256 name test_lpm flags 1 bpftool map update pinned /sys/fs/bpf/lpm key 8 0 0 0 0 0 value 1 bpftool map update pinned /sys/fs/bpf/lpm key 16 0 0 0 0 128 value 2 bpftool map dump pinned /sys/fs/bpf/lpm Returns only 1 element. (2 expected) Fixes: b471f2f1de8b ("bpf: implement MAP_GET_NEXT_KEY command for LPM_TRIE") Signed-off-by: Jonathan Lemon Acked-by: Martin KaFai Lau Signed-off-by: Daniel Borkmann Signed-off-by: Greg Kroah-Hartman --- kernel/bpf/lpm_trie.c | 9 ++++-- tools/testing/selftests/bpf/test_lpm_map.c | 41 ++++++++++++++++++++++++++--- 2 files changed, 45 insertions(+), 5 deletions(-) --- a/kernel/bpf/lpm_trie.c +++ b/kernel/bpf/lpm_trie.c @@ -676,9 +676,14 @@ find_leftmost: * have exact two children, so this function will never return NULL. */ for (node = search_root; node;) { - if (!(node->flags & LPM_TREE_NODE_FLAG_IM)) + if (node->flags & LPM_TREE_NODE_FLAG_IM) { + node = rcu_dereference(node->child[0]); + } else { next_node = node; - node = rcu_dereference(node->child[0]); + node = rcu_dereference(node->child[0]); + if (!node) + node = rcu_dereference(next_node->child[1]); + } } do_copy: next_key->prefixlen = next_node->prefixlen; --- a/tools/testing/selftests/bpf/test_lpm_map.c +++ b/tools/testing/selftests/bpf/test_lpm_map.c @@ -573,13 +573,13 @@ static void test_lpm_get_next_key(void) /* add one more element (total two) */ key_p->prefixlen = 24; - inet_pton(AF_INET, "192.168.0.0", key_p->data); + inet_pton(AF_INET, "192.168.128.0", key_p->data); assert(bpf_map_update_elem(map_fd, key_p, &value, 0) == 0); memset(key_p, 0, key_size); assert(bpf_map_get_next_key(map_fd, NULL, key_p) == 0); assert(key_p->prefixlen == 24 && key_p->data[0] == 192 && - key_p->data[1] == 168 && key_p->data[2] == 0); + key_p->data[1] == 168 && key_p->data[2] == 128); memset(next_key_p, 0, key_size); assert(bpf_map_get_next_key(map_fd, key_p, next_key_p) == 0); @@ -592,7 +592,7 @@ static void test_lpm_get_next_key(void) /* Add one more element (total three) */ key_p->prefixlen = 24; - inet_pton(AF_INET, "192.168.128.0", key_p->data); + inet_pton(AF_INET, "192.168.0.0", key_p->data); assert(bpf_map_update_elem(map_fd, key_p, &value, 0) == 0); memset(key_p, 0, key_size); @@ -628,6 +628,41 @@ static void test_lpm_get_next_key(void) assert(bpf_map_get_next_key(map_fd, key_p, next_key_p) == 0); assert(next_key_p->prefixlen == 24 && next_key_p->data[0] == 192 && next_key_p->data[1] == 168 && next_key_p->data[2] == 1); + + memcpy(key_p, next_key_p, key_size); + assert(bpf_map_get_next_key(map_fd, key_p, next_key_p) == 0); + assert(next_key_p->prefixlen == 24 && next_key_p->data[0] == 192 && + next_key_p->data[1] == 168 && next_key_p->data[2] == 128); + + memcpy(key_p, next_key_p, key_size); + assert(bpf_map_get_next_key(map_fd, key_p, next_key_p) == 0); + assert(next_key_p->prefixlen == 16 && next_key_p->data[0] == 192 && + next_key_p->data[1] == 168); + + memcpy(key_p, next_key_p, key_size); + assert(bpf_map_get_next_key(map_fd, key_p, next_key_p) == -1 && + errno == ENOENT); + + /* Add one more element (total five) */ + key_p->prefixlen = 28; + inet_pton(AF_INET, "192.168.1.128", key_p->data); + assert(bpf_map_update_elem(map_fd, key_p, &value, 0) == 0); + + memset(key_p, 0, key_size); + assert(bpf_map_get_next_key(map_fd, NULL, key_p) == 0); + assert(key_p->prefixlen == 24 && key_p->data[0] == 192 && + key_p->data[1] == 168 && key_p->data[2] == 0); + + memset(next_key_p, 0, key_size); + assert(bpf_map_get_next_key(map_fd, key_p, next_key_p) == 0); + assert(next_key_p->prefixlen == 28 && next_key_p->data[0] == 192 && + next_key_p->data[1] == 168 && next_key_p->data[2] == 1 && + next_key_p->data[3] == 128); + + memcpy(key_p, next_key_p, key_size); + assert(bpf_map_get_next_key(map_fd, key_p, next_key_p) == 0); + assert(next_key_p->prefixlen == 24 && next_key_p->data[0] == 192 && + next_key_p->data[1] == 168 && next_key_p->data[2] == 1); memcpy(key_p, next_key_p, key_size); assert(bpf_map_get_next_key(map_fd, key_p, next_key_p) == 0);