Skip to content

Commit 6943588

Browse files
committed
Merge tag 'xfs-6.5-fixes-1' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux
Pull xfs fixes from Darrick Wong: "Flexarray declaration conversions. This probably should've been done with the merge window open, but I was not aware that the UBSAN knob would be getting turned up for 6.5, and the fstests failures due to the kernel warnings are getting in the way of testing. Summary: - Convert all the array[1] declarations into the accepted flex array[] declarations so that UBSAN and friends will not get confused" * tag 'xfs-6.5-fixes-1' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux: xfs: convert flex-array declarations in xfs attr shortform objects xfs: convert flex-array declarations in xfs attr leaf blocks xfs: convert flex-array declarations in struct xfs_attrlist*
2 parents 4667025 + f6250e2 commit 6943588

File tree

3 files changed

+71
-13
lines changed

3 files changed

+71
-13
lines changed

fs/xfs/libxfs/xfs_da_format.h

Lines changed: 66 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -591,7 +591,7 @@ struct xfs_attr_shortform {
591591
uint8_t valuelen; /* actual length of value (no NULL) */
592592
uint8_t flags; /* flags bits (see xfs_attr_leaf.h) */
593593
uint8_t nameval[]; /* name & value bytes concatenated */
594-
} list[1]; /* variable sized array */
594+
} list[]; /* variable sized array */
595595
};
596596

