git: def8b2b427ea - stable/13 - FFS extattr: fix handling of the tail

Konstantin Belousov kib at FreeBSD.org
Thu Mar 4 19:24:57 UTC 2021


The branch stable/13 has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=def8b2b427ea5bff099e70b2a8351312be9e997a

commit def8b2b427ea5bff099e70b2a8351312be9e997a
Author:     Konstantin Belousov <kib at FreeBSD.org>
AuthorDate: 2021-03-01 15:24:11 +0000
Commit:     Konstantin Belousov <kib at FreeBSD.org>
CommitDate: 2021-03-04 19:07:25 +0000

    FFS extattr: fix handling of the tail
    
    (cherry picked from commit 8742817ba62ec604156c139727155d36f5fbad06)
---
 sys/ufs/ffs/ffs_vnops.c | 22 ++++++++++++++++------
 1 file changed, 16 insertions(+), 6 deletions(-)

diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c
index af03b369a280..582ccccc2e12 100644
--- a/sys/ufs/ffs/ffs_vnops.c
+++ b/sys/ufs/ffs/ffs_vnops.c
@@ -1346,13 +1346,20 @@ ffs_rdextattr(u_char **p, struct vnode *vp, struct thread *td)
 	/* Validate disk xattrfile contents. */
 	for (eap = (void *)eae, eaend = (void *)(eae + easize); eap < eaend;
 	    eap = eapnext) {
+		/* Detect zeroed out tail */
+		if (eap->ea_length < sizeof(*eap) || eap->ea_length == 0) {
+			easize = (const u_char *)eap - eae;
+			break;
+		}
+			
 		eapnext = EXTATTR_NEXT(eap);
-		/* Bogusly short entry or bogusly long entry. */
-		if (eap->ea_length < sizeof(*eap) || eapnext > eaend) {
+		/* Bogusly long entry. */
+		if (eapnext > eaend) {
 			free(eae, M_TEMP);
 			return (EINTEGRITY);
 		}
 	}
+	ip->i_ea_len = easize;
 	*p = eae;
 	return (0);
 }
@@ -1407,7 +1414,6 @@ ffs_open_ea(struct vnode *vp, struct ucred *cred, struct thread *td)
 		ffs_unlock_ea(vp);
 		return (error);
 	}
-	ip->i_ea_len = dp->di_extsize;
 	ip->i_ea_error = 0;
 	ip->i_ea_refs++;
 	ffs_unlock_ea(vp);
@@ -1426,6 +1432,7 @@ ffs_close_ea(struct vnode *vp, int commit, struct ucred *cred, struct thread *td
 	struct ufs2_dinode *dp;
 	size_t ea_len, tlen;
 	int error, i, lcnt;
+	bool truncate;
 
 	ip = VTOI(vp);
 
@@ -1436,6 +1443,7 @@ ffs_close_ea(struct vnode *vp, int commit, struct ucred *cred, struct thread *td
 	}
 	dp = ip->i_din2;
 	error = ip->i_ea_error;
+	truncate = false;
 	if (commit && error == 0) {
 		ASSERT_VOP_ELOCKED(vp, "ffs_close_ea commit");
 		if (cred == NOCRED)
@@ -1452,12 +1460,12 @@ ffs_close_ea(struct vnode *vp, int commit, struct ucred *cred, struct thread *td
 
 		liovec[0].iov_base = ip->i_ea_area;
 		liovec[0].iov_len = ip->i_ea_len;
-		for (i = 1, tlen = ea_len; i < lcnt; i++) {
+		for (i = 1, tlen = ea_len - ip->i_ea_len; i < lcnt; i++) {
 			liovec[i].iov_base = __DECONST(void *, zero_region);
 			liovec[i].iov_len = MIN(ZERO_REGION_SIZE, tlen);
 			tlen -= liovec[i].iov_len;
 		}
-		MPASS(tlen == ip->i_ea_len);
+		MPASS(tlen == 0);
 
 		luio.uio_iov = liovec;
 		luio.uio_offset = 0;
@@ -1466,6 +1474,8 @@ ffs_close_ea(struct vnode *vp, int commit, struct ucred *cred, struct thread *td
 		luio.uio_rw = UIO_WRITE;
 		luio.uio_td = td;
 		error = ffs_extwrite(vp, &luio, IO_EXT | IO_SYNC, cred);
+		if (error == 0 && ip->i_ea_len == 0)
+			truncate = true;
 	}
 	if (--ip->i_ea_refs == 0) {
 		free(ip->i_ea_area, M_TEMP);
@@ -1475,7 +1485,7 @@ ffs_close_ea(struct vnode *vp, int commit, struct ucred *cred, struct thread *td
 	}
 	ffs_unlock_ea(vp);
 
-	if (commit && error == 0 && ip->i_ea_len == 0)
+	if (truncate)
 		ffs_truncate(vp, 0, IO_EXT, cred);
 	return (error);
 }


More information about the dev-commits-src-branches mailing list