⬢ DragonFlyBSD Kernel Audit
DF-3101 / fix.diff
← back to finding ↓ download raw
--- 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);