Skip to content

Commit 4770119

Browse files
committed
Merge tag 'fs_for_v6.12-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs
Pull UDF fixes from Jan Kara: "A couple of UDF error handling fixes for issues spotted by syzbot" * tag 'fs_for_v6.12-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs: udf: fix uninit-value use in udf_get_fileshortad udf: refactor inode_bmap() to handle error udf: refactor udf_next_aext() to handle error udf: refactor udf_current_aext() to handle error
2 parents a3a3769 + 264db9d commit 4770119

File tree

7 files changed

+224
-106
lines changed

7 files changed

+224
-106
lines changed

fs/udf/balloc.c

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@ static void udf_table_free_blocks(struct super_block *sb,
370370
struct extent_position oepos, epos;
371371
int8_t etype;
372372
struct udf_inode_info *iinfo;
373+
int ret = 0;
373374

374375
mutex_lock(&sbi->s_alloc_mutex);
375376
iinfo = UDF_I(table);
@@ -383,8 +384,12 @@ static void udf_table_free_blocks(struct super_block *sb,
383384
epos.block = oepos.block = iinfo->i_location;
384385
epos.bh = oepos.bh = NULL;
385386

386-
while (count &&
387-
(etype = udf_next_aext(table, &epos, &eloc, &elen, 1)) != -1) {
387+
while (count) {
388+
ret = udf_next_aext(table, &epos, &eloc, &elen, &etype, 1);
389+
if (ret < 0)
390+
goto error_return;
391+
if (ret == 0)
392+
break;
388393
if (((eloc.logicalBlockNum +
389394
(elen >> sb->s_blocksize_bits)) == start)) {
390395
if ((0x3FFFFFFF - elen) <
@@ -459,11 +464,8 @@ static void udf_table_free_blocks(struct super_block *sb,
459464
adsize = sizeof(struct short_ad);
460465
else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
461466
adsize = sizeof(struct long_ad);
462-
else {
463-
brelse(oepos.bh);
464-
brelse(epos.bh);
467+
else
465468
goto error_return;
466-
}
467469

468470
if (epos.offset + (2 * adsize) > sb->s_blocksize) {
469471
/* Steal a block from the extent being free'd */
@@ -479,10 +481,10 @@ static void udf_table_free_blocks(struct super_block *sb,
479481
__udf_add_aext(table, &epos, &eloc, elen, 1);
480482
}
481483

484+
error_return:
482485
brelse(epos.bh);
483486
brelse(oepos.bh);
484487

485-
error_return:
486488
mutex_unlock(&sbi->s_alloc_mutex);
487489
return;
488490
}
@@ -498,6 +500,7 @@ static int udf_table_prealloc_blocks(struct super_block *sb,
498500
struct extent_position epos;
499501
int8_t etype = -1;
500502
struct udf_inode_info *iinfo;
503+
int ret = 0;
501504

502505
if (first_block >= sbi->s_partmaps[partition].s_partition_len)
503506
return 0;
@@ -516,11 +519,14 @@ static int udf_table_prealloc_blocks(struct super_block *sb,
516519
epos.bh = NULL;
517520
eloc.logicalBlockNum = 0xFFFFFFFF;
518521

519-
while (first_block != eloc.logicalBlockNum &&
520-
(etype = udf_next_aext(table, &epos, &eloc, &elen, 1)) != -1) {
522+
while (first_block != eloc.logicalBlockNum) {
523+
ret = udf_next_aext(table, &epos, &eloc, &elen, &etype, 1);
524+
if (ret < 0)
525+
goto err_out;
526+
if (ret == 0)
527+
break;
521528
udf_debug("eloc=%u, elen=%u, first_block=%u\n",
522529
eloc.logicalBlockNum, elen, first_block);
523-
; /* empty loop body */
524530
}
525531

526532
if (first_block == eloc.logicalBlockNum) {
@@ -539,6 +545,7 @@ static int udf_table_prealloc_blocks(struct super_block *sb,
539545
alloc_count = 0;
540546
}
541547

548+
err_out:
542549
brelse(epos.bh);
543550

544551
if (alloc_count)
@@ -560,6 +567,7 @@ static udf_pblk_t udf_table_new_block(struct super_block *sb,
560567
struct extent_position epos, goal_epos;
561568
int8_t etype;
562569
struct udf_inode_info *iinfo = UDF_I(table);
570+
int ret = 0;
563571

564572
*err = -ENOSPC;
565573

@@ -583,8 +591,10 @@ static udf_pblk_t udf_table_new_block(struct super_block *sb,
583591
epos.block = iinfo->i_location;
584592
epos.bh = goal_epos.bh = NULL;
585593

586-
while (spread &&
587-
(etype = udf_next_aext(table, &epos, &eloc, &elen, 1)) != -1) {
594+
while (spread) {
595+
ret = udf_next_aext(table, &epos, &eloc, &elen, &etype, 1);
596+
if (ret <= 0)
597+
break;
588598
if (goal >= eloc.logicalBlockNum) {
589599
if (goal < eloc.logicalBlockNum +
590600
(elen >> sb->s_blocksize_bits))
@@ -612,9 +622,11 @@ static udf_pblk_t udf_table_new_block(struct super_block *sb,
612622

613623
brelse(epos.bh);
614624

615-
if (spread == 0xFFFFFFFF) {
625+
if (ret < 0 || spread == 0xFFFFFFFF) {
616626
brelse(goal_epos.bh);
617627
mutex_unlock(&sbi->s_alloc_mutex);
628+
if (ret < 0)
629+
*err = ret;
618630
return 0;
619631
}
620632

fs/udf/directory.c

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -166,13 +166,19 @@ static struct buffer_head *udf_fiiter_bread_blk(struct udf_fileident_iter *iter)
166166
*/
167167
static int udf_fiiter_advance_blk(struct udf_fileident_iter *iter)
168168
{
169+
int8_t etype = -1;
170+
int err = 0;
171+
169172
iter->loffset++;
170173
if (iter->loffset < DIV_ROUND_UP(iter->elen, 1<<iter->dir->i_blkbits))
171174
return 0;
172175

173176
iter->loffset = 0;
174-
if (udf_next_aext(iter->dir, &iter->epos, &iter->eloc, &iter->elen, 1)
175-
!= (EXT_RECORDED_ALLOCATED >> 30)) {
177+
err = udf_next_aext(iter->dir, &iter->epos, &iter->eloc,
178+
&iter->elen, &etype, 1);
179+
if (err < 0)
180+
return err;
181+
else if (err == 0 || etype != (EXT_RECORDED_ALLOCATED >> 30)) {
176182
if (iter->pos == iter->dir->i_size) {
177183
iter->elen = 0;
178184
return 0;
@@ -240,6 +246,7 @@ int udf_fiiter_init(struct udf_fileident_iter *iter, struct inode *dir,
240246
{
241247
struct udf_inode_info *iinfo = UDF_I(dir);
242248
int err = 0;
249+
int8_t etype;
243250

244251
iter->dir = dir;
245252
iter->bh[0] = iter->bh[1] = NULL;
@@ -259,9 +266,9 @@ int udf_fiiter_init(struct udf_fileident_iter *iter, struct inode *dir,
259266
goto out;
260267
}
261268

262-
if (inode_bmap(dir, iter->pos >> dir->i_blkbits, &iter->epos,
263-
&iter->eloc, &iter->elen, &iter->loffset) !=
264-
(EXT_RECORDED_ALLOCATED >> 30)) {
269+
err = inode_bmap(dir, iter->pos >> dir->i_blkbits, &iter->epos,
270+
&iter->eloc, &iter->elen, &iter->loffset, &etype);
271+
if (err <= 0 || etype != (EXT_RECORDED_ALLOCATED >> 30)) {
265272
if (pos == dir->i_size)
266273
return 0;
267274
udf_err(dir->i_sb,
@@ -457,6 +464,7 @@ int udf_fiiter_append_blk(struct udf_fileident_iter *iter)
457464
sector_t block;
458465
uint32_t old_elen = iter->elen;
459466
int err;
467+
int8_t etype;
460468

461469
if (WARN_ON_ONCE(iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB))
462470
return -EINVAL;
@@ -471,8 +479,9 @@ int udf_fiiter_append_blk(struct udf_fileident_iter *iter)
471479
udf_fiiter_update_elen(iter, old_elen);
472480
return err;
473481
}
474-
if (inode_bmap(iter->dir, block, &iter->epos, &iter->eloc, &iter->elen,
475-
&iter->loffset) != (EXT_RECORDED_ALLOCATED >> 30)) {
482+
err = inode_bmap(iter->dir, block, &iter->epos, &iter->eloc, &iter->elen,
483+
&iter->loffset, &etype);
484+
if (err <= 0 || etype != (EXT_RECORDED_ALLOCATED >> 30)) {
476485
udf_err(iter->dir->i_sb,
477486
"block %llu not allocated in directory (ino %lu)\n",
478487
(unsigned long long)block, iter->dir->i_ino);

0 commit comments

Comments
 (0)