Skip to content

Commit 032500a

Browse files
committed
Merge tag 'jfs-6.8' of github.com:kleikamp/linux-shaggy
Pull jfs updates from David Kleikamp: "Stability improvements" * tag 'jfs-6.8' of github.com:kleikamp/linux-shaggy: jfs: Add missing set_freezable() for freezable kthread jfs: fix array-index-out-of-bounds in diNewExt jfs: fix shift-out-of-bounds in dbJoin jfs: fix uaf in jfs_evict_inode jfs: fix array-index-out-of-bounds in dbAdjTree jfs: fix slab-out-of-bounds Read in dtSearch UBSAN: array-index-out-of-bounds in dtSplitRoot FS:JFS:UBSAN:array-index-out-of-bounds in dbAdjTree
2 parents bfed9a9 + a280c9c commit 032500a

5 files changed

Lines changed: 52 additions & 31 deletions

File tree

fs/jfs/jfs_dmap.c

Lines changed: 38 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,10 @@
6363
*/
6464
static void dbAllocBits(struct bmap * bmp, struct dmap * dp, s64 blkno,
6565
int nblocks);
66-
static void dbSplit(dmtree_t * tp, int leafno, int splitsz, int newval);
67-
static int dbBackSplit(dmtree_t * tp, int leafno);
68-
static int dbJoin(dmtree_t * tp, int leafno, int newval);
69-
static void dbAdjTree(dmtree_t * tp, int leafno, int newval);
66+
static void dbSplit(dmtree_t *tp, int leafno, int splitsz, int newval, bool is_ctl);
67+
static int dbBackSplit(dmtree_t *tp, int leafno, bool is_ctl);
68+
static int dbJoin(dmtree_t *tp, int leafno, int newval, bool is_ctl);
69+
static void dbAdjTree(dmtree_t *tp, int leafno, int newval, bool is_ctl);
7070
static int dbAdjCtl(struct bmap * bmp, s64 blkno, int newval, int alloc,
7171
int level);
7272
static int dbAllocAny(struct bmap * bmp, s64 nblocks, int l2nb, s64 * results);
@@ -2103,7 +2103,7 @@ static int dbFreeDmap(struct bmap * bmp, struct dmap * dp, s64 blkno,
21032103
* system.
21042104
*/
21052105
if (dp->tree.stree[word] == NOFREE)
2106-
dbBackSplit((dmtree_t *) & dp->tree, word);
2106+
dbBackSplit((dmtree_t *)&dp->tree, word, false);
21072107

21082108
dbAllocBits(bmp, dp, blkno, nblocks);
21092109
}
@@ -2189,7 +2189,7 @@ static void dbAllocBits(struct bmap * bmp, struct dmap * dp, s64 blkno,
21892189
* the binary system of the leaves if need be.
21902190
*/
21912191
dbSplit(tp, word, BUDMIN,
2192-
dbMaxBud((u8 *) & dp->wmap[word]));
2192+
dbMaxBud((u8 *)&dp->wmap[word]), false);
21932193

