* [PATCH] xfs: eliminate the potential overflow risk in xfs_da_grow_inode_int
@ 2022-09-10 2:38 Stephen Zhang
2022-09-11 22:38 ` Dave Chinner
0 siblings, 1 reply; 2+ messages in thread
From: Stephen Zhang @ 2022-09-10 2:38 UTC (permalink / raw)
To: djwong, dchinner, chandan.babu, yang.guang5
Cc: zhangshida, starzhangzsd, linux-xfs
The problem lies in the for-loop of xfs_da_grow_inode_int:
======
for(){
nmap = min(XFS_BMAP_MAX_NMAP, count);
...
error = xfs_bmapi_write(...,&mapp[mapi], &nmap);//(..., $1, $2)
...
mapi += nmap;
}
=====
where $1 stands for the start address of the array,
while $2 is used to indicate the size of the array.
The array $1 will advanced by $nmap in each iteration after
the allocation of extents.
But the size $2 still remains constant, which is determined by
min(XFS_BMAP_MAX_NMAP, count).
Hence there is a risk of overflow when the remained space in
the array is less than $2.
So variablize the array size $2 correspondingly in each iteration
to eliminate the risk.
Signed-off-by: Shida Zhang <zhangshida@kylinos.cn>
---
fs/xfs/libxfs/xfs_da_btree.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/xfs/libxfs/xfs_da_btree.c b/fs/xfs/libxfs/xfs_da_btree.c
index e7201dc68f43..3ef8c04624cc 100644
--- a/fs/xfs/libxfs/xfs_da_btree.c
+++ b/fs/xfs/libxfs/xfs_da_btree.c
@@ -2192,7 +2192,7 @@ xfs_da_grow_inode_int(
*/
mapp = kmem_alloc(sizeof(*mapp) * count, 0);
for (b = *bno, mapi = 0; b < *bno + count; ) {
- nmap = min(XFS_BMAP_MAX_NMAP, count);
+ nmap = min(XFS_BMAP_MAX_NMAP, count - mapi);
c = (int)(*bno + count - b);
error = xfs_bmapi_write(tp, dp, b, c,
xfs_bmapi_aflag(w)|XFS_BMAPI_METADATA,
--
2.25.1
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH] xfs: eliminate the potential overflow risk in xfs_da_grow_inode_int
2022-09-10 2:38 [PATCH] xfs: eliminate the potential overflow risk in xfs_da_grow_inode_int Stephen Zhang
@ 2022-09-11 22:38 ` Dave Chinner
0 siblings, 0 replies; 2+ messages in thread
From: Dave Chinner @ 2022-09-11 22:38 UTC (permalink / raw)
To: Stephen Zhang
Cc: djwong, dchinner, chandan.babu, yang.guang5, zhangshida,
linux-xfs
On Sat, Sep 10, 2022 at 10:38:39AM +0800, Stephen Zhang wrote:
> The problem lies in the for-loop of xfs_da_grow_inode_int:
> ======
> for(){
> nmap = min(XFS_BMAP_MAX_NMAP, count);
> ...
> error = xfs_bmapi_write(...,&mapp[mapi], &nmap);//(..., $1, $2)
> ...
> mapi += nmap;
> }
> =====
> where $1 stands for the start address of the array,
> while $2 is used to indicate the size of the array.
>
> The array $1 will advanced by $nmap in each iteration after
> the allocation of extents.
> But the size $2 still remains constant, which is determined by
> min(XFS_BMAP_MAX_NMAP, count).
>
> Hence there is a risk of overflow when the remained space in
> the array is less than $2.
> So variablize the array size $2 correspondingly in each iteration
> to eliminate the risk.
Except that xfs_bmapi_write() won't overrun the array....
> Signed-off-by: Shida Zhang <zhangshida@kylinos.cn>
> ---
> fs/xfs/libxfs/xfs_da_btree.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/fs/xfs/libxfs/xfs_da_btree.c b/fs/xfs/libxfs/xfs_da_btree.c
> index e7201dc68f43..3ef8c04624cc 100644
> --- a/fs/xfs/libxfs/xfs_da_btree.c
> +++ b/fs/xfs/libxfs/xfs_da_btree.c
> @@ -2192,7 +2192,7 @@ xfs_da_grow_inode_int(
> */
> mapp = kmem_alloc(sizeof(*mapp) * count, 0);
> for (b = *bno, mapi = 0; b < *bno + count; ) {
> - nmap = min(XFS_BMAP_MAX_NMAP, count);
> + nmap = min(XFS_BMAP_MAX_NMAP, count - mapi);
> c = (int)(*bno + count - b);
> error = xfs_bmapi_write(tp, dp, b, c,
> xfs_bmapi_aflag(w)|XFS_BMAPI_METADATA,
... because we've allocated a mapp array large enough for one extent
map per filesystem block.
The line:
c = (int)(*bno + count - b);
calculates the maximum length of the extent remaining to map, and
hence the maximum number of blocks we might need to map. We're
guaranteed that the array is large enough for all single block maps,
and xfs_bmapi_write() will never overrun the array because it doesn't
map extents beyond the length requested. IOWs, there isn't an array
overrun bug here even though we don't trim the requested number of
maps on the last call.
So the question remains: Why do we need *two* calculations that
calculate the remaining number of blocks to map here? i.e. surely
all we need is this:
- nmap = min(XFS_BMAP_MAX_NMAP, count);
c = (int)(*bno + count - b);
+ nmap = min(XFS_BMAP_MAX_NMAP, c);
Cheers,
Dave.
--
Dave Chinner
david@fromorbit.com
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2022-09-11 22:38 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-09-10 2:38 [PATCH] xfs: eliminate the potential overflow risk in xfs_da_grow_inode_int Stephen Zhang
2022-09-11 22:38 ` Dave Chinner
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).