The branch stable/13 has been updated by kib:

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

commit def8b2b427ea5bff099e70b2a8351312be9e997a
Author:     Konstantin Belousov <[email protected]>
AuthorDate: 2021-03-01 15:24:11 +0000
Commit:     Konstantin Belousov <[email protected]>
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);
 }
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/dev-commits-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to