Hi Eric, On Mon, Feb 15, 2021 at 07:04:25PM -0600, Eric Sandeen wrote: > On 10/12/20 11:06 PM, Gao Xiang wrote: > > Check stripe numbers in calc_stripe_factors() by using > > xfs_validate_stripe_geometry(). > > > > Signed-off-by: Gao Xiang <hsiangkao@xxxxxxxxxx> > > Hm, unless I have made a mistake, this seems to allow an invalid > stripe specification. > > Without this patch, this fails: > > # mkfs/mkfs.xfs -f -d su=4097,sw=1 /dev/loop0 > data su must be a multiple of the sector size (512) > > With the patch: > > # mkfs/mkfs.xfs -f -d su=4097,sw=1 /dev/loop0 > meta-data=/dev/loop0 isize=512 agcount=8, agsize=32768 blks > = sectsz=512 attr=2, projid32bit=1 > = crc=1 finobt=1, sparse=1, rmapbt=0 > = reflink=1 bigtime=0 > data = bsize=4096 blocks=262144, imaxpct=25 > = sunit=1 swidth=1 blks > naming =version 2 bsize=4096 ascii-ci=0, ftype=1 > log =internal log bsize=4096 blocks=2560, version=2 > = sectsz=512 sunit=1 blks, lazy-count=1 > realtime =none extsz=4096 blocks=0, rtextents=0 > Discarding blocks...Done. > > When you are back from holiday, can you check? No big rush. I'm back from holiday today. I think the problem is in "if (dsu || dsw) {" it turns into "dsunit = (int)BTOBBT(dsu);" anyway, and then if (!libxfs_validate_stripe_geometry(NULL, BBTOB(dsunit), BBTOB(dswidth), cfg->sectorsize, false)) so dsu isn't checked with sectorsize in advance before it turns into BB. the fix seems simple though, 1) turn dsunit and dswidth into bytes rather than BB, but I have no idea the range of these 2 varibles, since I saw "if (big_dswidth > INT_MAX) {" but the big_dswidth was also in BB as well, if we turn these into bytes, and such range cannot be guarunteed... 2) recover the previous code snippet and check dsu in advance: if (dsu % cfg->sectorsize) { fprintf(stderr, _("data su must be a multiple of the sector size (%d)\n"), cfg->sectorsize); usage(); } btw, do we have some range test about these variables? I could rearrange the code snippet, but I'm not sure if it could introduce some new potential regression as well... Thanks, Gao Xiang > > Thanks, > -Eric > > > --- > > libxfs/libxfs_api_defs.h | 1 + > > mkfs/xfs_mkfs.c | 23 +++++++---------------- > > 2 files changed, 8 insertions(+), 16 deletions(-) > > > > diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h > > index e7e42e93..306d0deb 100644 > > --- a/libxfs/libxfs_api_defs.h > > +++ b/libxfs/libxfs_api_defs.h > > @@ -188,6 +188,7 @@ > > #define xfs_trans_roll_inode libxfs_trans_roll_inode > > #define xfs_trans_roll libxfs_trans_roll > > > > +#define xfs_validate_stripe_geometry libxfs_validate_stripe_geometry > > #define xfs_verify_agbno libxfs_verify_agbno > > #define xfs_verify_agino libxfs_verify_agino > > #define xfs_verify_cksum libxfs_verify_cksum > > diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c > > index 8fe149d7..aec40c1f 100644 > > --- a/mkfs/xfs_mkfs.c > > +++ b/mkfs/xfs_mkfs.c > > @@ -2305,12 +2305,6 @@ _("both data su and data sw options must be specified\n")); > > usage(); > > } > > > > - if (dsu % cfg->sectorsize) { > > - fprintf(stderr, > > -_("data su must be a multiple of the sector size (%d)\n"), cfg->sectorsize); > > - usage(); > > - } > > - > > dsunit = (int)BTOBBT(dsu); > > big_dswidth = (long long int)dsunit * dsw; > > if (big_dswidth > INT_MAX) { > > @@ -2322,13 +2316,9 @@ _("data stripe width (%lld) is too large of a multiple of the data stripe unit ( > > dswidth = big_dswidth; > > } > > > > - if ((dsunit && !dswidth) || (!dsunit && dswidth) || > > - (dsunit && (dswidth % dsunit != 0))) { > > - fprintf(stderr, > > -_("data stripe width (%d) must be a multiple of the data stripe unit (%d)\n"), > > - dswidth, dsunit); > > + if (!libxfs_validate_stripe_geometry(NULL, BBTOB(dsunit), BBTOB(dswidth), > > + cfg->sectorsize, false)) > > usage(); > > - } > > > > /* If sunit & swidth were manually specified as 0, same as noalign */ > > if ((cli_opt_set(&dopts, D_SUNIT) || cli_opt_set(&dopts, D_SU)) && > > @@ -2344,11 +2334,12 @@ _("data stripe width (%d) must be a multiple of the data stripe unit (%d)\n"), > > > > /* if no stripe config set, use the device default */ > > if (!dsunit) { > > - /* Ignore nonsense from device. XXX add more validation */ > > - if (ft->dsunit && ft->dswidth == 0) { > > + /* Ignore nonsense from device report. */ > > + if (!libxfs_validate_stripe_geometry(NULL, BBTOB(ft->dsunit), > > + BBTOB(ft->dswidth), 0, true)) { > > fprintf(stderr, > > -_("%s: Volume reports stripe unit of %d bytes and stripe width of 0, ignoring.\n"), > > - progname, BBTOB(ft->dsunit)); > > +_("%s: Volume reports invalid stripe unit (%d) and stripe width (%d), ignoring.\n"), > > + progname, BBTOB(ft->dsunit), BBTOB(ft->dswidth)); > > ft->dsunit = 0; > > ft->dswidth = 0; > > } else { > > >