From: Jan Kara jack@suse.cz
commit 19fd80de0a8b5170ef34704c8984cca920dffa59 upstream
When adding extent to a file fails, so far we've silently squelshed the error. Make sure to propagate it up properly.
Signed-off-by: Jan Kara jack@suse.cz Signed-off-by: Vladislav Efanov VEfanov@ispras.ru --- Syzkaller reports this problem in 5.10 stable release. The problem has been fixed by the following patch which can be cleanly applied to the 5.10 branch. fs/udf/inode.c | 41 +++++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 14 deletions(-)
diff --git a/fs/udf/inode.c b/fs/udf/inode.c index d114774ecdea..3e11190b7118 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -57,15 +57,15 @@ static int udf_update_inode(struct inode *, int); static int udf_sync_inode(struct inode *inode); static int udf_alloc_i_data(struct inode *inode, size_t size); static sector_t inode_getblk(struct inode *, sector_t, int *, int *); -static int8_t udf_insert_aext(struct inode *, struct extent_position, - struct kernel_lb_addr, uint32_t); +static int udf_insert_aext(struct inode *, struct extent_position, + struct kernel_lb_addr, uint32_t); static void udf_split_extents(struct inode *, int *, int, udf_pblk_t, struct kernel_long_ad *, int *); static void udf_prealloc_extents(struct inode *, int, int, struct kernel_long_ad *, int *); static void udf_merge_extents(struct inode *, struct kernel_long_ad *, int *); -static void udf_update_extents(struct inode *, struct kernel_long_ad *, int, - int, struct extent_position *); +static int udf_update_extents(struct inode *, struct kernel_long_ad *, int, + int, struct extent_position *); static int udf_get_block(struct inode *, sector_t, struct buffer_head *, int);
static void __udf_clear_extent_cache(struct inode *inode) @@ -887,7 +887,9 @@ static sector_t inode_getblk(struct inode *inode, sector_t block, /* write back the new extents, inserting new extents if the new number * of extents is greater than the old number, and deleting extents if * the new number of extents is less than the old number */ - udf_update_extents(inode, laarr, startnum, endnum, &prev_epos); + *err = udf_update_extents(inode, laarr, startnum, endnum, &prev_epos); + if (*err < 0) + goto out_free;
newblock = udf_get_pblock(inode->i_sb, newblocknum, iinfo->i_location.partitionReferenceNum, 0); @@ -1155,21 +1157,30 @@ static void udf_merge_extents(struct inode *inode, struct kernel_long_ad *laarr, } }
-static void udf_update_extents(struct inode *inode, struct kernel_long_ad *laarr, - int startnum, int endnum, - struct extent_position *epos) +static int udf_update_extents(struct inode *inode, struct kernel_long_ad *laarr, + int startnum, int endnum, + struct extent_position *epos) { int start = 0, i; struct kernel_lb_addr tmploc; uint32_t tmplen; + int err;
if (startnum > endnum) { for (i = 0; i < (startnum - endnum); i++) udf_delete_aext(inode, *epos); } else if (startnum < endnum) { for (i = 0; i < (endnum - startnum); i++) { - udf_insert_aext(inode, *epos, laarr[i].extLocation, - laarr[i].extLength); + err = udf_insert_aext(inode, *epos, + laarr[i].extLocation, + laarr[i].extLength); + /* + * If we fail here, we are likely corrupting the extent + * list and leaking blocks. At least stop early to + * limit the damage. + */ + if (err < 0) + return err; udf_next_aext(inode, epos, &laarr[i].extLocation, &laarr[i].extLength, 1); start++; @@ -1181,6 +1192,7 @@ static void udf_update_extents(struct inode *inode, struct kernel_long_ad *laarr udf_write_aext(inode, epos, &laarr[i].extLocation, laarr[i].extLength, 1); } + return 0; }
struct buffer_head *udf_bread(struct inode *inode, udf_pblk_t block, @@ -2215,12 +2227,13 @@ int8_t udf_current_aext(struct inode *inode, struct extent_position *epos, return etype; }
-static int8_t udf_insert_aext(struct inode *inode, struct extent_position epos, - struct kernel_lb_addr neloc, uint32_t nelen) +static int udf_insert_aext(struct inode *inode, struct extent_position epos, + struct kernel_lb_addr neloc, uint32_t nelen) { struct kernel_lb_addr oeloc; uint32_t oelen; int8_t etype; + int err;
if (epos.bh) get_bh(epos.bh); @@ -2230,10 +2243,10 @@ static int8_t udf_insert_aext(struct inode *inode, struct extent_position epos, neloc = oeloc; nelen = (etype << 30) | oelen; } - udf_add_aext(inode, &epos, &neloc, nelen, 1); + err = udf_add_aext(inode, &epos, &neloc, nelen, 1); brelse(epos.bh);
- return (nelen >> 30); + return err; }
int8_t udf_delete_aext(struct inode *inode, struct extent_position epos)
Hi Greg,
Our syzbot found the this issue on v5.10, could you please pick it up for v5.10?
在 2023/9/5 15:14, Greg Kroah-Hartman 写道:
On Tue, Sep 05, 2023 at 02:57:48PM +0800, Li Nan wrote:
Hi Greg,
Our syzbot found the this issue on v5.10, could you please pick it up for v5.10?
What issue? Pick what up?
There's no context here :( .
I am so sorry I forgot to attach the patch. The patch is: https://lore.kernel.org/all/20230815113453.2213555-1-VEfanov@ispras.ru/
It fix the bug: https://patchew.org/linux/20230120091028.1591622-1-VEfanov@ispras.ru/
On Tue, Sep 05, 2023 at 03:49:25PM +0800, Li Nan wrote:
在 2023/9/5 15:14, Greg Kroah-Hartman 写道:
On Tue, Sep 05, 2023 at 02:57:48PM +0800, Li Nan wrote:
Hi Greg,
Our syzbot found the this issue on v5.10, could you please pick it up for v5.10?
What issue? Pick what up?
There's no context here :( .
I am so sorry I forgot to attach the patch. The patch is: https://lore.kernel.org/all/20230815113453.2213555-1-VEfanov@ispras.ru/
Odd, I missed that somehow.
Anyway, no, sorry, I can't just take it for 5.10, as you would have a regression if you moved to a newer kernel release. Please submit a working version for all stable kernels 5.10 and newer, if you want us to be able to accept this.
thanks,
greg k-h
On Tue, Aug 15, 2023 at 02:34:53PM +0300, Vladislav Efanov wrote:
From: Jan Kara jack@suse.cz
commit 19fd80de0a8b5170ef34704c8984cca920dffa59 upstream
When adding extent to a file fails, so far we've silently squelshed the error. Make sure to propagate it up properly.
Signed-off-by: Jan Kara jack@suse.cz Signed-off-by: Vladislav Efanov VEfanov@ispras.ru
Syzkaller reports this problem in 5.10 stable release. The problem has been fixed by the following patch which can be cleanly applied to the 5.10 branch. fs/udf/inode.c | 41 +++++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 14 deletions(-)
Sorry I missed this, but we need versions for 5.10 and newer if we were to be able to take this.
thanks,
greg k-h
linux-stable-mirror@lists.linaro.org