From: Andreas Gruenbacher <agruenba@redhat.com> stable inclusion from stable-v5.15.209 commit 3b28eb75afe520972bacc833850c2b30aa0824cd category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/15751 CVE: CVE-2026-53049 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=... -------------------------------- [ Upstream commit fe2c8d051150b90b3ccb85f89e3b1d636cb88ec8 ] Function gfs2_logd() calls the log flushing functions gfs2_ail1_start(), gfs2_ail1_wait(), and gfs2_ail1_empty() without holding sdp->sd_log_flush_lock, but these functions require exclusion against concurrent transactions. To fix that, add a non-locking __gfs2_log_flush() function. Then, in gfs2_logd(), take sdp->sd_log_flush_lock before calling the above mentioned log flushing functions and __gfs2_log_flush(). Fixes: 5e4c7632aae1c ("gfs2: Issue revokes more intelligently") Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> Signed-off-by: Sasha Levin <sashal@kernel.org> Conflicts: fs/gfs2/log.c [context conflicts] Signed-off-by: Zhang Kunbo <zhangkunbo@huawei.com> --- fs/gfs2/log.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c index 7473b894e3c6..20f0e8fee25b 100644 --- a/fs/gfs2/log.c +++ b/fs/gfs2/log.c @@ -950,19 +950,19 @@ static void trans_drain(struct gfs2_trans *tr) } /** - * gfs2_log_flush - flush incore transaction(s) + * __gfs2_log_flush - flush incore transaction(s) * @sdp: the filesystem * @gl: The glock structure to flush. If NULL, flush the whole incore log * @flags: The log header flags: GFS2_LOG_HEAD_FLUSH_* and debug flags * */ -void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, u32 flags) +static void __gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, + u32 flags) { struct gfs2_trans *tr = NULL; enum gfs2_freeze_state state = atomic_read(&sdp->sd_freeze_state); - down_write(&sdp->sd_log_flush_lock); /* * Do this check while holding the log_flush_lock to prevent new @@ -1052,7 +1052,6 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, u32 flags) out_end: trace_gfs2_log_flush(sdp, 0, flags); out: - up_write(&sdp->sd_log_flush_lock); gfs2_trans_free(sdp, tr); if (gfs2_withdrawing(sdp)) gfs2_withdraw(sdp); @@ -1075,6 +1074,13 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, u32 flags) goto out_end; } +void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, u32 flags) +{ + down_write(&sdp->sd_log_flush_lock); + __gfs2_log_flush(sdp, gl, flags); + up_write(&sdp->sd_log_flush_lock); +} + /** * gfs2_merge_trans - Merge a new transaction into a cached transaction * @old: Original transaction to be expanded @@ -1233,19 +1239,25 @@ int gfs2_logd(void *data) did_flush = false; if (gfs2_jrnl_flush_reqd(sdp) || t == 0) { + down_write(&sdp->sd_log_flush_lock); gfs2_ail1_empty(sdp, 0); - gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL | - GFS2_LFC_LOGD_JFLUSH_REQD); + __gfs2_log_flush(sdp, NULL, + GFS2_LOG_HEAD_FLUSH_NORMAL | + GFS2_LFC_LOGD_JFLUSH_REQD); did_flush = true; + up_write(&sdp->sd_log_flush_lock); } if (gfs2_ail_flush_reqd(sdp)) { + down_write(&sdp->sd_log_flush_lock); gfs2_ail1_start(sdp); gfs2_ail1_wait(sdp); gfs2_ail1_empty(sdp, 0); - gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL | - GFS2_LFC_LOGD_AIL_FLUSH_REQD); + __gfs2_log_flush(sdp, NULL, + GFS2_LOG_HEAD_FLUSH_NORMAL | + GFS2_LFC_LOGD_AIL_FLUSH_REQD); did_flush = true; + up_write(&sdp->sd_log_flush_lock); } if (!gfs2_ail_flush_reqd(sdp) || did_flush) -- 2.34.1