Message ID | 157845709897.84011.1433283906403215456.stgit@magnolia (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | xfs: fix buf log item memory corruption on non-amd64 | expand |
On Tue, Jan 07, 2020 at 08:18:19PM -0800, Darrick J. Wong wrote: > diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c > index 3984779e5911..bfbe8a5b8959 100644 > --- a/fs/xfs/xfs_buf_item.c > +++ b/fs/xfs/xfs_buf_item.c > @@ -761,18 +761,25 @@ xfs_buf_item_init( > * buffer. This makes the implementation as simple as possible. > */ > error = xfs_buf_item_get_format(bip, bp->b_map_count); > - ASSERT(error == 0); > - if (error) { /* to stop gcc throwing set-but-unused warnings */ > - kmem_cache_free(xfs_buf_item_zone, bip); > - return error; > + if (error) { > + xfs_err(mp, "could not allocate buffer item, err=%d", error); > + goto err; > } The error handling here is weird, as xfs_buf_item_get_format can't fail to start with. I'd rather see a prep patch removing the bogus check for the kmem_zalloc and change the return value from xfs_buf_item_get_format to void. Otherwise the patch looks good.
On Wed, Jan 08, 2020 at 12:51:31AM -0800, Christoph Hellwig wrote: > On Tue, Jan 07, 2020 at 08:18:19PM -0800, Darrick J. Wong wrote: > > diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c > > index 3984779e5911..bfbe8a5b8959 100644 > > --- a/fs/xfs/xfs_buf_item.c > > +++ b/fs/xfs/xfs_buf_item.c > > @@ -761,18 +761,25 @@ xfs_buf_item_init( > > * buffer. This makes the implementation as simple as possible. > > */ > > error = xfs_buf_item_get_format(bip, bp->b_map_count); > > - ASSERT(error == 0); > > - if (error) { /* to stop gcc throwing set-but-unused warnings */ > > - kmem_cache_free(xfs_buf_item_zone, bip); > > - return error; > > + if (error) { > > + xfs_err(mp, "could not allocate buffer item, err=%d", error); > > + goto err; > > } > > The error handling here is weird, as xfs_buf_item_get_format can't fail > to start with. I'd rather see a prep patch removing the bogus check > for the kmem_zalloc and change the return value from > xfs_buf_item_get_format to void. > > Otherwise the patch looks good. Ok. --D
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index 3984779e5911..bfbe8a5b8959 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c @@ -761,18 +761,25 @@ xfs_buf_item_init( * buffer. This makes the implementation as simple as possible. */ error = xfs_buf_item_get_format(bip, bp->b_map_count); - ASSERT(error == 0); - if (error) { /* to stop gcc throwing set-but-unused warnings */ - kmem_cache_free(xfs_buf_item_zone, bip); - return error; + if (error) { + xfs_err(mp, "could not allocate buffer item, err=%d", error); + goto err; } - for (i = 0; i < bip->bli_format_count; i++) { chunks = DIV_ROUND_UP(BBTOB(bp->b_maps[i].bm_len), XFS_BLF_CHUNK); map_size = DIV_ROUND_UP(chunks, NBWORD); + if (map_size > XFS_BLF_DATAMAP_SIZE) { + xfs_err(mp, + "buffer item dirty bitmap (%u uints) too small to reflect %u bytes!", + map_size, + BBTOB(bp->b_maps[i].bm_len)); + error = -EFSCORRUPTED; + goto err; + } + bip->bli_formats[i].blf_type = XFS_LI_BUF; bip->bli_formats[i].blf_blkno = bp->b_maps[i].bm_bn; bip->bli_formats[i].blf_len = bp->b_maps[i].bm_len; @@ -782,6 +789,9 @@ xfs_buf_item_init( bp->b_log_item = bip; xfs_buf_hold(bp); return 0; +err: + kmem_cache_free(xfs_buf_item_zone, bip); + return error; } @@ -805,6 +815,9 @@ xfs_buf_item_log_segment( uint end_bit; uint mask; + ASSERT(first < XFS_BLF_DATAMAP_SIZE * XFS_BLF_CHUNK * NBWORD); + ASSERT(last < XFS_BLF_DATAMAP_SIZE * XFS_BLF_CHUNK * NBWORD); + /* * Convert byte offsets to bit numbers. */