]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs: fix memcpy fortify errors in EFI log format copying
authorDarrick J. Wong <djwong@kernel.org>
Fri, 18 Nov 2022 09:54:10 +0000 (10:54 +0100)
committerCarlos Maiolino <cem@kernel.org>
Mon, 21 Nov 2022 14:26:48 +0000 (15:26 +0100)
Source kernel commit: 03a7485cd701e1c08baadcf39d9592d83715e224

Starting in 6.1, CONFIG_FORTIFY_SOURCE checks the length parameter of
memcpy.  Since we're already fixing problems with BUI item copying, we
should fix it everything else.

An extra difficulty here is that the ef[id]_extents arrays are declared
as single-element arrays.  This is not the convention for flex arrays in
the modern kernel, and it causes all manner of problems with static
checking tools, since they often cannot tell the difference between a
single element array and a flex array.

So for starters, change those array[1] declarations to array[]
declarations to signal that they are proper flex arrays and adjust all
the "size-1" expressions to fit the new declaration style.

Next, refactor the xfs_efi_copy_format function to handle the copying of
the head and the flex array members separately.  While we're at it, fix
a minor validation deficiency in the recovery function.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Kees Cook <keescook@chromium.org>
Reviewed-by: Allison Henderson <allison.henderson@oracle.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
libxfs/xfs_log_format.h
logprint/log_redo.c

index b351b9dc656184369b433640b18f22992114113b..2f41fa8477c9d617117388dfd62117b9ae1d08db 100644 (file)
@@ -613,7 +613,7 @@ typedef struct xfs_efi_log_format {
        uint16_t                efi_size;       /* size of this item */
        uint32_t                efi_nextents;   /* # extents to free */
        uint64_t                efi_id;         /* efi identifier */
-       xfs_extent_t            efi_extents[1]; /* array of extents to free */
+       xfs_extent_t            efi_extents[];  /* array of extents to free */
 } xfs_efi_log_format_t;
 
 typedef struct xfs_efi_log_format_32 {
@@ -621,7 +621,7 @@ typedef struct xfs_efi_log_format_32 {
        uint16_t                efi_size;       /* size of this item */
        uint32_t                efi_nextents;   /* # extents to free */
        uint64_t                efi_id;         /* efi identifier */
-       xfs_extent_32_t         efi_extents[1]; /* array of extents to free */
+       xfs_extent_32_t         efi_extents[];  /* array of extents to free */
 } __attribute__((packed)) xfs_efi_log_format_32_t;
 
 typedef struct xfs_efi_log_format_64 {
@@ -629,7 +629,7 @@ typedef struct xfs_efi_log_format_64 {
        uint16_t                efi_size;       /* size of this item */
        uint32_t                efi_nextents;   /* # extents to free */
        uint64_t                efi_id;         /* efi identifier */
-       xfs_extent_64_t         efi_extents[1]; /* array of extents to free */
+       xfs_extent_64_t         efi_extents[];  /* array of extents to free */
 } xfs_efi_log_format_64_t;
 
 /*
@@ -642,7 +642,7 @@ typedef struct xfs_efd_log_format {
        uint16_t                efd_size;       /* size of this item */
        uint32_t                efd_nextents;   /* # of extents freed */
        uint64_t                efd_efi_id;     /* id of corresponding efi */
-       xfs_extent_t            efd_extents[1]; /* array of extents freed */
+       xfs_extent_t            efd_extents[];  /* array of extents freed */
 } xfs_efd_log_format_t;
 
 typedef struct xfs_efd_log_format_32 {
@@ -650,7 +650,7 @@ typedef struct xfs_efd_log_format_32 {
        uint16_t                efd_size;       /* size of this item */
        uint32_t                efd_nextents;   /* # of extents freed */
        uint64_t                efd_efi_id;     /* id of corresponding efi */
-       xfs_extent_32_t         efd_extents[1]; /* array of extents freed */
+       xfs_extent_32_t         efd_extents[];  /* array of extents freed */
 } __attribute__((packed)) xfs_efd_log_format_32_t;
 
 typedef struct xfs_efd_log_format_64 {
@@ -658,7 +658,7 @@ typedef struct xfs_efd_log_format_64 {
        uint16_t                efd_size;       /* size of this item */
        uint32_t                efd_nextents;   /* # of extents freed */
        uint64_t                efd_efi_id;     /* id of corresponding efi */
-       xfs_extent_64_t         efd_extents[1]; /* array of extents freed */
+       xfs_extent_64_t         efd_extents[];  /* array of extents freed */
 } xfs_efd_log_format_64_t;
 
 /*
index 1974382d2da3d9225673140202c86604a3df5191..226bc30aa4fda8a63067b26baf04b43e01e1bf8e 100644 (file)
@@ -20,9 +20,9 @@ xfs_efi_copy_format(
 {
        uint i;
        uint nextents = ((xfs_efi_log_format_t *)buf)->efi_nextents;
-       uint dst_len = sizeof(xfs_efi_log_format_t) + (nextents - 1) * sizeof(xfs_extent_t);
-       uint len32 = sizeof(xfs_efi_log_format_32_t) + (nextents - 1) * sizeof(xfs_extent_32_t);
-       uint len64 = sizeof(xfs_efi_log_format_64_t) + (nextents - 1) * sizeof(xfs_extent_64_t);
+       uint dst_len = sizeof(xfs_efi_log_format_t) + (nextents) * sizeof(xfs_extent_t);
+       uint len32 = sizeof(xfs_efi_log_format_32_t) + (nextents) * sizeof(xfs_extent_32_t);
+       uint len64 = sizeof(xfs_efi_log_format_64_t) + (nextents) * sizeof(xfs_extent_64_t);
 
        if (len == dst_len || continued) {
                memcpy((char *)dst_efi_fmt, buf, len);
@@ -86,7 +86,7 @@ xlog_print_trans_efi(
        *ptr += src_len;
 
        /* convert to native format */
-       dst_len = sizeof(xfs_efi_log_format_t) + (src_f->efi_nextents - 1) * sizeof(xfs_extent_t);
+       dst_len = sizeof(xfs_efi_log_format_t) + (src_f->efi_nextents) * sizeof(xfs_extent_t);
 
        if (continued && src_len < core_size) {
                printf(_("EFI: Not enough data to decode further\n"));
@@ -144,7 +144,7 @@ xlog_recover_print_efi(
         * Need to convert to native format.
         */
        dst_len = sizeof(xfs_efi_log_format_t) +
-               (src_f->efi_nextents - 1) * sizeof(xfs_extent_t);
+               (src_f->efi_nextents) * sizeof(xfs_extent_t);
        if ((f = (xfs_efi_log_format_t *)malloc(dst_len)) == NULL) {
                fprintf(stderr, _("%s: xlog_recover_print_efi: malloc failed\n"),
                        progname);
@@ -177,7 +177,7 @@ xlog_print_trans_efd(char **ptr, uint len)
        xfs_efd_log_format_t *f;
        xfs_efd_log_format_t lbuf;
        /* size without extents at end */
-       uint core_size = sizeof(xfs_efd_log_format_t) - sizeof(xfs_extent_t);
+       uint core_size = sizeof(xfs_efd_log_format_t);
 
        /*
         * memmove to ensure 8-byte alignment for the long longs in