]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/vfs/vfs_attrlist.c
xnu-3247.1.106.tar.gz
[apple/xnu.git] / bsd / vfs / vfs_attrlist.c
index 54d0323f84a0273ecd2f5f0683df6c45c733e7a6..38d7a3f2453d63833981b85e0de6266694f0cfd6 100644 (file)
@@ -473,7 +473,7 @@ struct getattrlist_attrtab {
 static struct getattrlist_attrtab getattrlist_common_tab[] = {
        {ATTR_CMN_NAME,         VATTR_BIT(va_name),             sizeof(struct attrreference),   KAUTH_VNODE_READ_ATTRIBUTES},
        {ATTR_CMN_DEVID,        0,                              sizeof(dev_t),                  KAUTH_VNODE_READ_ATTRIBUTES},
-       {ATTR_CMN_FSID,         VATTR_BIT(va_fsid),             sizeof(fsid_t),                 KAUTH_VNODE_READ_ATTRIBUTES},
+       {ATTR_CMN_FSID,         0,                              sizeof(fsid_t),                 KAUTH_VNODE_READ_ATTRIBUTES},
        {ATTR_CMN_OBJTYPE,      0,                              sizeof(fsobj_type_t),           KAUTH_VNODE_READ_ATTRIBUTES},
        {ATTR_CMN_OBJTAG,       0,                              sizeof(fsobj_tag_t),            KAUTH_VNODE_READ_ATTRIBUTES},
        {ATTR_CMN_OBJID,        VATTR_BIT(va_fileid) | VATTR_BIT(va_linkid), sizeof(fsobj_id_t), KAUTH_VNODE_READ_ATTRIBUTES},
@@ -1446,14 +1446,6 @@ attr_pack_common(vfs_context_t ctx, struct vnode *vp,  struct attrlist *alp,
                } else if (VATTR_IS_SUPPORTED(vap, va_fsid64)) {
                        ATTR_PACK8((*abp), vap->va_fsid64);
                        abp->actual.commonattr |= ATTR_CMN_FSID;
-               } else if (VATTR_IS_SUPPORTED(vap, va_fsid)) {
-                       fsid_t fsid;
-
-                       /* va_fsid is 32 bits */
-                       fsid.val[0] = vap->va_fsid;
-                       fsid.val[1] = 0;
-                       ATTR_PACK8((*abp), fsid);
-                       abp->actual.commonattr |= ATTR_CMN_FSID;
                } else if (!return_valid || pack_invalid) {
                        fsid_t fsid = {{0}};
 
@@ -2493,17 +2485,6 @@ vfs_attr_pack(vnode_t vp, uio_t uio, struct attrlist *alp, uint64_t options,
        error = getattrlist_setupvattr_all(alp, vap, v_type, &fixedsize,
            proc_is64bit(vfs_context_proc(ctx)));
 
-       /*
-        * Ugly hack to correctly report fsids. vs_fsid is 32 bits and
-        * there is va_fsid64 as well but filesystems have to say that
-        * both are supported so that the value can be used correctly.
-        * So we set va_fsid if the filesystem has only set va_fsid64.
-        */
-
-       if ((alp->commonattr & ATTR_CMN_FSID) &&
-           VATTR_IS_SUPPORTED(vap, va_fsid64))
-               VATTR_SET_SUPPORTED(vap, va_fsid);
-
        if (error) {
                VFS_DEBUG(ctx, vp,
                    "ATTRLIST - ERROR: setup for request failed");
@@ -3238,9 +3219,18 @@ readdirattr(vnode_t dvp, struct fd_vn_data *fvd, uio_t auio,
                }
 
                /*
-                * We have an iocount on the directory already
+                * We have an iocount on the directory already.
+                * 
+                * Note that we supply NOCROSSMOUNT to the namei call as we attempt to acquire
+                * a vnode for this particular entry.  This is because the native call will
+                * (likely) attempt to emit attributes based on its own metadata in order to avoid
+                * creating vnodes where posssible.  If the native call is not going to  walk
+                * up the vnode mounted-on chain in order to find the top-most mount point, then we
+                * should not either in this emulated readdir+getattrlist() approach.  We  
+                * will be responsible for setting DIR_MNTSTATUS_MNTPOINT on that directory that
+                * contains a mount point.  
                 */
-               NDINIT(&nd, LOOKUP, OP_GETATTR, AUDITVNPATH1 | USEDVP,
+               NDINIT(&nd, LOOKUP, OP_GETATTR, (AUDITVNPATH1 | USEDVP | NOCROSSMOUNT), 
                    UIO_SYSSPACE, CAST_USER_ADDR_T(name_buffer), ctx);
 
                nd.ni_dvp = dvp;
@@ -3738,7 +3728,8 @@ setattrlist_internal(vnode_t vp, struct setattrlist_args *uap, proc_t p, vfs_con
        }
        if (al.commonattr & ATTR_CMN_CHGTIME) {
                ATTR_UNPACK_TIME(va.va_change_time, proc_is64);
-               VATTR_SET_ACTIVE(&va, va_change_time);
+               al.commonattr &= ~ATTR_CMN_CHGTIME;
+               /*quietly ignore change time; advisory in man page*/
        }
        if (al.commonattr & ATTR_CMN_ACCTIME) {
                ATTR_UNPACK_TIME(va.va_access_time, proc_is64);
@@ -3772,6 +3763,10 @@ setattrlist_internal(vnode_t vp, struct setattrlist_args *uap, proc_t p, vfs_con
        if (al.commonattr & ATTR_CMN_FLAGS) {
                ATTR_UNPACK(va.va_flags);
                VATTR_SET_ACTIVE(&va, va_flags);
+#if CONFIG_MACF
+               if ((error = mac_vnode_check_setflags(ctx, vp, va.va_flags)) != 0)
+                       goto out;
+#endif
        }
        if (al.commonattr & ATTR_CMN_EXTENDED_SECURITY) {
 
@@ -3834,18 +3829,20 @@ setattrlist_internal(vnode_t vp, struct setattrlist_args *uap, proc_t p, vfs_con
                        volname = cursor;
                        ATTR_UNPACK(ar);        
                        /* attr_length cannot be 0! */
-                       if ((ar.attr_dataoffset < 0) || (ar.attr_length == 0)) {
+                       if ((ar.attr_dataoffset < 0) || (ar.attr_length == 0) ||
+                               (ar.attr_length > uap->bufferSize) ||
+                               (uap->bufferSize - ar.attr_length < (unsigned)ar.attr_dataoffset)) {
                                VFS_DEBUG(ctx, vp, "ATTRLIST - ERROR: bad offset supplied (2) ", ar.attr_dataoffset);
                                error = EINVAL;
                                goto out;
                        }
 
-                       volname += ar.attr_dataoffset;
-                       if ((volname + ar.attr_length) > bufend) {
+                       if (volname >= bufend - ar.attr_dataoffset - ar.attr_length) {
                                error = EINVAL;
                                VFS_DEBUG(ctx, vp, "ATTRLIST - ERROR: volume name too big for caller buffer");
                                goto out;
                        }
+                       volname += ar.attr_dataoffset;
                        /* guarantee NUL termination */
                        volname[ar.attr_length - 1] = 0;
                }