bcachefs: Initialize padding space after alloc bkey
authorJustin Husted <sigstop@gmail.com>
Sat, 12 Oct 2019 00:20:30 +0000 (17:20 -0700)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:08:30 +0000 (17:08 -0400)
Packed bkeys are padded up to 64 bit alignment, but the alloc bkey type
was not clearing the pad bytes after the last data byte. This left the
key possibly containing some random garbage at the end.

This problem was found using valgrind.

This patch also changes a path with the inode bkey to clear in the same
way.

Signed-off-by: Justin Husted <sigstop@gmail.com>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/alloc_background.c
fs/bcachefs/inode.c
fs/bcachefs/util.h

index 7d5d94dbc64f1590c7eece7f6dc6f6fdc934cfc6..7b9079a740efd81035becad45d04a9f26e354904 100644 (file)
@@ -152,6 +152,7 @@ void bch2_alloc_pack(struct bkey_i_alloc *dst,
 {
        unsigned idx = 0;
        void *d = dst->v.data;
+       unsigned bytes;
 
        dst->v.fields   = 0;
        dst->v.gen      = src.gen;
@@ -160,7 +161,9 @@ void bch2_alloc_pack(struct bkey_i_alloc *dst,
        BCH_ALLOC_FIELDS()
 #undef  x
 
-       set_bkey_val_bytes(&dst->k, (void *) d - (void *) &dst->v);
+       bytes = (void *) d - (void *) &dst->v;
+       set_bkey_val_bytes(&dst->k, bytes);
+       memset_u64s_tail(&dst->v, 0, bytes);
 }
 
 static unsigned bch_alloc_val_u64s(const struct bch_alloc *a)
index b0e670cc9d0f3a76c067e394da6a19ce48ad549c..67555db01dc47bbcf6bb5de75933100487493a1e 100644 (file)
@@ -95,6 +95,7 @@ void bch2_inode_pack(struct bkey_inode_buf *packed,
        u8 *end = (void *) &packed[1];
        u8 *last_nonzero_field = out;
        unsigned nr_fields = 0, last_nonzero_fieldnr = 0;
+       unsigned bytes;
 
        bkey_inode_init(&packed->inode.k_i);
        packed->inode.k.p.inode         = inode->bi_inum;
@@ -117,10 +118,9 @@ void bch2_inode_pack(struct bkey_inode_buf *packed,
        out = last_nonzero_field;
        nr_fields = last_nonzero_fieldnr;
 
-       set_bkey_val_bytes(&packed->inode.k, out - (u8 *) &packed->inode.v);
-       memset(out, 0,
-              (u8 *) &packed->inode.v +
-              bkey_val_bytes(&packed->inode.k) - out);
+       bytes = out - (u8 *) &packed->inode.v;
+       set_bkey_val_bytes(&packed->inode.k, bytes);
+       memset_u64s_tail(&packed->inode.v, 0, bytes);
 
        SET_INODE_NR_FIELDS(&packed->inode.v, nr_fields);
 
index 965b6dd73bfa565e32752ce917a97c0aad7514f4..33589362f5df4265b38c09d3afecf7e94a4e1b4e 100644 (file)
@@ -648,6 +648,14 @@ static inline void memmove_u64s(void *dst, const void *src,
                __memmove_u64s_up(dst, src, u64s);
 }
 
+/* Set the last few bytes up to a u64 boundary given an offset into a buffer. */
+static inline void memset_u64s_tail(void *s, int c, unsigned bytes)
+{
+       unsigned rem = round_up(bytes, sizeof(u64)) - bytes;
+
+       memset(s + bytes, c, rem);
+}
+
 void sort_cmp_size(void *base, size_t num, size_t size,
          int (*cmp_func)(const void *, const void *, size_t),
          void (*swap_func)(void *, void *, size_t));