]> git.ipfire.org Git - people/arne_f/kernel.git/blobdiff - fs/gfs2/log.c
gfs2: fix use-after-free on transaction ail lists
[people/arne_f/kernel.git] / fs / gfs2 / log.c
index a3208511f35aadcb44ec88673b558950a76d2efb..f30418911e1bde09eca0b1bc68f38d0b887b51cf 100644 (file)
@@ -804,8 +804,10 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl,
  * @new: New transaction to be merged
  */
 
-static void gfs2_merge_trans(struct gfs2_trans *old, struct gfs2_trans *new)
+static void gfs2_merge_trans(struct gfs2_sbd *sdp, struct gfs2_trans *new)
 {
+       struct gfs2_trans *old = sdp->sd_log_tr;
+
        WARN_ON_ONCE(!test_bit(TR_ATTACHED, &old->tr_flags));
 
        old->tr_num_buf_new     += new->tr_num_buf_new;
@@ -817,6 +819,11 @@ static void gfs2_merge_trans(struct gfs2_trans *old, struct gfs2_trans *new)
 
        list_splice_tail_init(&new->tr_databuf, &old->tr_databuf);
        list_splice_tail_init(&new->tr_buf, &old->tr_buf);
+
+       spin_lock(&sdp->sd_ail_lock);
+       list_splice_tail_init(&new->tr_ail1_list, &old->tr_ail1_list);
+       list_splice_tail_init(&new->tr_ail2_list, &old->tr_ail2_list);
+       spin_unlock(&sdp->sd_ail_lock);
 }
 
 static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
@@ -828,7 +835,7 @@ static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
        gfs2_log_lock(sdp);
 
        if (sdp->sd_log_tr) {
-               gfs2_merge_trans(sdp->sd_log_tr, tr);
+               gfs2_merge_trans(sdp, tr);
        } else if (tr->tr_num_buf_new || tr->tr_num_databuf_new) {
                gfs2_assert_withdraw(sdp, test_bit(TR_ALLOCED, &tr->tr_flags));
                sdp->sd_log_tr = tr;