From 90ea8cdc22b9b2c37d0071fdc6481b0d6019eb43 Mon Sep 17 00:00:00 2001 From: kib Date: Thu, 28 Jun 2012 14:26:55 +0000 Subject: [PATCH] Fix unbounded-length malloc, controlled from usermode. The added check is performed before exact size of the buffer is calculated, but the buffer cannot have size greater then the total space allocated for extended attributes. The existing check is executing with precise size, but it is too late, since buffer needs to be allocated in advance. Also, adapt to uio_resid being of ssize_t type. Use lblktosize instead of multiplying by fs block size by hand as well. git-svn-id: svn://svn.freebsd.org/base/stable/9@237713 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f --- sys/ufs/ffs/ffs_vnops.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c index 44529915b..5f4257474 100644 --- a/sys/ufs/ffs/ffs_vnops.c +++ b/sys/ufs/ffs/ffs_vnops.c @@ -1649,7 +1649,8 @@ vop_setextattr { struct inode *ip; struct fs *fs; uint32_t ealength, ul; - int ealen, olen, eapad1, eapad2, error, i, easize; + ssize_t ealen; + int olen, eapad1, eapad2, error, i, easize; u_char *eae, *p; ip = VTOI(ap->a_vp); @@ -1668,6 +1669,10 @@ vop_setextattr { if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY) return (EROFS); + ealen = ap->a_uio->uio_resid; + if (ealen < 0 || ealen > lblktosize(fs, NXADDR)) + return (EINVAL); + error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace, ap->a_cred, ap->a_td, VWRITE); if (error) { @@ -1685,7 +1690,6 @@ vop_setextattr { if (error) return (error); - ealen = ap->a_uio->uio_resid; ealength = sizeof(uint32_t) + 3 + strlen(ap->a_name); eapad1 = 8 - (ealength % 8); if (eapad1 == 8) @@ -1713,7 +1717,7 @@ vop_setextattr { easize += (ealength - ul); } } - if (easize > NXADDR * fs->fs_bsize) { + if (easize > lblktosize(fs, NXADDR)) { free(eae, M_TEMP); ffs_close_ea(ap->a_vp, 0, ap->a_cred, ap->a_td); if (ip->i_ea_area != NULL && ip->i_ea_error == 0) -- 2.45.0