@@ -591,7 +591,7 @@ struct xfs_attr_shortform {
591
591
uint8_t valuelen ; /* actual length of value (no NULL) */
592
592
uint8_t flags ; /* flags bits (see xfs_attr_leaf.h) */
593
593
uint8_t nameval []; /* name & value bytes concatenated */
594
- } list [1 ]; /* variable sized array */
594
+ } list []; /* variable sized array */
595
595
};
596
596
597
597
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 */
620
620
typedef struct xfs_attr_leaf_name_local {
621
621
__be16 valuelen ; /* number of bytes in value */
622
622
__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 */
624
629
} xfs_attr_leaf_name_local_t ;
625
630
626
631
typedef struct xfs_attr_leaf_name_remote {
627
632
__be32 valueblk ; /* block number of value bytes */
628
633
__be32 valuelen ; /* number of bytes in value */
629
634
__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 */
631
641
} xfs_attr_leaf_name_remote_t ;
632
642
633
643
typedef struct xfs_attr_leafblock {
634
644
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 */
636
646
/*
637
647
* The rest of the block contains the following structures after the
638
648
* leaf entries, growing from the bottom up. The variables are never
@@ -664,7 +674,7 @@ struct xfs_attr3_leaf_hdr {
664
674
665
675
struct xfs_attr3_leafblock {
666
676
struct xfs_attr3_leaf_hdr hdr ;
667
- struct xfs_attr_leaf_entry entries [1 ];
677
+ struct xfs_attr_leaf_entry entries [];
668
678
669
679
/*
670
680
* 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)
747
757
*/
748
758
static inline int xfs_attr_leaf_entsize_remote (int nlen )
749
759
{
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 );
752
785
}
753
786
754
787
static inline int xfs_attr_leaf_entsize_local (int nlen , int vlen )
755
788
{
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 );
758
815
}
759
816
760
817
static inline int xfs_attr_leaf_entsize_local_max (int bsize )
0 commit comments