--- a/sys/vfs/hpfs/hpfs_alsubr.c +++ b/sys/vfs/hpfs/hpfs_alsubr.c @@ -46,6 +46,9 @@ #define AE_DONE 0 /* Nothing to change */ #define AE_SPLIT 2 /* Split was done, ranp is valid */ +/* Max AlSec b-tree depth we are willing to walk (crafted-image guard). */ +#define HPFS_MAXALSECDEPTH 32 + int hpfs_addextentr (struct hpfsmount *, lsn_t, alleaf_t *, alnode_t *, u_long *); int hpfs_allocalsec (struct hpfsmount *, lsn_t, struct buf **); @@ -739,7 +742,8 @@ * THE TREE. */ int -hpfs_truncatealblk(struct hpfsmount *hpmp, alblk_t *abp, lsn_t bn, int *resp) +hpfs_truncatealblk(struct hpfsmount *hpmp, alblk_t *abp, lsn_t bn, int *resp, + int depth) { int error; alleaf_t *alp; @@ -758,6 +762,11 @@ anp = AB_LASTANP(abp); while (abp->ab_busycnt && (bn <= anp->an_nextoff)) { + if (depth >= HPFS_MAXALSECDEPTH) { + kprintf("hpfs_truncatealblk: " + "alsec tree too deep\n"); + return (EINVAL); + } dprintf(("hpfs_truncatealblk: AlNode: [0x%x,0x%x] \n", anp->an_nextoff,anp->an_lsn)); @@ -768,7 +777,8 @@ asp = (alsec_t *)bp->b_data; error = hpfs_truncatealblk (hpmp, - &asp->as_ab, bn, resp); + &asp->as_ab, bn, resp, + depth + 1); if (error) { brelse(bp); return (error); --- a/sys/vfs/hpfs/hpfs_subr.c +++ b/sys/vfs/hpfs/hpfs_subr.c @@ -771,7 +771,7 @@ dprintf(("blen: 0x%x -> 0x%x\n", oldblen, newblen)); - error = hpfs_truncatealblk (hpmp, &hp->h_fn.fn_ab, newblen, &pf); + error = hpfs_truncatealblk (hpmp, &hp->h_fn.fn_ab, newblen, &pf, 0); if (error) return (error); if (pf) { --- a/sys/vfs/hpfs/hpfs_subr.h +++ b/sys/vfs/hpfs/hpfs_subr.h @@ -79,5 +79,6 @@ hpfs_breadstruct(hpmp, lsn, D_BSIZE, D_MAGIC, bpp) int hpfs_hpbmap (struct hpfsnode *, daddr_t, daddr_t *, int *); -int hpfs_truncatealblk (struct hpfsmount *, alblk_t *, lsn_t,int *); +int hpfs_truncatealblk (struct hpfsmount *, alblk_t *, lsn_t,int *, + int); int hpfs_addextent (struct hpfsmount *, struct hpfsnode *, u_long);