Message ID | 20230106060229.never.047-kees@kernel.org |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:4e01:0:0:0:0:0 with SMTP id p1csp665227wrt; Thu, 5 Jan 2023 22:06:14 -0800 (PST) X-Google-Smtp-Source: AMrXdXtwgAO/Rn05puVUGPNFkBwDAxfI1jvs2Td24/aVRbcV+wnSwG0I97zDtEN/JMwiQSz/AsyQ X-Received: by 2002:a17:903:1d0:b0:18f:a447:2254 with SMTP id e16-20020a17090301d000b0018fa4472254mr73209597plh.64.1672985174137; Thu, 05 Jan 2023 22:06:14 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1672985174; cv=none; d=google.com; s=arc-20160816; b=Fv/1Q3G4+ooihJcD+5TZpKrpOt97fK8vv5MwNoLvKBdNJyJx+lX5vqASCJrx//bmbX sI/ED/Gpt7uD8WIAAp7FHDV+P1LcxsMqIHM9plUifZEoO4YKaMQP/kJtdWj7iotoeJ0A elRd9pQa3V88XCCx+W3qnWz1bz20xqmFt+WJMkbXlTIT9ids1sTBJ2Sx8AKgiS1s/pDa +dQgzHdGpFII17hJjd7xkZbxaOWwEnVNofgw2aTrUr3DElMahvhr3LtMeJxb32rWzVYD jGVuF0wC2UAaXJdC2I8bq3MkVq5TWSIclG9SewMNg7fgAAmSQmwRq6z6Zc9OzoZL/V/U KkxQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :message-id:date:subject:cc:to:from:dkim-signature; bh=Y+anX43Mu+MJERuRlu4YWa+yMoYVv49RcDXznbQT8og=; b=u15f/apcAo4mXpY3eubARj6+R1txxlQEfmPdl/nVmpdLiwZGsgPCKGqE5HJ1cpWZQU nLvGqG8h5cMxPd1kDxroYBCtYkZv5cPn8e9dfSqS1AFud+2k0aWCk55T+z44xGUMSO0t zwLggY0l/7WoSGnmCW1SYYW1sy9sX1O4wI9x3xVNCOJXzLubDrbRijTDmjIexr84/FlA Pi5vUvH+9QuYFh9b1X6V2ti1JqBWp8V9o+Y9CYCUP+Ipk4SoywU8LOSfPaVRw6QSZS1p 1gUmnPEdy4nNfri0wkz0J+RgeS56wX6q9H+aAAAe0yEPBuYsasrS8CP2+qRqACm8RIKS HfcA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=TQWkY0ok; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id i8-20020a655b88000000b0049fde0f046bsi510759pgr.66.2023.01.05.22.06.01; Thu, 05 Jan 2023 22:06:14 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=TQWkY0ok; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231603AbjAFGCl (ORCPT <rfc822;tmhikaru@gmail.com> + 99 others); Fri, 6 Jan 2023 01:02:41 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49510 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230477AbjAFGCi (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Fri, 6 Jan 2023 01:02:38 -0500 Received: from mail-pj1-x102b.google.com (mail-pj1-x102b.google.com [IPv6:2607:f8b0:4864:20::102b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5B2DB6C7E4 for <linux-kernel@vger.kernel.org>; Thu, 5 Jan 2023 22:02:36 -0800 (PST) Received: by mail-pj1-x102b.google.com with SMTP id c8-20020a17090a4d0800b00225c3614161so4244972pjg.5 for <linux-kernel@vger.kernel.org>; Thu, 05 Jan 2023 22:02:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=Y+anX43Mu+MJERuRlu4YWa+yMoYVv49RcDXznbQT8og=; b=TQWkY0oklPgt/5r5cwlVo9/0J0Iztw/r7ZwqqWCfiaJ3MzTS223U360dspIUhp/6Ov W2ryG5VksV19en1B01GCNx5Blp8tkuWN9+Hcv2CBH1NjfIurxS3d/qRO6lVnW4xNySFi uEYY1OecqFbDKQA3D7PxeZ4NX0XKm5qooreVE= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=Y+anX43Mu+MJERuRlu4YWa+yMoYVv49RcDXznbQT8og=; b=XCYlykeUDPZpKjX+uxtaEgVjdnZ0uRZeyQDjSRlhDUsYjXz/msi5UKWfThsl33mmml Ea2jLwSrl4qycBWNseaKPSgIR9e0P1mXbAiroU7aX0P1A3P+QgWNZooHGF6yAlI4wT1J vAouiLh4H5h/18epBvPwar+/5HJm5PLvay37b0xtIebIxb9RlWEbIO07jXsts4To/S15 Xl9LVJPt9xj0gXm7ND2/+rC73So/JPIQyE2fzU5nTpTH7yehpLoinp25BPZzYXYMq0BA u6RMsHyBZRGMHOeF18gAF7CbWZPjvkp7PXr21hP4eZL2FPO1HjPcqKNDvuxRhVfGUyqf HZlg== X-Gm-Message-State: AFqh2kq7Z5ftBEy4Tq7z/6vSBdKC1wCKcb4WLf/xPK7oANZQ1hA9/J5s aHX+64YExm7XJfCojpCF1OQmnw== X-Received: by 2002:a05:6a20:8b89:b0:a7:a591:4fca with SMTP id m9-20020a056a208b8900b000a7a5914fcamr57145215pzh.61.1672984956350; Thu, 05 Jan 2023 22:02:36 -0800 (PST) Received: from www.outflux.net (smtp.outflux.net. [198.145.64.163]) by smtp.gmail.com with ESMTPSA id q15-20020aa7842f000000b00580e3917af7sm263876pfn.117.2023.01.05.22.02.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 05 Jan 2023 22:02:35 -0800 (PST) From: Kees Cook <keescook@chromium.org> To: Coly Li <colyli@suse.de> Cc: Kees Cook <keescook@chromium.org>, Thorsten Leemhuis <linux@leemhuis.info>, Kent Overstreet <kent.overstreet@gmail.com>, linux-bcache@vger.kernel.org, linux-kernel@vger.kernel.org, linux-hardening@vger.kernel.org Subject: [PATCH] bcache: Silence memcpy() run-time false positive warnings Date: Thu, 5 Jan 2023 22:02:33 -0800 Message-Id: <20230106060229.never.047-kees@kernel.org> X-Mailer: git-send-email 2.34.1 MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=2294; h=from:subject:message-id; bh=hTGH6NubMvHnfos0JgY0W0bCNHZlDQ5kCsJbr0ADcY0=; b=owEBbQKS/ZANAwAKAYly9N/cbcAmAcsmYgBjt7l5Xn8LxEcT24jMoUZlJV8VEac0DCWD7svpNFHI yMy3+VaJAjMEAAEKAB0WIQSlw/aPIp3WD3I+bhOJcvTf3G3AJgUCY7e5eQAKCRCJcvTf3G3AJjHiD/ 4giyGiIV4i/gX19THV5iQPRflDiE5uFQ4U5i4aNgMO4xSRe0h7fdAAd9H2hbcvQ5QMcC5Fp9x5XiYW 1d76Qh1qODHd6Xqh0TZf0nWjemG0WVgp6e1J9ELcMzOt5b6Vx6clehvCmD+ZWT94mFIiN3Lj9E1prN /H+LxGCQWt8gDOY+jJmoecUftIBPFP5EBY9nLqv8IVzNyNZUKAE+0C1psgsWC/UWyNbM2VWCxZIGr8 lbHRbNCUm/l4YNxmkrL5jRFtcnn+9LOMrJB3DGl3OdhjATJDNHMXR0i35XwwXFc8V82AC9xl/MKyGQ 8AX3wkEcq7IkJxiGfgF68iIglGoO5Q8x9HX1RScGBi9CP/abFFjI22dSqt7meoxDw+HZc+UuGvYLg9 QvxJwODOjWzl6l+Hposek0iHpSFubiB39TU2sTa+Z5UAQry2mQNBrUOh9ngYrjEXLJKo2JH4q+rCbB fzcW3YfR13fg3J+Fq7voE4mxuYzLQiG31IFiaO6W0xwL1L+ypmVouBwJ16zBiW1uH27KO909OFs9Z/ ThkVd/H8u5E1d1k6T/OP4TNRxHV1/1ljFiu6t+BpU1UtGliAIgkarWRvGdiApxpjbZmpfBUP+FWVJn bJDIE9UCb4EpRBlZAmbBuUvw6MlaZP5NWpRDumhgpLSbZhz8y8rb35MTiHog== X-Developer-Key: i=keescook@chromium.org; a=openpgp; fpr=A5C3F68F229DD60F723E6E138972F4DFDC6DC026 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1754252102286310464?= X-GMAIL-MSGID: =?utf-8?q?1754252102286310464?= |
Series |
bcache: Silence memcpy() run-time false positive warnings
|
|
Commit Message
Kees Cook
Jan. 6, 2023, 6:02 a.m. UTC
struct bkey has internal padding in a union, but it isn't always named
the same (e.g. key ## _pad, key_p, etc). This makes it extremely hard
for the compiler to reason about the available size of copies done
against such keys. Use unsafe_memcpy() for now, to silence the many
run-time false positive warnings:
memcpy: detected field-spanning write (size 264) of single field "&i->j" at drivers/md/bcache/journal.c:152 (size 240)
memcpy: detected field-spanning write (size 24) of single field "&b->key" at drivers/md/bcache/btree.c:939 (size 16)
emcpy: detected field-spanning write (size 24) of single field "&temp.key" at drivers/md/bcache/extents.c:428 (size 16)
Reported-by: Thorsten Leemhuis <linux@leemhuis.info>
Link: https://lore.kernel.org/all/19200730-a3ba-6f4f-bb81-71339bdbbf73@leemhuis.info/
Cc: Coly Li <colyli@suse.de>
Cc: Kent Overstreet <kent.overstreet@gmail.com>
Cc: linux-bcache@vger.kernel.org
Signed-off-by: Kees Cook <keescook@chromium.org>
---
drivers/md/bcache/bcache_ondisk.h | 3 ++-
drivers/md/bcache/journal.c | 3 ++-
2 files changed, 4 insertions(+), 2 deletions(-)
Comments
On 06.01.23 07:02, Kees Cook wrote: > struct bkey has internal padding in a union, but it isn't always named > the same (e.g. key ## _pad, key_p, etc). This makes it extremely hard > for the compiler to reason about the available size of copies done > against such keys. Use unsafe_memcpy() for now, to silence the many > run-time false positive warnings: > > memcpy: detected field-spanning write (size 264) of single field "&i->j" at drivers/md/bcache/journal.c:152 (size 240) > memcpy: detected field-spanning write (size 24) of single field "&b->key" at drivers/md/bcache/btree.c:939 (size 16) > emcpy: detected field-spanning write (size 24) of single field "&temp.key" at drivers/md/bcache/extents.c:428 (size 16) Thx for looking into this. > Reported-by: Thorsten Leemhuis <linux@leemhuis.info> > Link: https://lore.kernel.org/all/19200730-a3ba-6f4f-bb81-71339bdbbf73@leemhuis.info/ Credit where credit is due, this should be: Reported-by: Alexandre Pereira <alexpereira@disroot.org> Link: https://bugzilla.kernel.org/show_bug.cgi?id=216785 > Cc: Coly Li <colyli@suse.de> > […] Ciao, Thorsten
> 2023年1月6日 14:02,Kees Cook <keescook@chromium.org> 写道: > > struct bkey has internal padding in a union, but it isn't always named > the same (e.g. key ## _pad, key_p, etc). This makes it extremely hard > for the compiler to reason about the available size of copies done > against such keys. Use unsafe_memcpy() for now, to silence the many > run-time false positive warnings: > The keys is embedded in multiple data structures as a generalized model with some helpers, bkey_bytes() is one of them. It is not surprised for such feeling when people read the code at first glance. And thank you for improving it :-) > memcpy: detected field-spanning write (size 264) of single field "&i->j" at drivers/md/bcache/journal.c:152 (size 240) > memcpy: detected field-spanning write (size 24) of single field "&b->key" at drivers/md/bcache/btree.c:939 (size 16) > emcpy: detected field-spanning write (size 24) of single field "&temp.key" at drivers/md/bcache/extents.c:428 (size 16) > How does the above information can be founded? Should I use llvm and enable FORTIFY_SOURCE? I don’t say the bkey and bkey_bytes() stuffs are elegant, but why the compiler cannot find such situation? IMHO it is quite similar to something like “struct foo *bar[0]” at the end of a data structure. > Reported-by: Thorsten Leemhuis <linux@leemhuis.info> > Link: https://lore.kernel.org/all/19200730-a3ba-6f4f-bb81-71339bdbbf73@leemhuis.info/ > Cc: Coly Li <colyli@suse.de> > Cc: Kent Overstreet <kent.overstreet@gmail.com> > Cc: linux-bcache@vger.kernel.org > Signed-off-by: Kees Cook <keescook@chromium.org> The code comments as justification is informative. Thanks for this. Acked-by: Coly Li <colyli@suse.de> Coly Li > --- > drivers/md/bcache/bcache_ondisk.h | 3 ++- > drivers/md/bcache/journal.c | 3 ++- > 2 files changed, 4 insertions(+), 2 deletions(-) > > diff --git a/drivers/md/bcache/bcache_ondisk.h b/drivers/md/bcache/bcache_ondisk.h > index d086a0ce4bc2..6620a7f8fffc 100644 > --- a/drivers/md/bcache/bcache_ondisk.h > +++ b/drivers/md/bcache/bcache_ondisk.h > @@ -106,7 +106,8 @@ static inline unsigned long bkey_bytes(const struct bkey *k) > return bkey_u64s(k) * sizeof(__u64); > } > > -#define bkey_copy(_dest, _src) memcpy(_dest, _src, bkey_bytes(_src)) > +#define bkey_copy(_dest, _src) unsafe_memcpy(_dest, _src, bkey_bytes(_src), \ > + /* bkey is always padded */) > > static inline void bkey_copy_key(struct bkey *dest, const struct bkey *src) > { > diff --git a/drivers/md/bcache/journal.c b/drivers/md/bcache/journal.c > index e5da469a4235..c182c21de2e8 100644 > --- a/drivers/md/bcache/journal.c > +++ b/drivers/md/bcache/journal.c > @@ -149,7 +149,8 @@ reread: left = ca->sb.bucket_size - offset; > bytes, GFP_KERNEL); > if (!i) > return -ENOMEM; > - memcpy(&i->j, j, bytes); > + unsafe_memcpy(&i->j, j, bytes, > + /* "bytes" was calculated by set_bytes() above */); > /* Add to the location after 'where' points to */ > list_add(&i->list, where); > ret = 1; > -- > 2.34.1 >
On Fri, Jan 06, 2023 at 11:01:05AM +0100, Thorsten Leemhuis wrote: > Credit where credit is due, this should be: > > Reported-by: Alexandre Pereira <alexpereira@disroot.org> > Link: https://bugzilla.kernel.org/show_bug.cgi?id=216785 Ah-ha, thank you! I've updated this.
On Fri, Jan 06, 2023 at 09:39:16PM +0800, Coly Li wrote: > > > > 2023年1月6日 14:02,Kees Cook <keescook@chromium.org> 写道: > > > > struct bkey has internal padding in a union, but it isn't always named > > the same (e.g. key ## _pad, key_p, etc). This makes it extremely hard > > for the compiler to reason about the available size of copies done > > against such keys. Use unsafe_memcpy() for now, to silence the many > > run-time false positive warnings: > > > > The keys is embedded in multiple data structures as a generalized model with some helpers, bkey_bytes() is one of them. Yeah, if the helpers were able to operate on the padding variable (rather than the key), then the compiler would be in a better position to figure out bounds checking. Right now it sees the destination as the key and then the size as larger than the key (but equal to the union's padding variable -- but it doesn't "know" about that). > > memcpy: detected field-spanning write (size 264) of single field "&i->j" at drivers/md/bcache/journal.c:152 (size 240) > > memcpy: detected field-spanning write (size 24) of single field "&b->key" at drivers/md/bcache/btree.c:939 (size 16) > > memcpy: detected field-spanning write (size 24) of single field "&temp.key" at drivers/md/bcache/extents.c:428 (size 16) > > > > How does the above information can be founded? Should I use llvm and enable FORTIFY_SOURCE? It was reported at run-time under a kernel built with CONFIG_FORTIFY_SOURCE=y (See https://bugzilla.kernel.org/show_bug.cgi?id=216785) > I don’t say the bkey and bkey_bytes() stuffs are elegant, but why the compiler cannot find such situation? IMHO it is quite similar to something like “struct foo *bar[0]” at the end of a data structure. Nit: "bar[0]" is deprecated in favor of "bar[]" or DECLARE_FLEX_ARRAY(...) where needed, see: https://www.kernel.org/doc/html/latest/process/deprecated.html#zero-length-and-one-element-arrays and here is the patch that fixes this: https://lore.kernel.org/all/YzIc8z+QaHvqPjLX@work/ But to answer the question, what's happening is mostly due to a (specification?) bug in GCC and Clang (where it can't tell an outer struct contains an inner struct that ends in a flexible array), so this: struct jset { ... union { struct bkey start[0]; __u64 d[0]; }; }; looks like it has a fixed size, when in fact it doesn't. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101832 There is disagreement within GCC about whether or not this behavior is "by design", so for the meantime, we have to work around it in the kernel. So the first warning comes from: memcpy(&i->j, j, bytes); where the compiler thinks the object pointed at by "&i->j" is fixed size, as it doesn't "see" the trailing flexible arrays within j. The other 2 warnings come from the same problem, but they're from struct bkey and the union created by BKEY_PADDED(). Here's everything I could see: struct bkey { __u64 high; __u64 low; __u64 ptr[]; }; #define BKEY_PADDED(key) \ union { struct bkey key; __u64 key ## _pad[BKEY_PAD]; } #define BITMASK(name, type, field, offset, size) \ static inline __u64 name(const type *k) \ { return (k->field >> offset) & ~(~0ULL << size); } \ #define KEY_FIELD(name, field, offset, size) \ BITMASK(name, struct bkey, field, offset, size) KEY_FIELD(KEY_PTRS, high, 60, 3) static inline unsigned long bkey_u64s(const struct bkey *k) { return (sizeof(struct bkey) / sizeof(__u64)) + KEY_PTRS(k); } static inline unsigned long bkey_bytes(const struct bkey *k) { return bkey_u64s(k) * sizeof(__u64); } #define bkey_copy(_dest, _src) memcpy(_dest, _src, bkey_bytes(_src)) BKEY_PADDED(key) temp; bkey_copy(&temp.key, k); So, again, the memcpy() in bkey_copy() can't see into &temp.key to notice the trailing flexible array, and thinks it is copying "too much". However, in both cases, the bounds checking is being performed (first by set_bytes(), and in the latter two, by bkey_bytes()), so the direct fix is to just disable the FORTIFY checking on these memcpy() uses. > > Reported-by: Thorsten Leemhuis <linux@leemhuis.info> > > Link: https://lore.kernel.org/all/19200730-a3ba-6f4f-bb81-71339bdbbf73@leemhuis.info/ > > Cc: Coly Li <colyli@suse.de> > > Cc: Kent Overstreet <kent.overstreet@gmail.com> > > Cc: linux-bcache@vger.kernel.org > > Signed-off-by: Kees Cook <keescook@chromium.org> > > The code comments as justification is informative. Thanks for this. > > Acked-by: Coly Li <colyli@suse.de> Thanks! -Kees
diff --git a/drivers/md/bcache/bcache_ondisk.h b/drivers/md/bcache/bcache_ondisk.h index d086a0ce4bc2..6620a7f8fffc 100644 --- a/drivers/md/bcache/bcache_ondisk.h +++ b/drivers/md/bcache/bcache_ondisk.h @@ -106,7 +106,8 @@ static inline unsigned long bkey_bytes(const struct bkey *k) return bkey_u64s(k) * sizeof(__u64); } -#define bkey_copy(_dest, _src) memcpy(_dest, _src, bkey_bytes(_src)) +#define bkey_copy(_dest, _src) unsafe_memcpy(_dest, _src, bkey_bytes(_src), \ + /* bkey is always padded */) static inline void bkey_copy_key(struct bkey *dest, const struct bkey *src) { diff --git a/drivers/md/bcache/journal.c b/drivers/md/bcache/journal.c index e5da469a4235..c182c21de2e8 100644 --- a/drivers/md/bcache/journal.c +++ b/drivers/md/bcache/journal.c @@ -149,7 +149,8 @@ reread: left = ca->sb.bucket_size - offset; bytes, GFP_KERNEL); if (!i) return -ENOMEM; - memcpy(&i->j, j, bytes); + unsafe_memcpy(&i->j, j, bytes, + /* "bytes" was calculated by set_bytes() above */); /* Add to the location after 'where' points to */ list_add(&i->list, where); ret = 1;