diff options
author | kib <kib@FreeBSD.org> | 2012-06-21 09:20:07 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2012-06-21 09:20:07 +0000 |
commit | 7e14b6838bca79d6c18eb00c4fe8c0a3e3b066ff (patch) | |
tree | 01adac257d485894b5ea4edc255ff795afc07789 /sys/ufs/ffs | |
parent | df9f3d2faa1df2bb13d274183876fe227e259a65 (diff) | |
download | FreeBSD-src-7e14b6838bca79d6c18eb00c4fe8c0a3e3b066ff.zip FreeBSD-src-7e14b6838bca79d6c18eb00c4fe8c0a3e3b066ff.tar.gz |
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.
Reported and tested by: pho
MFC after: 1 week
Diffstat (limited to 'sys/ufs/ffs')
-rw-r--r-- | sys/ufs/ffs/ffs_vnops.c | 10 |
1 files changed, 7 insertions, 3 deletions
diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c index 6259911..ee6733b 100644 --- a/sys/ufs/ffs/ffs_vnops.c +++ b/sys/ufs/ffs/ffs_vnops.c @@ -1648,7 +1648,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); @@ -1667,6 +1668,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) { @@ -1684,7 +1689,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) @@ -1712,7 +1716,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) |