21942194
word += 1;
21952195
} else {
@@ -2229,7 +2229,7 @@ static void dbAllocBits(struct bmap * bmp, struct dmap * dp, s64 blkno,
22292229
* system of the leaves to reflect the current
22302230
* allocation (size).
22312231
*/
2232-
dbSplit(tp, word, size, NOFREE);
2232+
dbSplit(tp, word, size, NOFREE, false);
22332233

22342234
/* get the number of dmap words handled */
22352235
nw = BUDSIZE(size, BUDMIN);
@@ -2336,7 +2336,7 @@ static int dbFreeBits(struct bmap * bmp, struct dmap * dp, s64 blkno,
23362336
/* update the leaf for this dmap word.
23372337
*/
23382338
rc = dbJoin(tp, word,
2339-
dbMaxBud((u8 *) & dp->wmap[word]));
2339+
dbMaxBud((u8 *)&dp->wmap[word]), false);
23402340
if (rc)
23412341
return rc;
23422342

@@ -2369,7 +2369,7 @@ static int dbFreeBits(struct bmap * bmp, struct dmap * dp, s64 blkno,
23692369

23702370
/* update the leaf.
23712371
*/
2372-
rc = dbJoin(tp, word, size);
2372+
rc = dbJoin(tp, word, size, false);
23732373
if (rc)
23742374
return rc;
23752375

@@ -2521,16 +2521,16 @@ dbAdjCtl(struct bmap * bmp, s64 blkno, int newval, int alloc, int level)
25212521
* that it is at the front of a binary buddy system.
25222522
*/
25232523
if (oldval == NOFREE) {
2524-
rc = dbBackSplit((dmtree_t *) dcp, leafno);
2524+
rc = dbBackSplit((dmtree_t *)dcp, leafno, true);
25252525
if (rc) {
25262526
release_metapage(mp);
25272527
return rc;
25282528
}
25292529
oldval = dcp->stree[ti];
25302530
}
2531-
dbSplit((dmtree_t *) dcp, leafno, dcp->budmin, newval);
2531+
dbSplit((dmtree_t *) dcp, leafno, dcp->budmin, newval, true);
25322532
} else {
2533-
rc = dbJoin((dmtree_t *) dcp, leafno, newval);
2533+
rc = dbJoin((dmtree_t *) dcp, leafno, newval, true);
25342534
if (rc) {
25352535
release_metapage(mp);
25362536
return rc;
@@ -2561,7 +2561,7 @@ dbAdjCtl(struct bmap * bmp, s64 blkno, int newval, int alloc, int level)
25612561
*/
25622562
if (alloc) {
25632563
dbJoin((dmtree_t *) dcp, leafno,
2564-
oldval);
2564+
oldval, true);
25652565
} else {
25662566
/* the dbJoin() above might have
25672567
* caused a larger binary buddy system
@@ -2571,9 +2571,9 @@ dbAdjCtl(struct bmap * bmp, s64 blkno, int newval, int alloc, int level)
25712571
*/
25722572
if (dcp->stree[ti] == NOFREE)
25732573
dbBackSplit((dmtree_t *)
2574-
dcp, leafno);
2574+
dcp, leafno, true);
25752575
dbSplit((dmtree_t *) dcp, leafno,
2576-
dcp->budmin, oldval);
2576+
dcp->budmin, oldval, true);
25772577
}
25782578

25792579
/* release the buffer and return the error.
@@ -2621,7 +2621,7 @@ dbAdjCtl(struct bmap * bmp, s64 blkno, int newval, int alloc, int level)
26212621
*
26222622
* serialization: IREAD_LOCK(ipbmap) or IWRITE_LOCK(ipbmap) held on entry/exit;
26232623
*/
2624-
static void dbSplit(dmtree_t * tp, int leafno, int splitsz, int newval)
2624+
static void dbSplit(dmtree_t *tp, int leafno, int splitsz, int newval, bool is_ctl)
26252625
{
26262626
int budsz;
26272627
int cursz;
@@ -2643,7 +2643,7 @@ static void dbSplit(dmtree_t * tp, int leafno, int splitsz, int newval)
26432643
while (cursz >= splitsz) {
26442644
/* update the buddy's leaf with its new value.
26452645
*/
2646-
dbAdjTree(tp, leafno ^ budsz, cursz);
2646+
dbAdjTree(tp, leafno ^ budsz, cursz, is_ctl);
26472647

26482648
/* on to the next size and buddy.
26492649
*/
@@ -2655,7 +2655,7 @@ static void dbSplit(dmtree_t * tp, int leafno, int splitsz, int newval)
26552655
/* adjust the dmap tree to reflect the specified leaf's new
26562656
* value.
26572657
*/
2658-
dbAdjTree(tp, leafno, newval);
2658+
dbAdjTree(tp, leafno, newval, is_ctl);
26592659
}
26602660

26612661

@@ -2686,7 +2686,7 @@ static void dbSplit(dmtree_t * tp, int leafno, int splitsz, int newval)
26862686
*
26872687
* serialization: IREAD_LOCK(ipbmap) or IWRITE_LOCK(ipbmap) held on entry/exit;
26882688
*/
2689-
static int dbBackSplit(dmtree_t * tp, int leafno)
2689+
static int dbBackSplit(dmtree_t *tp, int leafno, bool is_ctl)
26902690
{
26912691
int budsz, bud, w, bsz, size;
26922692
int cursz;
@@ -2737,7 +2737,7 @@ static int dbBackSplit(dmtree_t * tp, int leafno)
27372737
* system in two.
27382738
*/
27392739
cursz = leaf[bud] - 1;
2740-
dbSplit(tp, bud, cursz, cursz);
2740+
dbSplit(tp, bud, cursz, cursz, is_ctl);
27412741
break;
27422742
}
27432743
}
@@ -2763,9 +2763,11 @@ static int dbBackSplit(dmtree_t * tp, int leafno)
27632763
* leafno - the number of the leaf to be updated.
27642764
* newval - the new value for the leaf.
27652765
*
2766-
* RETURN VALUES: none
2766+
* RETURN VALUES:
2767+
* 0 - success
2768+
* -EIO - i/o error
27672769
*/
2768-
static int dbJoin(dmtree_t * tp, int leafno, int newval)
2770+
static int dbJoin(dmtree_t *tp, int leafno, int newval, bool is_ctl)
27692771
{
27702772
int budsz, buddy;
27712773
s8 *leaf;
@@ -2790,6 +2792,10 @@ static int dbJoin(dmtree_t * tp, int leafno, int newval)
27902792
* get the buddy size (number of words covered) of
27912793
* the new value.
27922794
*/
2795+
2796+
if ((newval - tp->dmt_budmin) > BUDMIN)
2797+
return -EIO;
2798+
27932799
budsz = BUDSIZE(newval, tp->dmt_budmin);
27942800

27952801
/* try to join.
@@ -2820,12 +2826,12 @@ static int dbJoin(dmtree_t * tp, int leafno, int newval)
28202826
if (leafno < buddy) {
28212827
/* leafno is the left buddy.
28222828
*/
2823-
dbAdjTree(tp, buddy, NOFREE);
2829+
dbAdjTree(tp, buddy, NOFREE, is_ctl);
28242830
} else {
28252831
/* buddy is the left buddy and becomes
28262832
* leafno.
28272833
*/
2828-
dbAdjTree(tp, leafno, NOFREE);
2834+
dbAdjTree(tp, leafno, NOFREE, is_ctl);
28292835
leafno = buddy;
28302836
}
28312837

@@ -2838,7 +2844,7 @@ static int dbJoin(dmtree_t * tp, int leafno, int newval)
28382844

28392845
/* update the leaf value.
28402846
*/
2841-
dbAdjTree(tp, leafno, newval);
2847+
dbAdjTree(tp, leafno, newval, is_ctl);
28422848

28432849
return 0;
28442850
}
@@ -2859,15 +2865,20 @@ static int dbJoin(dmtree_t * tp, int leafno, int newval)
28592865
*
28602866
* RETURN VALUES: none
28612867
*/
2862-
static void dbAdjTree(dmtree_t * tp, int leafno, int newval)
2868+
static void dbAdjTree(dmtree_t *tp, int leafno, int newval, bool is_ctl)
28632869
{
28642870
int lp, pp, k;
2865-
int max;
2871+
int max, size;
2872+
2873+
size = is_ctl ? CTLTREESIZE : TREESIZE;
28662874

28672875
/* pick up the index of the leaf for this leafno.
28682876
*/
28692877
lp = leafno + le32_to_cpu(tp->dmt_leafidx);
28702878

2879+
if (WARN_ON_ONCE(lp >= size || lp < 0))
2880+
return;
2881+
28712882
/* is the current value the same as the old value ? if so,
28722883
* there is nothing to do.
28732884
*/

fs/jfs/jfs_dtree.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -633,6 +633,11 @@ int dtSearch(struct inode *ip, struct component_name * key, ino_t * data,
633633
for (base = 0, lim = p->header.nextindex; lim; lim >>= 1) {
634634
index = base + (lim >> 1);
635635

636+
if (stbl[index] < 0) {
637+
rc = -EIO;
638+
goto out;
639+
}
640+
636641
if (p->header.flag & BT_LEAF) {
637642
/* uppercase leaf name to compare */
638643
cmp =
@@ -1970,7 +1975,7 @@ static int dtSplitRoot(tid_t tid,
19701975
do {
19711976
f = &rp->slot[fsi];
19721977
fsi = f->next;
1973-
} while (fsi != -1);
1978+
} while (fsi >= 0);
19741979

19751980
f->next = n;
19761981
}

fs/jfs/jfs_imap.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2179,6 +2179,9 @@ static int diNewExt(struct inomap * imap, struct iag * iagp, int extno)
21792179
/* get the ag and iag numbers for this iag.
21802180
*/
21812181
agno = BLKTOAG(le64_to_cpu(iagp->agstart), sbi);
2182+
if (agno >= MAXAG || agno < 0)
2183+
return -EIO;
2184+
21822185
iagno = le32_to_cpu(iagp->iagnum);
21832186

21842187
/* check if this is the last free extent within the

fs/jfs/jfs_mount.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -172,15 +172,15 @@ int jfs_mount(struct super_block *sb)
172172
}
173173
jfs_info("jfs_mount: ipimap:0x%p", ipimap);
174174

175-
/* map further access of per fileset inodes by the fileset inode */
176-
sbi->ipimap = ipimap;
177-
178175
/* initialize fileset inode allocation map */
179176
if ((rc = diMount(ipimap))) {
180177
jfs_err("jfs_mount: diMount failed w/rc = %d", rc);
181178
goto err_ipimap;
182179
}
183180

181+
/* map further access of per fileset inodes by the fileset inode */
182+
sbi->ipimap = ipimap;
183+
184184
return rc;
185185

186186
/*

fs/jfs/jfs_txnmgr.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2702,6 +2702,7 @@ int jfs_lazycommit(void *arg)
27022702
unsigned long flags;
27032703
struct jfs_sb_info *sbi;
27042704

2705+
set_freezable();
27052706
do {
27062707
LAZY_LOCK(flags);
27072708
jfs_commit_thread_waking = 0; /* OK to wake another thread */
@@ -2884,6 +2885,7 @@ int jfs_sync(void *arg)
28842885
struct jfs_inode_info *jfs_ip;
28852886
tid_t tid;
28862887

2888+
set_freezable();
28872889
do {
28882890
/*
28892891
* write each inode on the anonymous inode list

0 commit comments

Comments
 (0)