Merge tag 'jfs-6.7' of https://github.com/kleikamp/linux-shaggy
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 2 Nov 2023 18:08:28 +0000 (08:08 -1000)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 2 Nov 2023 18:08:28 +0000 (08:08 -1000)
Pull jfs updates from Dave Kleikamp:
 "Minor stability improvements"

* tag 'jfs-6.7' of https://github.com/kleikamp/linux-shaggy:
  jfs: define xtree root and page independently
  jfs: fix array-index-out-of-bounds in diAlloc
  jfs: fix array-index-out-of-bounds in dbFindLeaf
  fs/jfs: Add validity check for db_maxag and db_agpref
  fs/jfs: Add check for negative db_l2nbperpage

fs/jfs/jfs_dinode.h
fs/jfs/jfs_dmap.c
fs/jfs/jfs_imap.c
fs/jfs/jfs_incore.h
fs/jfs/jfs_txnmgr.c
fs/jfs/jfs_xtree.c
fs/jfs/jfs_xtree.h

index 6b231d0d0071ba6a06a66192882c99b4014f55a7..603aae17a69343fcd766d12dbf2231c4fe7cd173 100644 (file)
@@ -96,7 +96,7 @@ struct dinode {
 #define di_gengen      u._file._u1._imap._gengen
 
                        union {
-                               xtpage_t _xtroot;
+                               xtroot_t _xtroot;
                                struct {
                                        u8 unused[16];  /* 16: */
                                        dxd_t _dxd;     /* 16: */
index 88afd108c2dd2e04c63ee2bb7348c8173bc6d26b..11c77757ead9e00b684da592de0b2232034ebda1 100644 (file)
@@ -87,7 +87,7 @@ static int dbAllocCtl(struct bmap * bmp, s64 nblocks, int l2nb, s64 blkno,
 static int dbExtend(struct inode *ip, s64 blkno, s64 nblocks, s64 addnblocks);
 static int dbFindBits(u32 word, int l2nb);
 static int dbFindCtl(struct bmap * bmp, int l2nb, int level, s64 * blkno);
-static int dbFindLeaf(dmtree_t * tp, int l2nb, int *leafidx);
+static int dbFindLeaf(dmtree_t *tp, int l2nb, int *leafidx, bool is_ctl);
 static int dbFreeBits(struct bmap * bmp, struct dmap * dp, s64 blkno,
                      int nblocks);
 static int dbFreeDmap(struct bmap * bmp, struct dmap * dp, s64 blkno,
@@ -180,7 +180,8 @@ int dbMount(struct inode *ipbmap)
        bmp->db_nfree = le64_to_cpu(dbmp_le->dn_nfree);
 
        bmp->db_l2nbperpage = le32_to_cpu(dbmp_le->dn_l2nbperpage);
-       if (bmp->db_l2nbperpage > L2PSIZE - L2MINBLOCKSIZE) {
+       if (bmp->db_l2nbperpage > L2PSIZE - L2MINBLOCKSIZE ||
+               bmp->db_l2nbperpage < 0) {
                err = -EINVAL;
                goto err_release_metapage;
        }
@@ -194,6 +195,12 @@ int dbMount(struct inode *ipbmap)
        bmp->db_maxlevel = le32_to_cpu(dbmp_le->dn_maxlevel);
        bmp->db_maxag = le32_to_cpu(dbmp_le->dn_maxag);
        bmp->db_agpref = le32_to_cpu(dbmp_le->dn_agpref);
+       if (bmp->db_maxag >= MAXAG || bmp->db_maxag < 0 ||
+               bmp->db_agpref >= MAXAG || bmp->db_agpref < 0) {
+               err = -EINVAL;
+               goto err_release_metapage;
+       }
+
        bmp->db_aglevel = le32_to_cpu(dbmp_le->dn_aglevel);
        bmp->db_agheight = le32_to_cpu(dbmp_le->dn_agheight);
        bmp->db_agwidth = le32_to_cpu(dbmp_le->dn_agwidth);
@@ -1710,7 +1717,7 @@ static int dbFindCtl(struct bmap * bmp, int l2nb, int level, s64 * blkno)
                 * dbFindLeaf() returns the index of the leaf at which
                 * free space was found.
                 */
-               rc = dbFindLeaf((dmtree_t *) dcp, l2nb, &leafidx);
+               rc = dbFindLeaf((dmtree_t *) dcp, l2nb, &leafidx, true);
 
                /* release the buffer.
                 */
@@ -1957,7 +1964,7 @@ dbAllocDmapLev(struct bmap * bmp,
         * free space.  if sufficient free space is found, dbFindLeaf()
         * returns the index of the leaf at which free space was found.
         */
-       if (dbFindLeaf((dmtree_t *) & dp->tree, l2nb, &leafidx))
+       if (dbFindLeaf((dmtree_t *) &dp->tree, l2nb, &leafidx, false))
                return -ENOSPC;
 
        if (leafidx < 0)
@@ -2921,14 +2928,18 @@ static void dbAdjTree(dmtree_t * tp, int leafno, int newval)
  *     leafidx - return pointer to be set to the index of the leaf
  *               describing at least l2nb free blocks if sufficient
  *               free blocks are found.
+ *     is_ctl  - determines if the tree is of type ctl
  *
  * RETURN VALUES:
  *     0       - success
  *     -ENOSPC - insufficient free blocks.
  */
-static int dbFindLeaf(dmtree_t * tp, int l2nb, int *leafidx)
+static int dbFindLeaf(dmtree_t *tp, int l2nb, int *leafidx, bool is_ctl)
 {
        int ti, n = 0, k, x = 0;
+       int max_size;
+
+       max_size = is_ctl ? CTLTREESIZE : TREESIZE;
 
        /* first check the root of the tree to see if there is
         * sufficient free space.
@@ -2949,6 +2960,8 @@ static int dbFindLeaf(dmtree_t * tp, int l2nb, int *leafidx)
                        /* sufficient free space found.  move to the next
                         * level (or quit if this is the last level).
                         */
+                       if (x + n > max_size)
+                               return -ENOSPC;
                        if (l2nb <= tp->dmt_stree[x + n])
                                break;
                }
index 8e87264e56ce655555854e4bd9cb97b63eecf9af..a037ee59e39854f662ddfdc03a51d7f0f96a07f6 100644 (file)
@@ -670,7 +670,7 @@ int diWrite(tid_t tid, struct inode *ip)
                 * This is the special xtree inside the directory for storing
                 * the directory table
                 */
-               xtpage_t *p, *xp;
+               xtroot_t *p, *xp;
                xad_t *xad;
 
                jfs_ip->xtlid = 0;
@@ -684,7 +684,7 @@ int diWrite(tid_t tid, struct inode *ip)
                 * copy xtree root from inode to dinode:
                 */
                p = &jfs_ip->i_xtroot;
-               xp = (xtpage_t *) &dp->di_dirtable;
+               xp = (xtroot_t *) &dp->di_dirtable;
                lv = ilinelock->lv;
                for (n = 0; n < ilinelock->index; n++, lv++) {
                        memcpy(&xp->xad[lv->offset], &p->xad[lv->offset],
@@ -713,7 +713,7 @@ int diWrite(tid_t tid, struct inode *ip)
         *      regular file: 16 byte (XAD slot) granularity
         */
        if (type & tlckXTREE) {
-               xtpage_t *p, *xp;
+               xtroot_t *p, *xp;
                xad_t *xad;
 
                /*
@@ -1320,7 +1320,7 @@ diInitInode(struct inode *ip, int iagno, int ino, int extno, struct iag * iagp)
 int diAlloc(struct inode *pip, bool dir, struct inode *ip)
 {
        int rc, ino, iagno, addext, extno, bitno, sword;
-       int nwords, rem, i, agno;
+       int nwords, rem, i, agno, dn_numag;
        u32 mask, inosmap, extsmap;
        struct inode *ipimap;
        struct metapage *mp;
@@ -1356,6 +1356,9 @@ int diAlloc(struct inode *pip, bool dir, struct inode *ip)
 
        /* get the ag number of this iag */
        agno = BLKTOAG(JFS_IP(pip)->agstart, JFS_SBI(pip->i_sb));
+       dn_numag = JFS_SBI(pip->i_sb)->bmap->db_numag;
+       if (agno < 0 || agno > dn_numag)
+               return -EIO;
 
        if (atomic_read(&JFS_SBI(pip->i_sb)->bmap->db_active[agno])) {
                /*
index 721def69e732e444c18bdde9ae271da98260ca02..dd4264aa9beddecd58e17cd44a730d30acba4176 100644 (file)
@@ -66,7 +66,7 @@ struct jfs_inode_info {
        lid_t   xtlid;          /* lid of xtree lock on directory */
        union {
                struct {
-                       xtpage_t _xtroot;       /* 288: xtree root */
+                       xtroot_t _xtroot;       /* 288: xtree root */
                        struct inomap *_imap;   /* 4: inode map header  */
                } file;
                struct {
index ce4b4760fcb1d6402a3220887e10fd9f97e61e4a..dccc8b3f104593a5f96c68f1e51b4a7fefdb3d8d 100644 (file)
@@ -783,7 +783,7 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp,
                        if (mp->xflag & COMMIT_PAGE)
                                p = (xtpage_t *) mp->data;
                        else
-                               p = &jfs_ip->i_xtroot;
+                               p = (xtpage_t *) &jfs_ip->i_xtroot;
                        xtlck->lwm.offset =
                            le16_to_cpu(p->header.nextindex);
                }
@@ -1676,7 +1676,7 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
 
        if (tlck->type & tlckBTROOT) {
                lrd->log.redopage.type |= cpu_to_le16(LOG_BTROOT);
-               p = &JFS_IP(ip)->i_xtroot;
+               p = (xtpage_t *) &JFS_IP(ip)->i_xtroot;
                if (S_ISDIR(ip->i_mode))
                        lrd->log.redopage.type |=
                            cpu_to_le16(LOG_DIR_XTREE);
index 2d304cee884c6ff2cad43a06433abe425876f97f..5ee618d17e77303226357939f3889b908f3c962a 100644 (file)
@@ -1213,7 +1213,7 @@ xtSplitRoot(tid_t tid,
        struct xtlock *xtlck;
        int rc;
 
-       sp = &JFS_IP(ip)->i_xtroot;
+       sp = (xtpage_t *) &JFS_IP(ip)->i_xtroot;
 
        INCREMENT(xtStat.split);
 
@@ -2098,7 +2098,7 @@ int xtAppend(tid_t tid,           /* transaction id */
  */
 void xtInitRoot(tid_t tid, struct inode *ip)
 {
-       xtpage_t *p;
+       xtroot_t *p;
 
        /*
         * acquire a transaction lock on the root
index ad7592191d7607d38d246a631550785c3487bd11..0f6cf5a1ce75bd3240fe23ffa9a06ea4b7d9771a 100644 (file)
@@ -65,24 +65,33 @@ struct xadlist {
 #define XTPAGEMAXSLOT  256
 #define XTENTRYSTART   2
 
-/*
- *     xtree page:
- */
-typedef union {
-       struct xtheader {
-               __le64 next;    /* 8: */
-               __le64 prev;    /* 8: */
+struct xtheader {
+       __le64 next;    /* 8: */
+       __le64 prev;    /* 8: */
 
-               u8 flag;        /* 1: */
-               u8 rsrvd1;      /* 1: */
-               __le16 nextindex;       /* 2: next index = number of entries */
-               __le16 maxentry;        /* 2: max number of entries */
-               __le16 rsrvd2;  /* 2: */
+       u8 flag;        /* 1: */
+       u8 rsrvd1;      /* 1: */
+       __le16 nextindex;       /* 2: next index = number of entries */
+       __le16 maxentry;        /* 2: max number of entries */
+       __le16 rsrvd2;  /* 2: */
 
-               pxd_t self;     /* 8: self */
-       } header;               /* (32) */
+       pxd_t self;     /* 8: self */
+};
 
+/*
+ *     xtree root (in inode):
+ */
+typedef union {
+       struct xtheader header;
        xad_t xad[XTROOTMAXSLOT];       /* 16 * maxentry: xad array */
+} xtroot_t;
+
+/*
+ *     xtree page:
+ */
+typedef union {
+       struct xtheader header;
+       xad_t xad[XTPAGEMAXSLOT];       /* 16 * maxentry: xad array */
 } xtpage_t;
 
 /*