Received: by 2002:a05:6a10:9e8c:0:0:0:0 with SMTP id y12csp766107pxx; Thu, 29 Oct 2020 14:02:48 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxpUWoCZPPWKXrlsRHCr4CDTopdp63juotdCn9ceU+PpSQw2bGoGekqRzzACScgKHfEMupR X-Received: by 2002:a17:907:40c0:: with SMTP id nu24mr6232583ejb.359.1604005368187; Thu, 29 Oct 2020 14:02:48 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1604005368; cv=none; d=google.com; s=arc-20160816; b=MfRqej1Pe6svL6coNjiKlUZPIYLRaRh4GrI4TjOElBLWJd1eYLqXtvDj+mpdebw1SB yyBf0CgCe5PEZkB7QI0omK7L79pcFo0AJlziXVQS3gcJXy+irr2hpjoMffvR8hW2yuPN SYGt/DEvJlRKI4TnUv5bKvKACRxXYPJ75eU6vY0j20SrcT7kaCg+/fNfZxTOaqGATEQs K5Pz4tnEAQA7YGMChRNiVbkJcl16wvLdf6c0VY0GEAS9ifYjGtCp4g6sy8Xy4vV8OnjH mi1GGL40P0tQH2F06Cy0m92PO6oJEcOmVORyH9Q1pUXHD0jhJfZv8tWE5ntdNaibrMTa qZvA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:subject:message-id:date:from:in-reply-to :references:mime-version:dkim-signature; bh=1YTlLHaZTomYHKwfcUy/D+8HN1lrU93CEOhzQLhOkog=; b=v0SUkFxTOTScmighNlKVArLmBB4BfWMvLC0PhK5WYGpewfX3Y1Fyw40++qUyyKG869 K5JBxi+knfMK44ysiuEk7ksH8beA5uy6A5e1I7kUnUESdWxV5G9afaQNE7FvNS3oK8KF LOb0Fk7xJi6eDLcaXCIigFIqnDeHdiKGv26RNRhG3tymQ3JhjOCJzYJvmlTyoSSZtAfl aM28jytc9tFZA+OFQHjCX1ZLdxTAoZFkeIZOgHtxvh+j964I1VPlH+jvt5DWVQYXSzeA qFvIvHPdJva4HW54F4Rm0rnbBQmylkqBaCrJKHKE42175WjAozKbZMFKWc72qNgjWuzj G6sA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b="h4A/ikGd"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id w18si2770272ejz.722.2020.10.29.14.02.24; Thu, 29 Oct 2020 14:02:48 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b="h4A/ikGd"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726404AbgJ2U6d (ORCPT + 99 others); Thu, 29 Oct 2020 16:58:33 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41438 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726165AbgJ2U6d (ORCPT ); Thu, 29 Oct 2020 16:58:33 -0400 Received: from mail-wr1-x443.google.com (mail-wr1-x443.google.com [IPv6:2a00:1450:4864:20::443]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E085DC0613D2 for ; Thu, 29 Oct 2020 13:58:32 -0700 (PDT) Received: by mail-wr1-x443.google.com with SMTP id k10so2920974wrw.13 for ; Thu, 29 Oct 2020 13:58:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=1YTlLHaZTomYHKwfcUy/D+8HN1lrU93CEOhzQLhOkog=; b=h4A/ikGd2x0QjnM7BDtzaj8rWGQ1JekzD++OKlsyct06sMrY3C5pG8VL6o9J0HjGKU 86vGGFoX7K3ESSlqlIkHxUuAwBJmdPPQWriM2ktZxcOnqicZ1UoYmpMfBItPsxnffeOw TUWk9SvsqD1wDQ8Y7JF8rPoRhAzk12g7YraxXs1jJvRQX4BejlnZcwcral5cANWLnFzZ PkID87RB5AvYvwGto3ATm4XuiacJ6yKdR4A6nw/5oEjb6fVc5K7URu+3llRUv0ilV/H/ nv+/OwfyM0OGf7exyNE4Gq3ETMbmkE7r5nH9SIwlKVWYhowI61B74bUh/vYgR9QNk2z3 +6kQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=1YTlLHaZTomYHKwfcUy/D+8HN1lrU93CEOhzQLhOkog=; b=qg1Pszh+HWqM+s36NxxVpE5l2U8Q/fmbWEX776W/yw8ugAWxvC2zmGHBhxWVy5ihuR HrQyjNu7n9aPf+BaCLBvuGFgkb0OWRVI9zccXfkXbaQy3VBwWAAubcIu2YC2jYITx/a6 910f7XPXK0i1ViaON/Gsh+zh+2WFLRpuPiFq4wUbnGtG35mqud6WhMR6WFuHwiuqx8gI 39hVwlnKFvsQX6vAZyC6tfY9dAdm89aT2SWrrr6dbnfyoFp6UsoJ68KaK/NdFAM5evk3 NJ/KbgMtE2oOoYUKIz4nqXRwzBEWQ+7+OYRc6xb8z5/zuJDkJGUJrzovOkykWQZ2iEyT 5OkA== X-Gm-Message-State: AOAM532R/ezT9mnQVFVCyK7gya2zk7TMMy3qm0r1eJgG3m1inP6i5Ub+ pfuQtI6oSY/MVbaLMy04mFYQiN2yr40u/FUUWB8WcQ== X-Received: by 2002:adf:f20e:: with SMTP id p14mr7739130wro.376.1604005111278; Thu, 29 Oct 2020 13:58:31 -0700 (PDT) MIME-Version: 1.0 References: <20201029160938.154084-1-irogers@google.com> In-Reply-To: From: Ian Rogers Date: Thu, 29 Oct 2020 13:58:19 -0700 Message-ID: Subject: Re: [PATCH] libbpf hashmap: Fix undefined behavior in hash_bits To: Andrii Nakryiko Cc: Alexei Starovoitov , Daniel Borkmann , Martin KaFai Lau , Song Liu , Yonghong Song , Andrii Nakryiko , John Fastabend , KP Singh , Networking , bpf , open list Content-Type: text/plain; charset="UTF-8" Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Thu, Oct 29, 2020 at 1:16 PM Andrii Nakryiko wrote: > > On Thu, Oct 29, 2020 at 9:11 AM Ian Rogers wrote: > > > > If bits is 0, the case when the map is empty, then the >> is the size of > > the register which is undefined behavior - on x86 it is the same as a > > shift by 0. Fix by handling the 0 case explicitly when running with > > address sanitizer. > > > > A variant of this patch was posted previously as: > > https://lore.kernel.org/lkml/20200508063954.256593-1-irogers@google.com/ > > > > Signed-off-by: Ian Rogers > > --- > > tools/lib/bpf/hashmap.h | 14 ++++++++++++++ > > 1 file changed, 14 insertions(+) > > > > diff --git a/tools/lib/bpf/hashmap.h b/tools/lib/bpf/hashmap.h > > index d9b385fe808c..27d0556527d3 100644 > > --- a/tools/lib/bpf/hashmap.h > > +++ b/tools/lib/bpf/hashmap.h > > @@ -12,9 +12,23 @@ > > #include > > #include > > > > +#ifdef __has_feature > > +#define HAVE_FEATURE(f) __has_feature(f) > > +#else > > +#define HAVE_FEATURE(f) 0 > > +#endif > > + > > static inline size_t hash_bits(size_t h, int bits) > > { > > /* shuffle bits and return requested number of upper bits */ > > +#if defined(ADDRESS_SANITIZER) || HAVE_FEATURE(address_sanitizer) > > + /* > > + * If the requested bits == 0 avoid undefined behavior from a > > + * greater-than bit width shift right (aka invalid-shift-exponent). > > + */ > > + if (bits == 0) > > + return -1; > > +#endif > > Oh, just too much # magic here :(... If we want to prevent hash_bits() > from being called with bits == 0 (despite the result never used), > let's just adjust hashmap__for_each_key_entry and > hashmap__for_each_key_entry_safe macros: > > diff --git a/tools/lib/bpf/hashmap.h b/tools/lib/bpf/hashmap.h > index d9b385fe808c..488e0ef236cb 100644 > --- a/tools/lib/bpf/hashmap.h > +++ b/tools/lib/bpf/hashmap.h > @@ -174,9 +174,9 @@ bool hashmap__find(const struct hashmap *map, > const void *key, void **value); > * @key: key to iterate entries for > */ > #define hashmap__for_each_key_entry(map, cur, _key) \ > - for (cur = ({ size_t bkt = hash_bits(map->hash_fn((_key), map->ctx),\ > - map->cap_bits); \ > - map->buckets ? map->buckets[bkt] : NULL; }); \ > + for (cur = map->buckets \ > + ? map->buckets[hash_bits(map->hash_fn((_key), > map->ctx), map->cap_bits)] \ > + : NULL; \ > cur; \ > cur = cur->next) \ > if (map->equal_fn(cur->key, (_key), map->ctx)) > > Either way it's a bit ugly and long, but at least we don't have extra > #-driven ugliness. This can work with the following changes in hashmap.c. I'll resend this as a whole patch. Thanks, Ian --- a/tools/lib/bpf/hashmap.c +++ b/tools/lib/bpf/hashmap.c @@ -156,7 +156,7 @@ int hashmap__insert(struct hashmap *map, const void **old_key, void **old_value) { struct hashmap_entry *entry; - size_t h; + size_t h = 0; int err; if (old_key) @@ -164,7 +164,9 @@ int hashmap__insert(struct hashmap *map, if (old_value) *old_value = NULL; - h = hash_bits(map->hash_fn(key, map->ctx), map->cap_bits); + if (map->buckets) + h = hash_bits(map->hash_fn(key, map->ctx), map->cap_bits); + if (strategy != HASHMAP_APPEND && hashmap_find_entry(map, key, h, NULL, &entry)) { if (old_key) @@ -208,6 +210,9 @@ bool hashmap__find(const struct hashmap struct hashmap_entry *entry; size_t h; + if (!map->buckets) + return false; + h = hash_bits(map->hash_fn(key, map->ctx), map->cap_bits); if (!hashmap_find_entry(map, key, h, NULL, &entry)) return false; @@ -223,6 +228,9 @@ bool hashmap__delete(struct hashmap *map struct hashmap_entry **pprev, *entry; size_t h; + if (!map->buckets) + return false; + h = hash_bits(map->hash_fn(key, map->ctx), map->cap_bits); if (!hashmap_find_entry(map, key, h, &pprev, &entry)) return false; > > #if (__SIZEOF_SIZE_T__ == __SIZEOF_LONG_LONG__) > > /* LP64 case */ > > return (h * 11400714819323198485llu) >> (__SIZEOF_LONG_LONG__ * 8 - bits); > > -- > > 2.29.1.341.ge80a0c044ae-goog > >