Skip to content

Commit f79adee

Browse files
committed
Merge tag 'jfs-6.14' of github.com:kleikamp/linux-shaggy
Pull jfs updates from David Kleikamp: "Various bug fixes and cleanups for JFS" * tag 'jfs-6.14' of github.com:kleikamp/linux-shaggy: jfs: add index corruption check to DT_GETPAGE() fs/jfs: consolidate sanity checking in dbMount jfs: add sanity check for agwidth in dbMount jfs: Prevent copying of nlink with value 0 from disk inode fs/jfs: Prevent integer overflow in AG size calculation fs/jfs: cast inactags to s64 to prevent potential overflow jfs: Fix uninit-value access of imap allocated in the diMount() function jfs: fix slab-out-of-bounds read in ea_get() jfs: add check read-only before truncation in jfs_truncate_nolock() jfs: add check read-only before txBeginAnon() call jfs: reject on-disk inodes of an unsupported type jfs: Remove reference to bh->b_page jfs: Delete a couple tabs in jfs_reconfigure()
2 parents fde0562 + a8dfb21 commit f79adee

File tree

7 files changed

+51
-41
lines changed

7 files changed

+51
-41
lines changed

fs/jfs/inode.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,7 @@ void jfs_truncate_nolock(struct inode *ip, loff_t length)
369369

370370
ASSERT(length >= 0);
371371

