!25 backport fsck.gfs2: Fix segfault in build_and_check_metalist
From: @liyy9 Reviewed-by: @Charlie_li Signed-off-by: @Charlie_li
This commit is contained in:
commit
c54db5a2c2
173
0003-fsck.gfs2-Fix-segfault-in-build_and_check_metalist.patch
Normal file
173
0003-fsck.gfs2-Fix-segfault-in-build_and_check_metalist.patch
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
From 100c229847e8c596eeb4eb92a71e9efc755e1558 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Andrew Price <anprice@redhat.com>
|
||||||
|
Date: Fri, 18 Oct 2019 16:07:44 +0100
|
||||||
|
Subject: [PATCH] fsck.gfs2: Fix segfault in build_and_check_metalist
|
||||||
|
|
||||||
|
In unlikely circumstances, indirect pointer corruption in a 'system'
|
||||||
|
inode's metadata tree can lead to the inode block state being marked as
|
||||||
|
'free' in pass1, which causes build_and_check_metalist() to be called in
|
||||||
|
pass 2. The pass has a NULL ->check_metalist function pointer and so a
|
||||||
|
segfault occurs when build_and_check_metalist attempts to call it.
|
||||||
|
|
||||||
|
Fix the segfault by calling ->check_metalist() only when it's not NULL.
|
||||||
|
This required some refactoring to make the extra level of if-nesting
|
||||||
|
easier to implement and read.
|
||||||
|
|
||||||
|
Resolves: rhbz#1487726
|
||||||
|
|
||||||
|
Signed-off-by: Andrew Price <anprice@redhat.com>
|
||||||
|
---
|
||||||
|
gfs2/fsck/metawalk.c | 107 ++++++++++++++++++++-----------------------
|
||||||
|
gfs2/fsck/metawalk.h | 1 +
|
||||||
|
2 files changed, 50 insertions(+), 58 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c
|
||||||
|
index d256dd2f..5792be56 100644
|
||||||
|
--- a/gfs2/fsck/metawalk.c
|
||||||
|
+++ b/gfs2/fsck/metawalk.c
|
||||||
|
@@ -1210,6 +1210,51 @@ static void file_ra(struct gfs2_inode *ip, struct gfs2_buffer_head *bh,
|
||||||
|
extlen * sdp->bsize, POSIX_FADV_WILLNEED);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int do_check_metalist(struct gfs2_inode *ip, uint64_t block, int height,
|
||||||
|
+ struct gfs2_buffer_head **bhp, struct metawalk_fxns *pass)
|
||||||
|
+{
|
||||||
|
+ int was_duplicate = 0;
|
||||||
|
+ int is_valid = 1;
|
||||||
|
+ int error;
|
||||||
|
+
|
||||||
|
+ if (pass->check_metalist == NULL)
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+ error = pass->check_metalist(ip, block, bhp, height, &is_valid,
|
||||||
|
+ &was_duplicate, pass->private);
|
||||||
|
+ if (error == meta_error) {
|
||||||
|
+ stack;
|
||||||
|
+ log_info("\n");
|
||||||
|
+ log_info(_("Serious metadata error on block %"PRIu64" (0x%"PRIx64").\n"),
|
||||||
|
+ block, block);
|
||||||
|
+ return error;
|
||||||
|
+ }
|
||||||
|
+ if (error == meta_skip_further) {
|
||||||
|
+ log_info("\n");
|
||||||
|
+ log_info(_("Unrecoverable metadata error on block %"PRIu64" (0x%"PRIx64")\n"),
|
||||||
|
+ block, block);
|
||||||
|
+ log_info(_("Further metadata will be skipped.\n"));
|
||||||
|
+ return error;
|
||||||
|
+ }
|
||||||
|
+ if (!is_valid) {
|
||||||
|
+ log_debug("Skipping rejected block %"PRIu64" (0x%"PRIx64")\n", block, block);
|
||||||
|
+ if (pass->invalid_meta_is_fatal)
|
||||||
|
+ return meta_error;
|
||||||
|
+ return meta_skip_one;
|
||||||
|
+ }
|
||||||
|
+ if (was_duplicate) {
|
||||||
|
+ log_debug("Skipping duplicate %"PRIu64" (0x%"PRIx64")\n", block, block);
|
||||||
|
+ return meta_skip_one;
|
||||||
|
+ }
|
||||||
|
+ if (!valid_block_ip(ip, block)) {
|
||||||
|
+ log_debug("Skipping invalid block %"PRIu64" (0x%"PRIx64")\n", block, block);
|
||||||
|
+ if (pass->invalid_meta_is_fatal)
|
||||||
|
+ return meta_error;
|
||||||
|
+ return meta_skip_one;
|
||||||
|
+ }
|
||||||
|
+ return error;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/**
|
||||||
|
* build_and_check_metalist - check a bunch of indirect blocks
|
||||||
|
* This includes hash table blocks for directories
|
||||||
|
@@ -1229,8 +1274,8 @@ static int build_and_check_metalist(struct gfs2_inode *ip, osi_list_t *mlp,
|
||||||
|
osi_list_t *prev_list, *cur_list, *tmp;
|
||||||
|
int h, head_size, iblk_type;
|
||||||
|
uint64_t *ptr, block, *undoptr;
|
||||||
|
- int error, was_duplicate, is_valid;
|
||||||
|
int maxptrs;
|
||||||
|
+ int error;
|
||||||
|
|
||||||
|
osi_list_add(&metabh->b_altlist, &mlp[0]);
|
||||||
|
|
||||||
|
@@ -1294,65 +1339,11 @@ static int build_and_check_metalist(struct gfs2_inode *ip, osi_list_t *mlp,
|
||||||
|
continue;
|
||||||
|
|
||||||
|
block = be64_to_cpu(*ptr);
|
||||||
|
- was_duplicate = 0;
|
||||||
|
- error = pass->check_metalist(ip, block, &nbh,
|
||||||
|
- h, &is_valid,
|
||||||
|
- &was_duplicate,
|
||||||
|
- pass->private);
|
||||||
|
- /* check_metalist should hold any buffers
|
||||||
|
- it gets with "bread". */
|
||||||
|
- if (error == meta_error) {
|
||||||
|
- stack;
|
||||||
|
- log_info(_("\nSerious metadata "
|
||||||
|
- "error on block %llu "
|
||||||
|
- "(0x%llx).\n"),
|
||||||
|
- (unsigned long long)block,
|
||||||
|
- (unsigned long long)block);
|
||||||
|
+ error = do_check_metalist(ip, block, h, &nbh, pass);
|
||||||
|
+ if (error == meta_error || error == meta_skip_further)
|
||||||
|
goto error_undo;
|
||||||
|
- }
|
||||||
|
- if (error == meta_skip_further) {
|
||||||
|
- log_info(_("\nUnrecoverable metadata "
|
||||||
|
- "error on block %llu "
|
||||||
|
- "(0x%llx). Further metadata"
|
||||||
|
- " will be skipped.\n"),
|
||||||
|
- (unsigned long long)block,
|
||||||
|
- (unsigned long long)block);
|
||||||
|
- goto error_undo;
|
||||||
|
- }
|
||||||
|
- if (!is_valid) {
|
||||||
|
- log_debug( _("Skipping rejected block "
|
||||||
|
- "%llu (0x%llx)\n"),
|
||||||
|
- (unsigned long long)block,
|
||||||
|
- (unsigned long long)block);
|
||||||
|
- if (pass->invalid_meta_is_fatal) {
|
||||||
|
- error = meta_error;
|
||||||
|
- goto error_undo;
|
||||||
|
- }
|
||||||
|
- continue;
|
||||||
|
- }
|
||||||
|
- /* Note that there's a special case in which
|
||||||
|
- we need to process the metadata block, even
|
||||||
|
- if it was a duplicate. That's for cases
|
||||||
|
- where we deleted the last reference as
|
||||||
|
- metadata. */
|
||||||
|
- if (was_duplicate) {
|
||||||
|
- log_debug( _("Skipping duplicate %llu "
|
||||||
|
- "(0x%llx)\n"),
|
||||||
|
- (unsigned long long)block,
|
||||||
|
- (unsigned long long)block);
|
||||||
|
+ if (error == meta_skip_one)
|
||||||
|
continue;
|
||||||
|
- }
|
||||||
|
- if (!valid_block_ip(ip, block)) {
|
||||||
|
- log_debug( _("Skipping invalid block "
|
||||||
|
- "%lld (0x%llx)\n"),
|
||||||
|
- (unsigned long long)block,
|
||||||
|
- (unsigned long long)block);
|
||||||
|
- if (pass->invalid_meta_is_fatal) {
|
||||||
|
- error = meta_error;
|
||||||
|
- goto error_undo;
|
||||||
|
- }
|
||||||
|
- continue;
|
||||||
|
- }
|
||||||
|
if (!nbh)
|
||||||
|
nbh = bread(ip->i_sbd, block);
|
||||||
|
osi_list_add_prev(&nbh->b_altlist, cur_list);
|
||||||
|
diff --git a/gfs2/fsck/metawalk.h b/gfs2/fsck/metawalk.h
|
||||||
|
index 119efeed..b5a037a3 100644
|
||||||
|
--- a/gfs2/fsck/metawalk.h
|
||||||
|
+++ b/gfs2/fsck/metawalk.h
|
||||||
|
@@ -39,6 +39,7 @@ enum meta_check_rc {
|
||||||
|
meta_error = -1,
|
||||||
|
meta_is_good = 0,
|
||||||
|
meta_skip_further = 1,
|
||||||
|
+ meta_skip_one = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* metawalk_fxns: function pointers to check various parts of the fs
|
||||||
|
--
|
||||||
|
2.33.0
|
||||||
|
|
||||||
@ -1,6 +1,6 @@
|
|||||||
Name: gfs2-utils
|
Name: gfs2-utils
|
||||||
Version: 3.2.0
|
Version: 3.2.0
|
||||||
Release: 7
|
Release: 8
|
||||||
Summary: Global Filesystem Utilities
|
Summary: Global Filesystem Utilities
|
||||||
|
|
||||||
License: GPLv2+ and LGPLv2+
|
License: GPLv2+ and LGPLv2+
|
||||||
@ -9,6 +9,7 @@ Source0: https://releases.pagure.org/gfs2-utils/gfs2-utils-%{version}.tar
|
|||||||
|
|
||||||
Patch0001: 0001-libgfs2-Fix-pointer-cast-byte-order-issue.patch
|
Patch0001: 0001-libgfs2-Fix-pointer-cast-byte-order-issue.patch
|
||||||
Patch0002: 0002-libgfs2-Fix-gfs-2-_log_header-metadata-description.patch
|
Patch0002: 0002-libgfs2-Fix-gfs-2-_log_header-metadata-description.patch
|
||||||
|
Patch0003: 0003-fsck.gfs2-Fix-segfault-in-build_and_check_metalist.patch
|
||||||
|
|
||||||
BuildRequires: ncurses-devel kernel-headers automake libtool zlib-devel gettext-devel
|
BuildRequires: ncurses-devel kernel-headers automake libtool zlib-devel gettext-devel
|
||||||
BuildRequires: bison flex libblkid-devel libuuid-devel check-devel
|
BuildRequires: bison flex libblkid-devel libuuid-devel check-devel
|
||||||
@ -54,6 +55,9 @@ make -C gfs2 install DESTDIR=%{buildroot}
|
|||||||
%exclude %{_mandir}/man8/gfs2_lockcapture.8.gz
|
%exclude %{_mandir}/man8/gfs2_lockcapture.8.gz
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Thu Nov 02 2023 liyuanyuan <liyuanyuan@xfusion.com> - 3.2.0-8
|
||||||
|
- fsck.gfs2: Fix segfault in build_and_check_metalist
|
||||||
|
|
||||||
* Thu Oct 26 2023 liyuanyuan <liyuanyuan@xfusion.com> - 3.2.0-7
|
* Thu Oct 26 2023 liyuanyuan <liyuanyuan@xfusion.com> - 3.2.0-7
|
||||||
- libgfs2: Fix gfs[2]_log_header metadata description
|
- libgfs2: Fix gfs[2]_log_header metadata description
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user