]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
gfs2: Fix NULL pointer dereference in gfs2_rgrp_dump
authorAndrew Price <anprice@redhat.com>
Wed, 7 Oct 2020 11:30:58 +0000 (12:30 +0100)
committerAndreas Gruenbacher <agruenba@redhat.com>
Wed, 14 Oct 2020 21:54:43 +0000 (23:54 +0200)
When an rindex entry is found to be corrupt, compute_bitstructs() calls
gfs2_consist_rgrpd() which calls gfs2_rgrp_dump() like this:

    gfs2_rgrp_dump(NULL, rgd->rd_gl, fs_id_buf);

gfs2_rgrp_dump then dereferences the gl without checking it and we get

    BUG: KASAN: null-ptr-deref in gfs2_rgrp_dump+0x28/0x280

because there's no rgrp glock involved while reading the rindex on mount.

Fix this by changing gfs2_rgrp_dump to take an rgrp argument.

Reported-by: syzbot+43fa87986bdd31df9de6@syzkaller.appspotmail.com
Signed-off-by: Andrew Price <anprice@redhat.com>
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
fs/gfs2/glops.c
fs/gfs2/rgrp.c
fs/gfs2/rgrp.h
fs/gfs2/util.c

index de1d5f1d9ff8561a5bfc400e4759b70635c1455f..c2c90747d79b5d6128417857f3fc42116b858d4d 100644 (file)
@@ -227,6 +227,15 @@ static void rgrp_go_inval(struct gfs2_glock *gl, int flags)
                rgd->rd_flags &= ~GFS2_RDF_UPTODATE;
 }
 
+static void gfs2_rgrp_go_dump(struct seq_file *seq, struct gfs2_glock *gl,
+                             const char *fs_id_buf)
+{
+       struct gfs2_rgrpd *rgd = gfs2_glock2rgrp(gl);
+
+       if (rgd)
+               gfs2_rgrp_dump(seq, rgd, fs_id_buf);
+}
+
 static struct gfs2_inode *gfs2_glock2inode(struct gfs2_glock *gl)
 {
        struct gfs2_inode *ip;
@@ -712,7 +721,7 @@ const struct gfs2_glock_operations gfs2_rgrp_glops = {
        .go_sync = rgrp_go_sync,
        .go_inval = rgrp_go_inval,
        .go_lock = gfs2_rgrp_go_lock,
-       .go_dump = gfs2_rgrp_dump,
+       .go_dump = gfs2_rgrp_go_dump,
        .go_type = LM_TYPE_RGRP,
        .go_flags = GLOF_LVB,
 };
index 074f228ea83901134dd41c550baf23a346ee660c..1bba5a9d45fa32f38af1462921b6ab24e5fe29cd 100644 (file)
@@ -2209,20 +2209,17 @@ static void rgblk_free(struct gfs2_sbd *sdp, struct gfs2_rgrpd *rgd,
 /**
  * gfs2_rgrp_dump - print out an rgrp
  * @seq: The iterator
- * @gl: The glock in question
+ * @rgd: The rgrp in question
  * @fs_id_buf: pointer to file system id (if requested)
  *
  */
 
-void gfs2_rgrp_dump(struct seq_file *seq, struct gfs2_glock *gl,
+void gfs2_rgrp_dump(struct seq_file *seq, struct gfs2_rgrpd *rgd,
                    const char *fs_id_buf)
 {
-       struct gfs2_rgrpd *rgd = gl->gl_object;
        struct gfs2_blkreserv *trs;
        const struct rb_node *n;
 
-       if (rgd == NULL)
-               return;
        gfs2_print_dbg(seq, "%s R: n:%llu f:%02x b:%u/%u i:%u r:%u e:%u\n",
                       fs_id_buf,
                       (unsigned long long)rgd->rd_addr, rgd->rd_flags,
@@ -2253,7 +2250,7 @@ static void gfs2_rgrp_error(struct gfs2_rgrpd *rgd)
                (unsigned long long)rgd->rd_addr);
        fs_warn(sdp, "umount on all nodes and run fsck.gfs2 to fix the error\n");
        sprintf(fs_id_buf, "fsid=%s: ", sdp->sd_fsname);
-       gfs2_rgrp_dump(NULL, rgd->rd_gl, fs_id_buf);
+       gfs2_rgrp_dump(NULL, rgd, fs_id_buf);
        rgd->rd_flags |= GFS2_RDF_ERROR;
 }
 
index a1d7e14fc55b9c2098c00348d5bc7bed652992b7..9a587ada51edaf2c16cc71af4367ab4fd0de5c7c 100644 (file)
@@ -67,7 +67,7 @@ extern void gfs2_rlist_add(struct gfs2_inode *ip, struct gfs2_rgrp_list *rlist,
 extern void gfs2_rlist_alloc(struct gfs2_rgrp_list *rlist);
 extern void gfs2_rlist_free(struct gfs2_rgrp_list *rlist);
 extern u64 gfs2_ri_total(struct gfs2_sbd *sdp);
-extern void gfs2_rgrp_dump(struct seq_file *seq, struct gfs2_glock *gl,
+extern void gfs2_rgrp_dump(struct seq_file *seq, struct gfs2_rgrpd *rgd,
                           const char *fs_id_buf);
 extern int gfs2_rgrp_send_discards(struct gfs2_sbd *sdp, u64 offset,
                                   struct buffer_head *bh,
index 1cd0328cae20a4d08183adca3022d4e69d9a45d3..0fba3bf641890e304be48f763346432b334bd065 100644 (file)
@@ -419,7 +419,7 @@ void gfs2_consist_rgrpd_i(struct gfs2_rgrpd *rgd,
        char fs_id_buf[sizeof(sdp->sd_fsname) + 7];
 
        sprintf(fs_id_buf, "fsid=%s: ", sdp->sd_fsname);
-       gfs2_rgrp_dump(NULL, rgd->rd_gl, fs_id_buf);
+       gfs2_rgrp_dump(NULL, rgd, fs_id_buf);
        gfs2_lm(sdp,
                "fatal: filesystem consistency error\n"
                "  RG = %llu\n"