597597
typedef struct xfs_attr_leaf_map { /* RLE map of free bytes */
@@ -620,19 +620,29 @@ typedef struct xfs_attr_leaf_entry { /* sorted on key, not name */
620620
typedef struct xfs_attr_leaf_name_local {
621621
__be16 valuelen; /* number of bytes in value */
622622
__u8 namelen; /* length of name bytes */
623-
__u8 nameval[1]; /* name/value bytes */
623+
/*
624+
* In Linux 6.5 this flex array was converted from nameval[1] to
625+
* nameval[]. Be very careful here about extra padding at the end;
626+
* see xfs_attr_leaf_entsize_local() for details.
627+
*/
628+
__u8 nameval[]; /* name/value bytes */
624629
} xfs_attr_leaf_name_local_t;
625630

626631
typedef struct xfs_attr_leaf_name_remote {
627632
__be32 valueblk; /* block number of value bytes */
628633
__be32 valuelen; /* number of bytes in value */
629634
__u8 namelen; /* length of name bytes */
630-
__u8 name[1]; /* name bytes */
635+
/*
636+
* In Linux 6.5 this flex array was converted from name[1] to name[].
637+
* Be very careful here about extra padding at the end; see
638+
* xfs_attr_leaf_entsize_remote() for details.
639+
*/
640+
__u8 name[]; /* name bytes */
631641
} xfs_attr_leaf_name_remote_t;
632642

633643
typedef struct xfs_attr_leafblock {
634644
xfs_attr_leaf_hdr_t hdr; /* constant-structure header block */
635-
xfs_attr_leaf_entry_t entries[1]; /* sorted on key, not name */
645+
xfs_attr_leaf_entry_t entries[]; /* sorted on key, not name */
636646
/*
637647
* The rest of the block contains the following structures after the
638648
* leaf entries, growing from the bottom up. The variables are never
@@ -664,7 +674,7 @@ struct xfs_attr3_leaf_hdr {
664674

665675
struct xfs_attr3_leafblock {
666676
struct xfs_attr3_leaf_hdr hdr;
667-
struct xfs_attr_leaf_entry entries[1];
677+
struct xfs_attr_leaf_entry entries[];
668678

669679
/*
670680
* The rest of the block contains the following structures after the
@@ -747,14 +757,61 @@ xfs_attr3_leaf_name_local(xfs_attr_leafblock_t *leafp, int idx)
747757
*/
748758
static inline int xfs_attr_leaf_entsize_remote(int nlen)
749759
{
750-
return round_up(sizeof(struct xfs_attr_leaf_name_remote) - 1 +
751-
nlen, XFS_ATTR_LEAF_NAME_ALIGN);
760+
/*
761+
* Prior to Linux 6.5, struct xfs_attr_leaf_name_remote ended with
762+
* name[1], which was used as a flexarray. The layout of this struct
763+
* is 9 bytes of fixed-length fields followed by a __u8 flex array at
764+
* offset 9.
765+
*
766+
* On most architectures, struct xfs_attr_leaf_name_remote had two
767+
* bytes of implicit padding at the end of the struct to make the
768+
* struct length 12. After converting name[1] to name[], there are
769+
* three implicit padding bytes and the struct size remains 12.
770+
* However, there are compiler configurations that do not add implicit
771+
* padding at all (m68k) and have been broken for years.
772+
*
773+
* This entsize computation historically added (the xattr name length)
774+
* to (the padded struct length - 1) and rounded that sum up to the
775+
* nearest multiple of 4 (NAME_ALIGN). IOWs, round_up(11 + nlen, 4).
776+
* This is encoded in the ondisk format, so we cannot change this.
777+
*
778+
* Compute the entsize from offsetof of the flexarray and manually
779+
* adding bytes for the implicit padding.
780+
*/
781+
const size_t remotesize =
782+
offsetof(struct xfs_attr_leaf_name_remote, name) + 2;
783+
784+
return round_up(remotesize + nlen, XFS_ATTR_LEAF_NAME_ALIGN);
752785
}
753786

754787
static inline int xfs_attr_leaf_entsize_local(int nlen, int vlen)
755788
{
756-
return round_up(sizeof(struct xfs_attr_leaf_name_local) - 1 +
757-
nlen + vlen, XFS_ATTR_LEAF_NAME_ALIGN);
789+
/*
790+
* Prior to Linux 6.5, struct xfs_attr_leaf_name_local ended with
791+
* nameval[1], which was used as a flexarray. The layout of this
792+
* struct is 3 bytes of fixed-length fields followed by a __u8 flex
793+
* array at offset 3.
794+
*
795+
* struct xfs_attr_leaf_name_local had zero bytes of implicit padding
796+
* at the end of the struct to make the struct length 4. On most
797+
* architectures, after converting nameval[1] to nameval[], there is
798+
* one implicit padding byte and the struct size remains 4. However,
799+
* there are compiler configurations that do not add implicit padding
800+
* at all (m68k) and would break.
801+
*
802+
* This entsize computation historically added (the xattr name and
803+
* value length) to (the padded struct length - 1) and rounded that sum
804+
* up to the nearest multiple of 4 (NAME_ALIGN). IOWs, the formula is
805+
* round_up(3 + nlen + vlen, 4). This is encoded in the ondisk format,
806+
* so we cannot change this.
807+
*
808+
* Compute the entsize from offsetof of the flexarray and manually
809+
* adding bytes for the implicit padding.
810+
*/
811+
const size_t localsize =
812+
offsetof(struct xfs_attr_leaf_name_local, nameval);
813+
814+
return round_up(localsize + nlen + vlen, XFS_ATTR_LEAF_NAME_ALIGN);
758815
}
759816

760817
static inline int xfs_attr_leaf_entsize_local_max(int bsize)

fs/xfs/libxfs/xfs_fs.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -592,12 +592,12 @@ typedef struct xfs_attrlist_cursor {
592592
struct xfs_attrlist {
593593
__s32 al_count; /* number of entries in attrlist */
594594
__s32 al_more; /* T/F: more attrs (do call again) */
595-
__s32 al_offset[1]; /* byte offsets of attrs [var-sized] */
595+
__s32 al_offset[]; /* byte offsets of attrs [var-sized] */
596596
};
597597

598598
struct xfs_attrlist_ent { /* data from attr_list() */
599599
__u32 a_valuelen; /* number bytes in value of attr */
600-
char a_name[1]; /* attr name (NULL terminated) */
600+
char a_name[]; /* attr name (NULL terminated) */
601601
};
602602

603603
typedef struct xfs_fsop_attrlist_handlereq {

fs/xfs/xfs_ondisk.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ xfs_check_ondisk_structs(void)
5656

5757
/* dir/attr trees */
5858
XFS_CHECK_STRUCT_SIZE(struct xfs_attr3_leaf_hdr, 80);
59-
XFS_CHECK_STRUCT_SIZE(struct xfs_attr3_leafblock, 88);
59+
XFS_CHECK_STRUCT_SIZE(struct xfs_attr3_leafblock, 80);
6060
XFS_CHECK_STRUCT_SIZE(struct xfs_attr3_rmt_hdr, 56);
6161
XFS_CHECK_STRUCT_SIZE(struct xfs_da3_blkinfo, 56);
6262
XFS_CHECK_STRUCT_SIZE(struct xfs_da3_intnode, 64);
@@ -88,7 +88,8 @@ xfs_check_ondisk_structs(void)
8888
XFS_CHECK_OFFSET(xfs_attr_leaf_name_remote_t, valuelen, 4);
8989
XFS_CHECK_OFFSET(xfs_attr_leaf_name_remote_t, namelen, 8);
9090
XFS_CHECK_OFFSET(xfs_attr_leaf_name_remote_t, name, 9);
91-
XFS_CHECK_STRUCT_SIZE(xfs_attr_leafblock_t, 40);
91+
XFS_CHECK_STRUCT_SIZE(xfs_attr_leafblock_t, 32);
92+
XFS_CHECK_STRUCT_SIZE(struct xfs_attr_shortform, 4);
9293
XFS_CHECK_OFFSET(struct xfs_attr_shortform, hdr.totsize, 0);
9394
XFS_CHECK_OFFSET(struct xfs_attr_shortform, hdr.count, 2);
9495
XFS_CHECK_OFFSET(struct xfs_attr_shortform, list[0].namelen, 4);

0 commit comments

Comments
 (0)