From: Kees Cook <keescook@chromium.org>
To: Kent Overstreet <kent.overstreet@linux.dev>
Cc: Andrew Morton <akpm@linux-foundation.org>,
Brian Foster <bfoster@redhat.com>,
kernel test robot <lkp@intel.com>,
Linux Memory Management List <linux-mm@kvack.org>,
linux-fsdevel@vger.kernel.org, linux-bcachefs@vger.kernel.org,
linux-hardening@vger.kernel.org
Subject: Re: [linux-next:master] BUILD REGRESSION df964ce9ef9fea10cf131bf6bad8658fde7956f6
Date: Sat, 30 Sep 2023 14:56:01 -0700 [thread overview]
Message-ID: <202309301403.82201B0A@keescook> (raw)
In-Reply-To: <202309301308.d22sJdaF-lkp@intel.com>
Hi Kent,
Andrew pointed this out to me, and it's a FORTIFY issue under a W=1 build:
On Sat, Sep 30, 2023 at 01:25:34PM +0800, kernel test robot wrote:
> tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git master
> branch HEAD: df964ce9ef9fea10cf131bf6bad8658fde7956f6 Add linux-next specific files for 20230929
>
> Error/Warning reports:
>
> [...]
> https://lore.kernel.org/oe-kbuild-all/202309192314.VBsjiIm5-lkp@intel.com
fs/bcachefs/extents.c: In function 'bch2_bkey_append_ptr':
include/linux/fortify-string.h:57:33: warning: writing 8 bytes into a region of size 0 [-Wstringop-overflow=]
57 | #define __underlying_memcpy __builtin_memcpy
| ^
include/linux/fortify-string.h:648:9: note: in expansion of macro '__underlying_memcpy'
648 | __underlying_##op(p, q, __fortify_size); \
| ^~~~~~~~~~~~~
include/linux/fortify-string.h:693:26: note: in expansion of macro '__fortify_memcpy_chk'
693 | #define memcpy(p, q, s) __fortify_memcpy_chk(p, q, s, \
| ^~~~~~~~~~~~~~~~~~~~
fs/bcachefs/extents.c:235:17: note: in expansion of macro 'memcpy'
235 | memcpy((void *) &k->v + bkey_val_bytes(&k->k),
| ^~~~~~
fs/bcachefs/bcachefs_format.h:287:33: note: destination object 'v' of size 0
287 | struct bch_val v;
| ^
The problem here is the struct bch_val is explicitly declared as a
zero-sized array, so the compiler becomes unhappy. :) Converting bch_val
to a flexible array will just kick the can down the road, since this is
going to run into -Wflex-array-member-not-at-end soon too since bch_val
overlaps with other structures:
struct bch_inode_v3 {
struct bch_val v;
__le64 bi_journal_seq;
...
};
As a container_of() target, this is fine -- leave it a zero-sized
array. The problem is using it as a destination for memcpy, etc, since
the compiler will believe it to be 0 sized. Instead, we need to impart
a type of some kind so that the compiler can actually unambiguously
reason about sizes. The memcpy() in the warning is targeting bch_val,
so I think the best fix is to correctly handle the different types.
So just to have everything in front of me, here's a summary of what I'm
seeing in the code:
struct bkey {
/* Size of combined key and value, in u64s */
__u8 u64s;
...
};
/* Empty placeholder struct, for container_of() */
struct bch_val {
__u64 __nothing[0];
};
struct bkey_i {
__u64 _data[0];
struct bkey k;
struct bch_val v;
};
static inline void bch2_bkey_append_ptr(struct bkey_i *k, struct bch_extent_ptr ptr)
{
EBUG_ON(bch2_bkey_has_device(bkey_i_to_s(k), ptr.dev));
switch (k->k.type) {
case KEY_TYPE_btree_ptr:
case KEY_TYPE_btree_ptr_v2:
case KEY_TYPE_extent:
EBUG_ON(bkey_val_u64s(&k->k) >= BKEY_EXTENT_VAL_U64s_MAX);
ptr.type = 1 << BCH_EXTENT_ENTRY_ptr;
memcpy((void *) &k->v + bkey_val_bytes(&k->k),
&ptr,
sizeof(ptr));
k->k.u64s++;
break;
default:
BUG();
}
}
So this is appending u64s into the region that start with bkey_i. Could
this gain a u64 flexible array?
struct bkey_i {
__u64 _data[0];
struct bkey k;
struct bch_val v;
__u64 ptrs[];
};
Then the memcpy() could be just a direct assignment:
k->ptrs[bkey_val_u64s(&k->k)] = (u64)ptr;
k->k.u64s++;
Alternatively, perhaps struct bkey could be the one to grow this flexible
array, and then it could eventually be tracked with __counted_by (but
not today since it expects to count the array element count, not a whole
struct size):
struct bkey {
/* Size of combined key and value, in u64s */
__u8 u64s;
...
__u64 data[] __counted_by(.u64s - BKEY_U64s);
};
And bch_val could be dropped...
Then the memcpy becomes:
k->k.u64s++;
k->k.data[bkey_val_u64s(&k->k)] = (u64)ptr;
It just seems like there is a lot of work happening that could really
just type casting or unions...
What do you think?
--
Kees Cook
next prev parent reply other threads:[~2023-09-30 21:56 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-09-30 5:25 [linux-next:master] BUILD REGRESSION df964ce9ef9fea10cf131bf6bad8658fde7956f6 kernel test robot
2023-09-30 21:56 ` Kees Cook [this message]
2023-10-02 3:22 ` Kent Overstreet
2023-10-02 4:52 ` Kees Cook
2023-10-03 13:27 ` Kent Overstreet
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=202309301403.82201B0A@keescook \
--to=keescook@chromium.org \
--cc=akpm@linux-foundation.org \
--cc=bfoster@redhat.com \
--cc=kent.overstreet@linux.dev \
--cc=linux-bcachefs@vger.kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-hardening@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=lkp@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).