372-
if (test_cflag(COMMIT_Nolink, ip)) {
372+
if (test_cflag(COMMIT_Nolink, ip) || isReadOnly(ip)) {
373373
xtTruncate(0, ip, length, COMMIT_WMAP);
374374
return;
375375
}

fs/jfs/jfs_dmap.c

Lines changed: 12 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -178,41 +178,26 @@ int dbMount(struct inode *ipbmap)
178178
dbmp_le = (struct dbmap_disk *) mp->data;
179179
bmp->db_mapsize = le64_to_cpu(dbmp_le->dn_mapsize);
180180
bmp->db_nfree = le64_to_cpu(dbmp_le->dn_nfree);
181-
182181
bmp->db_l2nbperpage = le32_to_cpu(dbmp_le->dn_l2nbperpage);
183-
if (bmp->db_l2nbperpage > L2PSIZE - L2MINBLOCKSIZE ||
184-
bmp->db_l2nbperpage < 0) {
185-
err = -EINVAL;
186-
goto err_release_metapage;
187-
}
188-
189182
bmp->db_numag = le32_to_cpu(dbmp_le->dn_numag);
190-
if (!bmp->db_numag || bmp->db_numag > MAXAG) {
191-
err = -EINVAL;
192-
goto err_release_metapage;
193-
}
194-
195183
bmp->db_maxlevel = le32_to_cpu(dbmp_le->dn_maxlevel);
196184
bmp->db_maxag = le32_to_cpu(dbmp_le->dn_maxag);
197185
bmp->db_agpref = le32_to_cpu(dbmp_le->dn_agpref);
198-
if (bmp->db_maxag >= MAXAG || bmp->db_maxag < 0 ||
199-
bmp->db_agpref >= MAXAG || bmp->db_agpref < 0) {
200-
err = -EINVAL;
201-
goto err_release_metapage;
202-
}
203-
204186
bmp->db_aglevel = le32_to_cpu(dbmp_le->dn_aglevel);
205187
bmp->db_agheight = le32_to_cpu(dbmp_le->dn_agheight);
206188
bmp->db_agwidth = le32_to_cpu(dbmp_le->dn_agwidth);
207189
bmp->db_agstart = le32_to_cpu(dbmp_le->dn_agstart);
208190
bmp->db_agl2size = le32_to_cpu(dbmp_le->dn_agl2size);
209-
if (bmp->db_agl2size > L2MAXL2SIZE - L2MAXAG ||
210-
bmp->db_agl2size < 0) {
211-
err = -EINVAL;
212-
goto err_release_metapage;
213-
}
214191

215-
if (((bmp->db_mapsize - 1) >> bmp->db_agl2size) > MAXAG) {
192+
if ((bmp->db_l2nbperpage > L2PSIZE - L2MINBLOCKSIZE) ||
193+
(bmp->db_l2nbperpage < 0) ||
194+
!bmp->db_numag || (bmp->db_numag > MAXAG) ||
195+
(bmp->db_maxag >= MAXAG) || (bmp->db_maxag < 0) ||
196+
(bmp->db_agpref >= MAXAG) || (bmp->db_agpref < 0) ||
197+
!bmp->db_agwidth ||
198+
(bmp->db_agl2size > L2MAXL2SIZE - L2MAXAG) ||
199+
(bmp->db_agl2size < 0) ||
200+
((bmp->db_mapsize - 1) >> bmp->db_agl2size) > MAXAG) {
216201
err = -EINVAL;
217202
goto err_release_metapage;
218203
}
@@ -3403,7 +3388,7 @@ int dbExtendFS(struct inode *ipbmap, s64 blkno, s64 nblocks)
34033388
oldl2agsize = bmp->db_agl2size;
34043389

34053390
bmp->db_agl2size = l2agsize;
3406-
bmp->db_agsize = 1 << l2agsize;
3391+
bmp->db_agsize = (s64)1 << l2agsize;
34073392

34083393
/* compute new number of AG */
34093394
agno = bmp->db_numag;
@@ -3666,8 +3651,8 @@ void dbFinalizeBmap(struct inode *ipbmap)
36663651
* system size is not a multiple of the group size).
36673652
*/
36683653
inactfree = (inactags && ag_rem) ?
3669-
((inactags - 1) << bmp->db_agl2size) + ag_rem
3670-
: inactags << bmp->db_agl2size;
3654+
(((s64)inactags - 1) << bmp->db_agl2size) + ag_rem
3655+
: ((s64)inactags << bmp->db_agl2size);
36713656

36723657
/* determine how many free blocks are in the active
36733658
* allocation groups plus the average number of free blocks

fs/jfs/jfs_dtree.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,8 @@ do { \
117117
if (!(RC)) { \
118118
if (((P)->header.nextindex > \
119119
(((BN) == 0) ? DTROOTMAXSLOT : (P)->header.maxslot)) || \
120-
((BN) && ((P)->header.maxslot > DTPAGEMAXSLOT))) { \
120+
((BN) && (((P)->header.maxslot > DTPAGEMAXSLOT) || \
121+
((P)->header.stblindex >= DTPAGEMAXSLOT)))) { \
121122
BT_PUTPAGE(MP); \
122123
jfs_error((IP)->i_sb, \
123124
"DT_GETPAGE: dtree page corrupt\n"); \

fs/jfs/jfs_extent.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,11 @@ extAlloc(struct inode *ip, s64 xlen, s64 pno, xad_t * xp, bool abnr)
7474
int rc;
7575
int xflag;
7676

77+
if (isReadOnly(ip)) {
78+
jfs_error(ip->i_sb, "read-only filesystem\n");
79+
return -EIO;
80+
}
81+
7782
/* This blocks if we are low on resources */
7883
txBeginAnon(ip->i_sb);
7984

@@ -253,6 +258,11 @@ int extRecord(struct inode *ip, xad_t * xp)
253258
{
254259
int rc;
255260

261+
if (isReadOnly(ip)) {
262+
jfs_error(ip->i_sb, "read-only filesystem\n");
263+
return -EIO;
264+
}
265+
256266
txBeginAnon(ip->i_sb);
257267

258268
mutex_lock(&JFS_IP(ip)->commit_mutex);

fs/jfs/jfs_imap.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ int diMount(struct inode *ipimap)
102102
* allocate/initialize the in-memory inode map control structure
103103
*/
104104
/* allocate the in-memory inode map control structure. */
105-
imap = kmalloc(sizeof(struct inomap), GFP_KERNEL);
105+
imap = kzalloc(sizeof(struct inomap), GFP_KERNEL);
106106
if (imap == NULL)
107107
return -ENOMEM;
108108

@@ -456,7 +456,7 @@ struct inode *diReadSpecial(struct super_block *sb, ino_t inum, int secondary)
456456
dp += inum % 8; /* 8 inodes per 4K page */
457457

458458
/* copy on-disk inode to in-memory inode */
459-
if ((copy_from_dinode(dp, ip)) != 0) {
459+
if ((copy_from_dinode(dp, ip) != 0) || (ip->i_nlink == 0)) {
460460
/* handle bad return by returning NULL for ip */
461461
set_nlink(ip, 1); /* Don't want iput() deleting it */
462462
iput(ip);
@@ -3029,14 +3029,23 @@ static void duplicateIXtree(struct super_block *sb, s64 blkno,
30293029
*
30303030
* RETURN VALUES:
30313031
* 0 - success
3032-
* -ENOMEM - insufficient memory
3032+
* -EINVAL - unexpected inode type
30333033
*/
30343034
static int copy_from_dinode(struct dinode * dip, struct inode *ip)
30353035
{
30363036
struct jfs_inode_info *jfs_ip = JFS_IP(ip);
30373037
struct jfs_sb_info *sbi = JFS_SBI(ip->i_sb);
3038+
int fileset = le32_to_cpu(dip->di_fileset);
3039+
3040+
switch (fileset) {
3041+
case AGGR_RESERVED_I: case AGGREGATE_I: case BMAP_I:
3042+
case LOG_I: case BADBLOCK_I: case FILESYSTEM_I:
3043+
break;
3044+
default:
3045+
return -EINVAL;
3046+
}
30383047

3039-
jfs_ip->fileset = le32_to_cpu(dip->di_fileset);
3048+
jfs_ip->fileset = fileset;
30403049
jfs_ip->mode2 = le32_to_cpu(dip->di_mode);
30413050
jfs_set_inode_flags(ip);
30423051

fs/jfs/super.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -389,8 +389,8 @@ static int jfs_reconfigure(struct fs_context *fc)
389389

390390
if (!ctx->newLVSize) {
391391
ctx->newLVSize = sb_bdev_nr_blocks(sb);
392-
if (ctx->newLVSize == 0)
393-
pr_err("JFS: Cannot determine volume size\n");
392+
if (ctx->newLVSize == 0)
393+
pr_err("JFS: Cannot determine volume size\n");
394394
}
395395

396396
rc = jfs_extendfs(sb, ctx->newLVSize, 0);
@@ -766,7 +766,7 @@ static ssize_t jfs_quota_write(struct super_block *sb, int type,
766766
}
767767
lock_buffer(bh);
768768
memcpy(bh->b_data+offset, data, tocopy);
769-
flush_dcache_page(bh->b_page);
769+
flush_dcache_folio(bh->b_folio);
770770
set_buffer_uptodate(bh);
771771
mark_buffer_dirty(bh);
772772
unlock_buffer(bh);

fs/jfs/xattr.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -559,11 +559,16 @@ static int ea_get(struct inode *inode, struct ea_buffer *ea_buf, int min_size)
559559

560560
size_check:
561561
if (EALIST_SIZE(ea_buf->xattr) != ea_size) {
562-
int size = clamp_t(int, ea_size, 0, EALIST_SIZE(ea_buf->xattr));
563-
564-
printk(KERN_ERR "ea_get: invalid extended attribute\n");
565-
print_hex_dump(KERN_ERR, "", DUMP_PREFIX_ADDRESS, 16, 1,
566-
ea_buf->xattr, size, 1);
562+
if (unlikely(EALIST_SIZE(ea_buf->xattr) > INT_MAX)) {
563+
printk(KERN_ERR "ea_get: extended attribute size too large: %u > INT_MAX\n",
564+
EALIST_SIZE(ea_buf->xattr));
565+
} else {
566+
int size = clamp_t(int, ea_size, 0, EALIST_SIZE(ea_buf->xattr));
567+
568+
printk(KERN_ERR "ea_get: invalid extended attribute\n");
569+
print_hex_dump(KERN_ERR, "", DUMP_PREFIX_ADDRESS, 16, 1,
570+
ea_buf->xattr, size, 1);
571+
}
567572
ea_release(inode, ea_buf);
568573
rc = -EIO;
569574
goto clean_up;

0 commit comments

Comments
 (0)