]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/vfs/vfs_attrlist.c
xnu-7195.50.7.100.1.tar.gz
[apple/xnu.git] / bsd / vfs / vfs_attrlist.c
index d7ba266002f07959ef72af8b330ef14336e55a96..c0bc4c89e29f7bb5f255bc8e44bbbe19c88f300a 100644 (file)
 #include <sys/file_internal.h>
 #include <sys/kauth.h>
 #include <sys/uio_internal.h>
 #include <sys/file_internal.h>
 #include <sys/kauth.h>
 #include <sys/uio_internal.h>
-#include <sys/malloc.h>
+#include <kern/kalloc.h>
 #include <sys/attr.h>
 #include <sys/sysproto.h>
 #include <sys/xattr.h>
 #include <sys/fsevents.h>
 #include <sys/attr.h>
 #include <sys/sysproto.h>
 #include <sys/xattr.h>
 #include <sys/fsevents.h>
-#include <kern/kalloc.h>
+#include <kern/zalloc.h>
 #include <miscfs/specfs/specdev.h>
 #include <security/audit/audit.h>
 
 #include <miscfs/specfs/specdev.h>
 #include <security/audit/audit.h>
 
 
 #define ATTR_TIME_SIZE  -1
 
 
 #define ATTR_TIME_SIZE  -1
 
+static int readdirattr(vnode_t, struct fd_vn_data *, uio_t, struct attrlist *,
+    uint64_t, int *, int *, vfs_context_t ctx) __attribute__((noinline));
+
+static void
+vattr_get_alt_data(vnode_t, struct attrlist *, struct vnode_attr *, int, int,
+    int, vfs_context_t) __attribute__((noinline));
+
+static void get_error_attributes(vnode_t, struct attrlist *, uint64_t, user_addr_t,
+    size_t, int, caddr_t, vfs_context_t) __attribute__((noinline));
+
+static int getvolattrlist(vfs_context_t, vnode_t, struct attrlist *, user_addr_t,
+    size_t, uint64_t, enum uio_seg, int) __attribute__((noinline));
+
+static int get_direntry(vfs_context_t, vnode_t, struct fd_vn_data *, int *,
+    struct direntry **) __attribute__((noinline));
+
 /*
  * Structure describing the state of an in-progress attrlist operation.
  */
 /*
  * Structure describing the state of an in-progress attrlist operation.
  */
@@ -130,8 +146,8 @@ attrlist_pack_variable2(struct _attrlist_buf *ab, const void *source, ssize_t co
         * Note that we may be able to pack the fixed width attref, but not
         * the variable (if there's no room).
         */
         * Note that we may be able to pack the fixed width attref, but not
         * the variable (if there's no room).
         */
-       ar.attr_dataoffset = ab->varcursor - ab->fixedcursor;
-       ar.attr_length = count + extcount;
+       ar.attr_dataoffset = (int32_t)(ab->varcursor - ab->fixedcursor);
+       ar.attr_length = (u_int32_t)(count + extcount);
        attrlist_pack_fixed(ab, &ar, sizeof(ar));
 
        /*
        attrlist_pack_fixed(ab, &ar, sizeof(ar));
 
        /*
@@ -188,7 +204,7 @@ attrlist_pack_variable(struct _attrlist_buf *ab, const void *source, ssize_t cou
  * allocated buffer space.
  */
 static void
  * allocated buffer space.
  */
 static void
-attrlist_pack_string(struct _attrlist_buf *ab, const char *source, ssize_t count)
+attrlist_pack_string(struct _attrlist_buf *ab, const char *source, size_t count)
 {
        struct attrreference ar;
        ssize_t fit, space;
 {
        struct attrreference ar;
        ssize_t fit, space;
@@ -206,8 +222,8 @@ attrlist_pack_string(struct _attrlist_buf *ab, const char *source, ssize_t count
        /*
         * Construct the fixed-width attribute that refers to this string.
         */
        /*
         * Construct the fixed-width attribute that refers to this string.
         */
-       ar.attr_dataoffset = ab->varcursor - ab->fixedcursor;
-       ar.attr_length = count + 1;
+       ar.attr_dataoffset = (int32_t)(ab->varcursor - ab->fixedcursor);
+       ar.attr_length = (u_int32_t)count + 1;
        attrlist_pack_fixed(ab, &ar, sizeof(ar));
 
        /*
        attrlist_pack_fixed(ab, &ar, sizeof(ar));
 
        /*
@@ -224,7 +240,7 @@ attrlist_pack_string(struct _attrlist_buf *ab, const char *source, ssize_t count
        space = ab->allocated - (ab->varcursor - ab->base);
        fit = lmin(count, space);
        if (space > 0) {
        space = ab->allocated - (ab->varcursor - ab->base);
        fit = lmin(count, space);
        if (space > 0) {
-               int bytes_to_zero;
+               long bytes_to_zero;
 
                /*
                 * If there is space remaining, copy data in, and
 
                /*
                 * If there is space remaining, copy data in, and
@@ -246,7 +262,7 @@ attrlist_pack_string(struct _attrlist_buf *ab, const char *source, ssize_t count
                         * Zero out any additional bytes we might have as a
                         * result of rounding up.
                         */
                         * Zero out any additional bytes we might have as a
                         * result of rounding up.
                         */
-                       bytes_to_zero = min((roundup(fit, 4) - fit),
+                       bytes_to_zero = lmin((roundup(fit, 4) - fit),
                            space - fit);
                        if (bytes_to_zero) {
                                bzero(&(ab->varcursor[fit]), bytes_to_zero);
                            space - fit);
                        if (bytes_to_zero) {
                                bzero(&(ab->varcursor[fit]), bytes_to_zero);
@@ -288,7 +304,7 @@ attrlist_pack_string(struct _attrlist_buf *ab, const char *source, ssize_t count
                        struct user64_timespec us = {.tv_sec = v.tv_sec, .tv_nsec = v.tv_nsec};         \
                        ATTR_PACK(&b, us);                                              \
                } else {                                                                \
                        struct user64_timespec us = {.tv_sec = v.tv_sec, .tv_nsec = v.tv_nsec};         \
                        ATTR_PACK(&b, us);                                              \
                } else {                                                                \
-                       struct user32_timespec us = {.tv_sec = v.tv_sec, .tv_nsec = v.tv_nsec};         \
+                       struct user32_timespec us = {.tv_sec = (user32_time_t)v.tv_sec, .tv_nsec = (user32_long_t)v.tv_nsec};         \
                        ATTR_PACK(&b, us);                                              \
                }                                                                       \
        } while(0)
                        ATTR_PACK(&b, us);                                              \
                }                                                                       \
        } while(0)
@@ -547,6 +563,7 @@ static struct getattrlist_attrtab getattrlist_common_extended_tab[] = {
        {.attr = ATTR_CMNEXT_REALFSID, .bits = VATTR_BIT(va_fsid64), .size = sizeof(fsid_t), .action = KAUTH_VNODE_READ_ATTRIBUTES},
        {.attr = ATTR_CMNEXT_CLONEID, .bits = VATTR_BIT(va_clone_id), .size = sizeof(uint64_t), .action = KAUTH_VNODE_READ_ATTRIBUTES},
        {.attr = ATTR_CMNEXT_EXT_FLAGS, .bits = VATTR_BIT(va_extflags), .size = sizeof(uint64_t), .action = KAUTH_VNODE_READ_ATTRIBUTES},
        {.attr = ATTR_CMNEXT_REALFSID, .bits = VATTR_BIT(va_fsid64), .size = sizeof(fsid_t), .action = KAUTH_VNODE_READ_ATTRIBUTES},
        {.attr = ATTR_CMNEXT_CLONEID, .bits = VATTR_BIT(va_clone_id), .size = sizeof(uint64_t), .action = KAUTH_VNODE_READ_ATTRIBUTES},
        {.attr = ATTR_CMNEXT_EXT_FLAGS, .bits = VATTR_BIT(va_extflags), .size = sizeof(uint64_t), .action = KAUTH_VNODE_READ_ATTRIBUTES},
+       {.attr = ATTR_CMNEXT_RECURSIVE_GENCOUNT, .bits = VATTR_BIT(va_recursive_gencount), .size = sizeof(uint64_t), .action = KAUTH_VNODE_READ_ATTRIBUTES},
        {.attr = 0, .bits = 0, .size = 0, .action = 0}
 };
 
        {.attr = 0, .bits = 0, .size = 0, .action = 0}
 };
 
@@ -981,12 +998,7 @@ getvolattrlist(vfs_context_t ctx, vnode_t vp, struct attrlist *alp,
        if (vs.f_active != 0) {
                /* If we're going to ask for f_vol_name, allocate a buffer to point it at */
                if (VFSATTR_IS_ACTIVE(&vs, f_vol_name)) {
        if (vs.f_active != 0) {
                /* If we're going to ask for f_vol_name, allocate a buffer to point it at */
                if (VFSATTR_IS_ACTIVE(&vs, f_vol_name)) {
-                       vs.f_vol_name = (char *) kalloc(MAXPATHLEN);
-                       if (vs.f_vol_name == NULL) {
-                               error = ENOMEM;
-                               VFS_DEBUG(ctx, vp, "ATTRLIST - ERROR: could not allocate f_vol_name buffer");
-                               goto out;
-                       }
+                       vs.f_vol_name = (char *) zalloc(ZV_NAMEI);
                        vs.f_vol_name[0] = '\0';
                }
 
                        vs.f_vol_name[0] = '\0';
                }
 
@@ -1193,7 +1205,7 @@ getvolattrlist(vfs_context_t ctx, vnode_t vp, struct attrlist *alp,
                goto out;
        }
 
                goto out;
        }
 
-       MALLOC(ab.base, char *, ab.allocated, M_TEMP, M_ZERO | M_WAITOK);
+       ab.base = kheap_alloc(KHEAP_TEMP, ab.allocated, Z_ZERO | Z_WAITOK);
        if (ab.base == NULL) {
                error = ENOMEM;
                VFS_DEBUG(ctx, vp, "ATTRLIST - ERROR: could not allocate %d for copy buffer", ab.allocated);
        if (ab.base == NULL) {
                error = ENOMEM;
                VFS_DEBUG(ctx, vp, "ATTRLIST - ERROR: could not allocate %d for copy buffer", ab.allocated);
@@ -1485,6 +1497,14 @@ getvolattrlist(vfs_context_t ctx, vnode_t vp, struct attrlist *alp,
                        vs.f_capabilities.valid[VOL_CAPABILITIES_FORMAT] |= VOL_CAP_FMT_NO_PERMISSIONS;
                }
 
                        vs.f_capabilities.valid[VOL_CAPABILITIES_FORMAT] |= VOL_CAP_FMT_NO_PERMISSIONS;
                }
 
+               /*
+                * ATTR_CMN_USERACCESS attribute was previously set by file-system drivers, thus volume capabilitiy
+                * VOL_CAP_INT_USERACCESS was conditionally enabled. ATTR_CMN_USERACCESS is now set inside VFS,
+                * regardless of underlying volume type thus we always set VOL_CAP_INT_USERACCESS.
+                */
+               vs.f_capabilities.capabilities[VOL_CAPABILITIES_INTERFACES] |= VOL_CAP_INT_USERACCESS;
+               vs.f_capabilities.valid[VOL_CAPABILITIES_INTERFACES] |= VOL_CAP_INT_USERACCESS;
+
                ATTR_PACK(&ab, vs.f_capabilities);
                ab.actual.volattr |= ATTR_VOL_CAPABILITIES;
        }
                ATTR_PACK(&ab, vs.f_capabilities);
                ab.actual.volattr |= ATTR_VOL_CAPABILITIES;
        }
@@ -1533,7 +1553,7 @@ getvolattrlist(vfs_context_t ctx, vnode_t vp, struct attrlist *alp,
         * of the result buffer, even if we copied less out.  The caller knows how big a buffer
         * they gave us, so they can always check for truncation themselves.
         */
         * of the result buffer, even if we copied less out.  The caller knows how big a buffer
         * they gave us, so they can always check for truncation themselves.
         */
-       *(uint32_t *)ab.base = (options & FSOPT_REPORT_FULLSIZE) ? ab.needed : imin(bufferSize, ab.needed);
+       *(uint32_t *)ab.base = (options & FSOPT_REPORT_FULLSIZE) ? (uint32_t)ab.needed : (uint32_t)lmin(bufferSize, ab.needed);
 
        /* Return attribute set output if requested. */
        if (return_valid &&
 
        /* Return attribute set output if requested. */
        if (return_valid &&
@@ -1549,21 +1569,19 @@ getvolattrlist(vfs_context_t ctx, vnode_t vp, struct attrlist *alp,
 
        if (UIO_SEG_IS_USER_SPACE(segflg)) {
                error = copyout(ab.base, CAST_USER_ADDR_T(attributeBuffer),
 
        if (UIO_SEG_IS_USER_SPACE(segflg)) {
                error = copyout(ab.base, CAST_USER_ADDR_T(attributeBuffer),
-                   ulmin(bufferSize, ab.needed));
+                   ulmin((uint32_t)bufferSize, (uint32_t)ab.needed));
        } else {
        } else {
-               bcopy(ab.base, (void *)attributeBuffer, (size_t)ulmin(bufferSize, ab.needed));
+               bcopy(ab.base, (void *)attributeBuffer, (size_t)ulmin((uint32_t)bufferSize, (uint32_t)ab.needed));
        }
 
 out:
        if (vs.f_vol_name != NULL) {
        }
 
 out:
        if (vs.f_vol_name != NULL) {
-               kfree(vs.f_vol_name, MAXPATHLEN);
+               zfree(ZV_NAMEI, vs.f_vol_name);
        }
        if (release_str) {
                vnode_putname(cnp);
        }
        }
        if (release_str) {
                vnode_putname(cnp);
        }
-       if (ab.base != NULL) {
-               FREE(ab.base, M_TEMP);
-       }
+       kheap_free(KHEAP_TEMP, ab.base, ab.allocated);
        VFS_DEBUG(ctx, vp, "ATTRLIST - returning %d", error);
 
        if (root_vp != NULL) {
        VFS_DEBUG(ctx, vp, "ATTRLIST - returning %d", error);
 
        if (root_vp != NULL) {
@@ -2381,6 +2399,16 @@ attr_pack_common_extended(mount_t mp, struct vnode *vp, struct attrlist *alp,
                }
        }
 
                }
        }
 
+       if (alp->forkattr & ATTR_CMNEXT_RECURSIVE_GENCOUNT) {
+               if (VATTR_IS_SUPPORTED(vap, va_recursive_gencount)) {
+                       ATTR_PACK8((*abp), vap->va_recursive_gencount);
+                       abp->actual.forkattr |= ATTR_CMNEXT_RECURSIVE_GENCOUNT;
+               } else if (!return_valid || pack_invalid) {
+                       uint64_t zero_val = 0;
+                       ATTR_PACK8((*abp), zero_val);
+               }
+       }
+
        return 0;
 }
 
        return 0;
 }
 
@@ -2737,13 +2765,7 @@ vfs_attr_pack_internal(mount_t mp, vnode_t vp, uio_t auio, struct attrlist *alp,
 
        //if a path is requested, allocate a temporary buffer to build it
        if (vp && (alp->commonattr & (ATTR_CMN_FULLPATH))) {
 
        //if a path is requested, allocate a temporary buffer to build it
        if (vp && (alp->commonattr & (ATTR_CMN_FULLPATH))) {
-               fullpathptr = (char*) kalloc(MAXPATHLEN);
-               if (fullpathptr == NULL) {
-                       error = ENOMEM;
-                       VFS_DEBUG(ctx, vp, "ATTRLIST - ERROR: cannot allocate fullpath buffer");
-                       goto out;
-               }
-               bzero(fullpathptr, MAXPATHLEN);
+               fullpathptr = (char*) zalloc_flags(ZV_NAMEI, Z_WAITOK | Z_ZERO);
                apaths.fullpathptr = fullpathptr;
                apaths.fullpathlenp = &fullpathlen;
        }
                apaths.fullpathptr = fullpathptr;
                apaths.fullpathlenp = &fullpathlen;
        }
@@ -2751,25 +2773,13 @@ vfs_attr_pack_internal(mount_t mp, vnode_t vp, uio_t auio, struct attrlist *alp,
        // only interpret fork attributes if they're used as new common attributes
        if (vp && use_fork) {
                if (alp->forkattr & (ATTR_CMNEXT_RELPATH)) {
        // only interpret fork attributes if they're used as new common attributes
        if (vp && use_fork) {
                if (alp->forkattr & (ATTR_CMNEXT_RELPATH)) {
-                       relpathptr = (char*) kalloc(MAXPATHLEN);
-                       if (relpathptr == NULL) {
-                               error = ENOMEM;
-                               VFS_DEBUG(ctx, vp, "ATTRLIST - ERROR: cannot allocate relpath buffer");
-                               goto out;
-                       }
-                       bzero(relpathptr, MAXPATHLEN);
+                       relpathptr = (char*) zalloc_flags(ZV_NAMEI, Z_WAITOK | Z_ZERO);
                        apaths.relpathptr = relpathptr;
                        apaths.relpathlenp = &relpathlen;
                }
 
                if (alp->forkattr & (ATTR_CMNEXT_NOFIRMLINKPATH)) {
                        apaths.relpathptr = relpathptr;
                        apaths.relpathlenp = &relpathlen;
                }
 
                if (alp->forkattr & (ATTR_CMNEXT_NOFIRMLINKPATH)) {
-                       REALpathptr = (char*) kalloc(MAXPATHLEN);
-                       if (REALpathptr == NULL) {
-                               error = ENOMEM;
-                               VFS_DEBUG(ctx, vp, "ATTRLIST - ERROR: cannot allocate canonpath buffer");
-                               goto out;
-                       }
-                       bzero(REALpathptr, MAXPATHLEN);
+                       REALpathptr = (char*) zalloc_flags(ZV_NAMEI, Z_WAITOK | Z_ZERO);
                        apaths.REALpathptr = REALpathptr;
                        apaths.REALpathlenp = &REALpathlen;
                }
                        apaths.REALpathptr = REALpathptr;
                        apaths.REALpathlenp = &REALpathlen;
                }
@@ -2821,8 +2831,7 @@ vfs_attr_pack_internal(mount_t mp, vnode_t vp, uio_t auio, struct attrlist *alp,
         * and big enough.
         */
        if (uio_isuserspace(auio) || (buf_size < ab.allocated)) {
         * and big enough.
         */
        if (uio_isuserspace(auio) || (buf_size < ab.allocated)) {
-               MALLOC(ab.base, char *, ab.allocated, M_TEMP,
-                   M_ZERO | M_WAITOK);
+               ab.base = kheap_alloc(KHEAP_TEMP, ab.allocated, Z_ZERO | Z_WAITOK);
                alloc_local_buf = 1;
        } else {
                /*
                alloc_local_buf = 1;
        } else {
                /*
@@ -2937,7 +2946,7 @@ vfs_attr_pack_internal(mount_t mp, vnode_t vp, uio_t auio, struct attrlist *alp,
         * of the result buffer, even if we copied less out.  The caller knows how big a buffer
         * they gave us, so they can always check for truncation themselves.
         */
         * of the result buffer, even if we copied less out.  The caller knows how big a buffer
         * they gave us, so they can always check for truncation themselves.
         */
-       *(uint32_t *)ab.base = (options & FSOPT_REPORT_FULLSIZE) ? ab.needed : imin(ab.allocated, ab.needed);
+       *(uint32_t *)ab.base = (options & FSOPT_REPORT_FULLSIZE) ? (uint32_t)ab.needed : (uint32_t)lmin(ab.allocated, ab.needed);
 
        /* Return attribute set output if requested. */
        if (return_valid) {
 
        /* Return attribute set output if requested. */
        if (return_valid) {
@@ -2951,11 +2960,11 @@ vfs_attr_pack_internal(mount_t mp, vnode_t vp, uio_t auio, struct attrlist *alp,
                bcopy(&ab.actual, ab.base + sizeof(uint32_t), sizeof(ab.actual));
        }
 
                bcopy(&ab.actual, ab.base + sizeof(uint32_t), sizeof(ab.actual));
        }
 
-       copy_size = imin(buf_size, ab.allocated);
+       copy_size = lmin(buf_size, ab.allocated);
 
        /* Only actually copyout as much out as the user buffer can hold */
        if (alloc_local_buf) {
 
        /* Only actually copyout as much out as the user buffer can hold */
        if (alloc_local_buf) {
-               error = uiomove(ab.base, copy_size, auio);
+               error = uiomove(ab.base, (int)copy_size, auio);
        } else {
                off_t orig_offset = uio_offset(auio);
 
        } else {
                off_t orig_offset = uio_offset(auio);
 
@@ -2980,16 +2989,16 @@ out:
                vnode_putname(vname);
        }
        if (fullpathptr) {
                vnode_putname(vname);
        }
        if (fullpathptr) {
-               kfree(fullpathptr, MAXPATHLEN);
+               zfree(ZV_NAMEI, fullpathptr);
        }
        if (relpathptr) {
        }
        if (relpathptr) {
-               kfree(relpathptr, MAXPATHLEN);
+               zfree(ZV_NAMEI, relpathptr);
        }
        if (REALpathptr) {
        }
        if (REALpathptr) {
-               kfree(REALpathptr, MAXPATHLEN);
+               zfree(ZV_NAMEI, REALpathptr);
        }
        }
-       if (ab.base != NULL && alloc_local_buf) {
-               FREE(ab.base, M_TEMP);
+       if (alloc_local_buf) {
+               kheap_free(KHEAP_TEMP, ab.base, ab.allocated);
        }
        return error;
 }
        }
        return error;
 }
@@ -3055,7 +3064,7 @@ getattrlist_internal(vfs_context_t ctx, vnode_t vp, struct attrlist  *alp,
     user_addr_t attributeBuffer, size_t bufferSize, uint64_t options,
     enum uio_seg segflg, char* authoritative_name, struct ucred *file_cred)
 {
     user_addr_t attributeBuffer, size_t bufferSize, uint64_t options,
     enum uio_seg segflg, char* authoritative_name, struct ucred *file_cred)
 {
-       struct vnode_attr va;
+       struct vnode_attr *va;
        kauth_action_t  action;
        ssize_t         fixedsize;
        char            *va_name;
        kauth_action_t  action;
        ssize_t         fixedsize;
        char            *va_name;
@@ -3086,7 +3095,8 @@ getattrlist_internal(vfs_context_t ctx, vnode_t vp, struct attrlist  *alp,
            &uio_buf[0], sizeof(uio_buf));
        uio_addiov(auio, attributeBuffer, bufferSize);
 
            &uio_buf[0], sizeof(uio_buf));
        uio_addiov(auio, attributeBuffer, bufferSize);
 
-       VATTR_INIT(&va);
+       va = kheap_alloc(KHEAP_TEMP, sizeof(struct vnode_attr), Z_WAITOK);
+       VATTR_INIT(va);
        va_name = NULL;
 
        if (alp->bitmapcount != ATTR_BIT_MAP_COUNT) {
        va_name = NULL;
 
        if (alp->bitmapcount != ATTR_BIT_MAP_COUNT) {
@@ -3156,7 +3166,7 @@ getattrlist_internal(vfs_context_t ctx, vnode_t vp, struct attrlist  *alp,
                        goto out;
                }
                /* Keep invalid attrs from being uninitialized */
                        goto out;
                }
                /* Keep invalid attrs from being uninitialized */
-               bzero(&va, sizeof(va));
+               bzero(va, sizeof(*va));
        }
 
        /* Pick up the vnode type.  If the FS is bad and changes vnode types on us, we
        }
 
        /* Pick up the vnode type.  If the FS is bad and changes vnode types on us, we
@@ -3167,7 +3177,7 @@ getattrlist_internal(vfs_context_t ctx, vnode_t vp, struct attrlist  *alp,
        /*
         * Set up the vnode_attr structure and authorise.
         */
        /*
         * Set up the vnode_attr structure and authorise.
         */
-       if ((error = getattrlist_setupvattr(alp, &va, &fixedsize, &action, proc_is64, (vtype == VDIR), use_fork)) != 0) {
+       if ((error = getattrlist_setupvattr(alp, va, &fixedsize, &action, proc_is64, (vtype == VDIR), use_fork)) != 0) {
                VFS_DEBUG(ctx, vp, "ATTRLIST - ERROR: setup for request failed");
                goto out;
        }
                VFS_DEBUG(ctx, vp, "ATTRLIST - ERROR: setup for request failed");
                goto out;
        }
@@ -3177,20 +3187,14 @@ getattrlist_internal(vfs_context_t ctx, vnode_t vp, struct attrlist  *alp,
        }
 
 
        }
 
 
-       if (va.va_active != 0) {
-               uint64_t va_active = va.va_active;
+       if (va->va_active != 0) {
+               uint64_t va_active = va->va_active;
 
                /*
                 * If we're going to ask for va_name, allocate a buffer to point it at
                 */
 
                /*
                 * If we're going to ask for va_name, allocate a buffer to point it at
                 */
-               if (VATTR_IS_ACTIVE(&va, va_name)) {
-                       MALLOC_ZONE(va_name, char *, MAXPATHLEN, M_NAMEI,
-                           M_WAITOK);
-                       if (va_name == NULL) {
-                               error = ENOMEM;
-                               VFS_DEBUG(ctx, vp, "ATTRLIST - ERROR: cannot allocate va_name buffer");
-                               goto out;
-                       }
+               if (VATTR_IS_ACTIVE(va, va_name)) {
+                       va_name = zalloc(ZV_NAMEI);
                        /*
                         * If we have an authoritative_name, prefer that name.
                         *
                        /*
                         * If we have an authoritative_name, prefer that name.
                         *
@@ -3201,21 +3205,21 @@ getattrlist_internal(vfs_context_t ctx, vnode_t vp, struct attrlist  *alp,
                         */
                        if (authoritative_name) {
                                /* Don't ask the file system */
                         */
                        if (authoritative_name) {
                                /* Don't ask the file system */
-                               VATTR_CLEAR_ACTIVE(&va, va_name);
+                               VATTR_CLEAR_ACTIVE(va, va_name);
                                strlcpy(va_name, authoritative_name, MAXPATHLEN);
                        }
                }
 
                                strlcpy(va_name, authoritative_name, MAXPATHLEN);
                        }
                }
 
-               va.va_name = authoritative_name ? NULL : va_name;
+               va->va_name = authoritative_name ? NULL : va_name;
 
                if (options & FSOPT_RETURN_REALDEV) {
 
                if (options & FSOPT_RETURN_REALDEV) {
-                       va.va_vaflags |= VA_REALFSID;
+                       va->va_vaflags |= VA_REALFSID;
                }
 
                /*
                 * Call the filesystem.
                 */
                }
 
                /*
                 * Call the filesystem.
                 */
-               if ((error = vnode_getattr(vp, &va, ctx)) != 0) {
+               if ((error = vnode_getattr(vp, va, ctx)) != 0) {
                        VFS_DEBUG(ctx, vp, "ATTRLIST - ERROR: filesystem returned %d", error);
                        goto out;
                }
                        VFS_DEBUG(ctx, vp, "ATTRLIST - ERROR: filesystem returned %d", error);
                        goto out;
                }
@@ -3230,7 +3234,7 @@ getattrlist_internal(vfs_context_t ctx, vnode_t vp, struct attrlist  *alp,
                 * opportunity to change the values of attributes
                 * retrieved.
                 */
                 * opportunity to change the values of attributes
                 * retrieved.
                 */
-               error = mac_vnode_check_getattr(ctx, file_cred, vp, &va);
+               error = mac_vnode_check_getattr(ctx, file_cred, vp, va);
                if (error) {
                        VFS_DEBUG(ctx, vp, "ATTRLIST - ERROR: MAC framework returned %d", error);
                        goto out;
                if (error) {
                        VFS_DEBUG(ctx, vp, "ATTRLIST - ERROR: MAC framework returned %d", error);
                        goto out;
@@ -3247,26 +3251,27 @@ getattrlist_internal(vfs_context_t ctx, vnode_t vp, struct attrlist  *alp,
                 * A (buggy) filesystem may change fields which belong
                 * to us. We try to deal with that here as well.
                 */
                 * A (buggy) filesystem may change fields which belong
                 * to us. We try to deal with that here as well.
                 */
-               va.va_active = va_active;
+               va->va_active = va_active;
                if (authoritative_name && va_name) {
                if (authoritative_name && va_name) {
-                       VATTR_SET_ACTIVE(&va, va_name);
-                       if (!(VATTR_IS_SUPPORTED(&va, va_name))) {
-                               VATTR_SET_SUPPORTED(&va, va_name);
+                       VATTR_SET_ACTIVE(va, va_name);
+                       if (!(VATTR_IS_SUPPORTED(va, va_name))) {
+                               VATTR_SET_SUPPORTED(va, va_name);
                        }
                }
                        }
                }
-               va.va_name = va_name;
+               va->va_name = va_name;
        }
 
        }
 
-       error = vfs_attr_pack_internal(vp->v_mount, vp, auio, alp, options, &va, NULL, ctx,
+       error = vfs_attr_pack_internal(vp->v_mount, vp, auio, alp, options, va, NULL, ctx,
            0, vtype, fixedsize);
 
 out:
        if (va_name) {
            0, vtype, fixedsize);
 
 out:
        if (va_name) {
-               FREE_ZONE(va_name, MAXPATHLEN, M_NAMEI);
+               zfree(ZV_NAMEI, va_name);
        }
        }
-       if (VATTR_IS_SUPPORTED(&va, va_acl) && (va.va_acl != NULL)) {
-               kauth_acl_free(va.va_acl);
+       if (VATTR_IS_SUPPORTED(va, va_acl) && (va->va_acl != NULL)) {
+               kauth_acl_free(va->va_acl);
        }
        }
+       kheap_free(KHEAP_TEMP, va, sizeof(struct vnode_attr));
 
        VFS_DEBUG(ctx, vp, "ATTRLIST - returning %d", error);
        return error;
 
        VFS_DEBUG(ctx, vp, "ATTRLIST - returning %d", error);
        return error;
@@ -3286,13 +3291,12 @@ fgetattrlist(proc_t p, struct fgetattrlist_args *uap, __unused int32_t *retval)
        fp = NULL;
        error = 0;
 
        fp = NULL;
        error = 0;
 
-       if ((error = file_vnode(uap->fd, &vp)) != 0) {
+       if ((error = fp_get_ftype(p, uap->fd, DTYPE_VNODE, EINVAL, &fp)) != 0) {
                return error;
        }
                return error;
        }
+       vp = (struct vnode *)fp->fp_glob->fg_data;
 
 
-       if ((error = fp_lookup(p, uap->fd, &fp, 0)) != 0 ||
-           (error = vnode_getwithref(vp)) != 0) {
-               vp = NULL;
+       if ((error = vnode_getwithref(vp)) != 0) {
                goto out;
        }
 
                goto out;
        }
 
@@ -3301,7 +3305,7 @@ fgetattrlist(proc_t p, struct fgetattrlist_args *uap, __unused int32_t *retval)
         */
        error = copyin(uap->alist, &al, sizeof(al));
        if (error) {
         */
        error = copyin(uap->alist, &al, sizeof(al));
        if (error) {
-               goto out;
+               goto out_vnode_put;
        }
 
        /* Default to using the vnode's name. */
        }
 
        /* Default to using the vnode's name. */
@@ -3309,16 +3313,12 @@ fgetattrlist(proc_t p, struct fgetattrlist_args *uap, __unused int32_t *retval)
            uap->bufferSize, uap->options,
            (IS_64BIT_PROCESS(p) ? UIO_USERSPACE64 : \
            UIO_USERSPACE32), NULL,
            uap->bufferSize, uap->options,
            (IS_64BIT_PROCESS(p) ? UIO_USERSPACE64 : \
            UIO_USERSPACE32), NULL,
-           fp->f_fglob->fg_cred);
+           fp->fp_glob->fg_cred);
 
 
+out_vnode_put:
+       vnode_put(vp);
 out:
 out:
-       if (fp) {
-               fp_drop(p, uap->fd, fp, 0);
-       }
-       if (vp) {
-               vnode_put(vp);
-       }
-       file_drop(uap->fd);
+       fp_drop(p, uap->fd, fp, 0);
 
        return error;
 }
 
        return error;
 }
@@ -3438,7 +3438,7 @@ refill_fd_direntries(vfs_context_t ctx, vnode_t dvp, struct fd_vn_data *fvd,
        if (fvd->fv_eofflag) {
                *eofflagp = 1;
                if (fvd->fv_buf) {
        if (fvd->fv_eofflag) {
                *eofflagp = 1;
                if (fvd->fv_buf) {
-                       FREE(fvd->fv_buf, M_FD_DIRBUF);
+                       kheap_free(KHEAP_DATA_BUFFERS, fvd->fv_buf, fvd->fv_bufallocsiz);
                        fvd->fv_buf = NULL;
                }
                return 0;
                        fvd->fv_buf = NULL;
                }
                return 0;
@@ -3470,7 +3470,8 @@ retry_alloc:
         * not copied out to user space.
         */
        if (!fvd->fv_buf) {
         * not copied out to user space.
         */
        if (!fvd->fv_buf) {
-               MALLOC(fvd->fv_buf, caddr_t, rdirbufsiz, M_FD_DIRBUF, M_WAITOK);
+               fvd->fv_buf = kheap_alloc(KHEAP_DATA_BUFFERS, rdirbufsiz, Z_WAITOK);
+               fvd->fv_bufallocsiz = rdirbufsiz;
                fvd->fv_bufdone = 0;
        }
 
                fvd->fv_bufdone = 0;
        }
 
@@ -3498,8 +3499,6 @@ retry_alloc:
                fvd->fv_bufsiz = rdirbufused;
                fvd->fv_bufdone = 0;
                bzero(fvd->fv_buf + rdirbufused, rdirbufsiz - rdirbufused);
                fvd->fv_bufsiz = rdirbufused;
                fvd->fv_bufdone = 0;
                bzero(fvd->fv_buf + rdirbufused, rdirbufsiz - rdirbufused);
-               /* Cache allocation size the Filesystem responded to */
-               fvd->fv_bufallocsiz = rdirbufsiz;
        } else if (!eofflag && (rdirbufsiz < FV_DIRBUF_MAX_SIZ)) {
                /*
                 * Some Filesystems have higher requirements for the
        } else if (!eofflag && (rdirbufsiz < FV_DIRBUF_MAX_SIZ)) {
                /*
                 * Some Filesystems have higher requirements for the
@@ -3511,8 +3510,7 @@ retry_alloc:
                 * from VNOP_READDIR is ignored until at least FV_DIRBUF_MAX_SIZ
                 * has been attempted.
                 */
                 * from VNOP_READDIR is ignored until at least FV_DIRBUF_MAX_SIZ
                 * has been attempted.
                 */
-               FREE(fvd->fv_buf, M_FD_DIRBUF);
-               fvd->fv_buf = NULL;
+               kheap_free(KHEAP_DATA_BUFFERS, fvd->fv_buf, fvd->fv_bufallocsiz);
                rdirbufsiz = 2 * rdirbufsiz;
                fvd->fv_bufallocsiz = 0;
                goto retry_alloc;
                rdirbufsiz = 2 * rdirbufsiz;
                fvd->fv_bufallocsiz = 0;
                goto retry_alloc;
@@ -3539,8 +3537,10 @@ retry_alloc:
         * time to free up directory entry buffer.
         */
        if ((error || eofflag) && fvd->fv_buf) {
         * time to free up directory entry buffer.
         */
        if ((error || eofflag) && fvd->fv_buf) {
-               FREE(fvd->fv_buf, M_FD_DIRBUF);
-               fvd->fv_buf = NULL;
+               kheap_free(KHEAP_DATA_BUFFERS, fvd->fv_buf, fvd->fv_bufallocsiz);
+               if (error) {
+                       fvd->fv_bufallocsiz = 0;
+               }
        }
 
        *eofflagp = eofflag;
        }
 
        *eofflagp = eofflag;
@@ -3642,7 +3642,7 @@ get_error_attributes(vnode_t vp, struct attrlist *alp, uint64_t options,
 {
        size_t fsiz, vsiz;
        struct _attrlist_buf ab;
 {
        size_t fsiz, vsiz;
        struct _attrlist_buf ab;
-       int namelen;
+       size_t namelen;
        kauth_action_t action;
        struct attrlist al;
        int needs_error_attr = (alp->commonattr & ATTR_CMN_ERROR);
        kauth_action_t action;
        struct attrlist al;
        int needs_error_attr = (alp->commonattr & ATTR_CMN_ERROR);
@@ -3689,7 +3689,7 @@ get_error_attributes(vnode_t vp, struct attrlist *alp, uint64_t options,
        ab.needed = fsiz + vsiz;
 
        /* Fill in the size needed */
        ab.needed = fsiz + vsiz;
 
        /* Fill in the size needed */
-       *((uint32_t *)ab.base) = ab.needed;
+       *((uint32_t *)ab.base) = (uint32_t)ab.needed;
        if (ab.needed > (ssize_t)kern_attr_buf_siz) {
                goto out;
        }
        if (ab.needed > (ssize_t)kern_attr_buf_siz) {
                goto out;
        }
@@ -3784,7 +3784,7 @@ readdirattr(vnode_t dvp, struct fd_vn_data *fvd, uio_t auio,
                return error;
        }
 
                return error;
        }
 
-       MALLOC(kern_attr_buf, caddr_t, kern_attr_buf_siz, M_TEMP, M_WAITOK);
+       kern_attr_buf = kheap_alloc(KHEAP_TEMP, kern_attr_buf_siz, Z_WAITOK);
 
        while (uio_resid(auio) > (user_ssize_t)MIN_BUF_SIZE_REQUIRED) {
                struct direntry *dp;
 
        while (uio_resid(auio) > (user_ssize_t)MIN_BUF_SIZE_REQUIRED) {
                struct direntry *dp;
@@ -3823,8 +3823,7 @@ readdirattr(vnode_t dvp, struct fd_vn_data *fvd, uio_t auio,
                 */
                if (dp->d_name[dp->d_namlen] != '\0') {
                        if (!max_path_name_buf) {
                 */
                if (dp->d_name[dp->d_namlen] != '\0') {
                        if (!max_path_name_buf) {
-                               MALLOC(max_path_name_buf, caddr_t, MAXPATHLEN,
-                                   M_TEMP, M_WAITOK);
+                               max_path_name_buf = zalloc_flags(ZV_NAMEI, Z_WAITOK);
                        }
                        bcopy(dp->d_name, max_path_name_buf, dp->d_namlen);
                        max_path_name_buf[dp->d_namlen] = '\0';
                        }
                        bcopy(dp->d_name, max_path_name_buf, dp->d_namlen);
                        max_path_name_buf[dp->d_namlen] = '\0';
@@ -3937,7 +3936,7 @@ readdirattr(vnode_t dvp, struct fd_vn_data *fvd, uio_t auio,
                        entlen += pad_bytes;
                }
                *((uint32_t *)kern_attr_buf) = (uint32_t)entlen;
                        entlen += pad_bytes;
                }
                *((uint32_t *)kern_attr_buf) = (uint32_t)entlen;
-               error = uiomove(kern_attr_buf, min(entlen, kern_attr_buf_siz),
+               error = uiomove(kern_attr_buf, min((int)entlen, (int)kern_attr_buf_siz),
                    auio);
 
                if (error) {
                    auio);
 
                if (error) {
@@ -3957,13 +3956,13 @@ readdirattr(vnode_t dvp, struct fd_vn_data *fvd, uio_t auio,
        }
 
        if (max_path_name_buf) {
        }
 
        if (max_path_name_buf) {
-               FREE(max_path_name_buf, M_TEMP);
+               zfree(ZV_NAMEI, max_path_name_buf);
        }
 
        /*
         * At this point, kern_attr_buf is always allocated
         */
        }
 
        /*
         * At this point, kern_attr_buf is always allocated
         */
-       FREE(kern_attr_buf, M_TEMP);
+       kheap_free(KHEAP_TEMP, kern_attr_buf, kern_attr_buf_siz);
 
        /*
         * Always set the offset to the last succesful offset
 
        /*
         * Always set the offset to the last succesful offset
@@ -3974,6 +3973,11 @@ readdirattr(vnode_t dvp, struct fd_vn_data *fvd, uio_t auio,
        return error;
 }
 
        return error;
 }
 
+/* common attributes that only require KAUTH_VNODE_LIST_DIRECTORY */
+#define LIST_DIR_ATTRS    (ATTR_CMN_NAME | ATTR_CMN_OBJTYPE |  \
+                          ATTR_CMN_FILEID | ATTR_CMN_RETURNED_ATTRS |  \
+                          ATTR_CMN_ERROR)
+
 /*
  * int getattrlistbulk(int dirfd, struct attrlist *alist, void *attributeBuffer,
  *    size_t bufferSize, uint64_t options)
 /*
  * int getattrlistbulk(int dirfd, struct attrlist *alist, void *attributeBuffer,
  *    size_t bufferSize, uint64_t options)
@@ -4015,7 +4019,7 @@ getattrlistbulk(proc_t p, struct getattrlistbulk_args *uap, int32_t *retval)
        ut = get_bsdthread_info(current_thread());
        segflg = IS_64BIT_PROCESS(p) ? UIO_USERSPACE64 : UIO_USERSPACE32;
 
        ut = get_bsdthread_info(current_thread());
        segflg = IS_64BIT_PROCESS(p) ? UIO_USERSPACE64 : UIO_USERSPACE32;
 
-       if ((fp->f_fglob->fg_flag & FREAD) == 0) {
+       if ((fp->fp_glob->fg_flag & FREAD) == 0) {
                /*
                 *  AUDIT_ARG(vnpath_withref, dvp, ARG_VNODE1);
                 */
                /*
                 *  AUDIT_ARG(vnpath_withref, dvp, ARG_VNODE1);
                 */
@@ -4053,7 +4057,7 @@ getattrlistbulk(proc_t p, struct getattrlistbulk_args *uap, int32_t *retval)
 
 #if CONFIG_MACF
        error = mac_file_check_change_offset(vfs_context_ucred(ctx),
 
 #if CONFIG_MACF
        error = mac_file_check_change_offset(vfs_context_ucred(ctx),
-           fp->f_fglob);
+           fp->fp_glob);
        if (error) {
                goto out;
        }
        if (error) {
                goto out;
        }
@@ -4084,12 +4088,12 @@ getattrlistbulk(proc_t p, struct getattrlistbulk_args *uap, int32_t *retval)
 #endif /* MAC */
 
        /*
 #endif /* MAC */
 
        /*
-        * If the only item requested is file names, we can let that past with
-        * just LIST_DIRECTORY.  If they want any other attributes, that means
-        * they need SEARCH as well.
+        * Requested attributes that are available in the direntry struct, with the addition
+        * of ATTR_CMN_RETURNED_ATTRS and ATTR_CMN_ERROR, can be let past with just LIST_DIRECTORY.
+        * Any other requested attributes require SEARCH as well.
         */
        action = KAUTH_VNODE_LIST_DIRECTORY;
         */
        action = KAUTH_VNODE_LIST_DIRECTORY;
-       if ((al.commonattr & ~ATTR_CMN_NAME) || al.fileattr || al.dirattr) {
+       if ((al.commonattr & ~LIST_DIR_ATTRS) || al.fileattr || al.dirattr) {
                action |= KAUTH_VNODE_SEARCH;
        }
 
                action |= KAUTH_VNODE_SEARCH;
        }
 
@@ -4098,7 +4102,7 @@ getattrlistbulk(proc_t p, struct getattrlistbulk_args *uap, int32_t *retval)
                goto out;
        }
 
                goto out;
        }
 
-       fvdata = (struct fd_vn_data *)fp->f_fglob->fg_vn_data;
+       fvdata = (struct fd_vn_data *)fp->fp_glob->fg_vn_data;
        if (!fvdata) {
                panic("Directory expected to have fg_vn_data");
        }
        if (!fvdata) {
                panic("Directory expected to have fg_vn_data");
        }
@@ -4111,12 +4115,10 @@ getattrlistbulk(proc_t p, struct getattrlistbulk_args *uap, int32_t *retval)
         * traversal needs to be restarted (Any existing state in the
         * directory buffer is removed as well).
         */
         * traversal needs to be restarted (Any existing state in the
         * directory buffer is removed as well).
         */
-       if (!fp->f_fglob->fg_offset) {
+       if (!fp->fp_glob->fg_offset) {
                fvdata->fv_offset = 0;
                fvdata->fv_offset = 0;
-               if (fvdata->fv_buf) {
-                       FREE(fvdata->fv_buf, M_FD_DIRBUF);
-               }
-               fvdata->fv_buf = NULL;
+               kheap_free(KHEAP_DATA_BUFFERS, fvdata->fv_buf,
+                   fvdata->fv_bufallocsiz);
                fvdata->fv_bufsiz = 0;
                fvdata->fv_bufdone = 0;
                fvdata->fv_soff = 0;
                fvdata->fv_bufsiz = 0;
                fvdata->fv_bufdone = 0;
                fvdata->fv_soff = 0;
@@ -4141,7 +4143,7 @@ getattrlistbulk(proc_t p, struct getattrlistbulk_args *uap, int32_t *retval)
            !(al.commonattr & ATTR_CMN_OBJTYPE)) {
                error = ENOTSUP;
        } else {
            !(al.commonattr & ATTR_CMN_OBJTYPE)) {
                error = ENOTSUP;
        } else {
-               struct vnode_attr va;
+               struct vnode_attr *va;
                char *va_name;
 
                if (fvdata->fv_eofflag && !fvdata->fv_buf) {
                char *va_name;
 
                if (fvdata->fv_eofflag && !fvdata->fv_buf) {
@@ -4156,12 +4158,13 @@ getattrlistbulk(proc_t p, struct getattrlistbulk_args *uap, int32_t *retval)
                        eofflag = 0;
                        count = 0;
 
                        eofflag = 0;
                        count = 0;
 
-                       VATTR_INIT(&va);
-                       MALLOC(va_name, char *, MAXPATHLEN, M_TEMP,
-                           M_WAITOK | M_ZERO);
-                       va.va_name = va_name;
+                       va = kheap_alloc(KHEAP_TEMP, sizeof(struct vnode_attr), Z_WAITOK);
+
+                       VATTR_INIT(va);
+                       va_name = zalloc_flags(ZV_NAMEI, Z_WAITOK | Z_ZERO);
+                       va->va_name = va_name;
 
 
-                       (void)getattrlist_setupvattr_all(&al, &va, VNON, NULL,
+                       (void)getattrlist_setupvattr_all(&al, va, VNON, NULL,
                            IS_64BIT_PROCESS(p), (uap->options & FSOPT_ATTR_CMN_EXTENDED));
 
                        /*
                            IS_64BIT_PROCESS(p), (uap->options & FSOPT_ATTR_CMN_EXTENDED));
 
                        /*
@@ -4169,11 +4172,12 @@ getattrlistbulk(proc_t p, struct getattrlistbulk_args *uap, int32_t *retval)
                         * filesystem to be rapidly aged.
                         */
                        ut->uu_flag |= UT_KERN_RAGE_VNODES;
                         * filesystem to be rapidly aged.
                         */
                        ut->uu_flag |= UT_KERN_RAGE_VNODES;
-                       error = VNOP_GETATTRLISTBULK(dvp, &al, &va, auio, NULL,
+                       error = VNOP_GETATTRLISTBULK(dvp, &al, va, auio, NULL,
                            options, &eofflag, &count, ctx);
                        ut->uu_flag &= ~UT_KERN_RAGE_VNODES;
 
                            options, &eofflag, &count, ctx);
                        ut->uu_flag &= ~UT_KERN_RAGE_VNODES;
 
-                       FREE(va_name, M_TEMP);
+                       zfree(ZV_NAMEI, va_name);
+                       kheap_free(KHEAP_TEMP, va, sizeof(struct vnode_attr));
 
                        /*
                         * cache state of eofflag.
 
                        /*
                         * cache state of eofflag.
@@ -4200,7 +4204,7 @@ getattrlistbulk(proc_t p, struct getattrlistbulk_args *uap, int32_t *retval)
 
        if (count) {
                fvdata->fv_offset = uio_offset(auio);
 
        if (count) {
                fvdata->fv_offset = uio_offset(auio);
-               fp->f_fglob->fg_offset = fvdata->fv_offset;
+               fp->fp_glob->fg_offset = fvdata->fv_offset;
                *retval = count;
                error = 0;
        } else if (!error && !eofflag) {
                *retval = count;
                error = 0;
        } else if (!error && !eofflag) {
@@ -4236,14 +4240,14 @@ attrlist_unpack_fixed(char **cursor, char *end, void *buf, ssize_t size)
 }
 
 #define ATTR_UNPACK(v)          do {if ((error = attrlist_unpack_fixed(&cursor, bufend, &v, sizeof(v))) != 0) goto out;} while(0);
 }
 
 #define ATTR_UNPACK(v)          do {if ((error = attrlist_unpack_fixed(&cursor, bufend, &v, sizeof(v))) != 0) goto out;} while(0);
-#define ATTR_UNPACK_CAST(t, v)  do { t _f; ATTR_UNPACK(_f); v = _f;} while(0)
+#define ATTR_UNPACK_CAST(t, v)  do { t _f; ATTR_UNPACK(_f); v = (typeof(v))_f;} while(0)
 #define ATTR_UNPACK_TIME(v, is64)                               \
        do {                                                    \
                if (is64) {                                     \
                        struct user64_timespec us;              \
                        ATTR_UNPACK(us);                        \
 #define ATTR_UNPACK_TIME(v, is64)                               \
        do {                                                    \
                if (is64) {                                     \
                        struct user64_timespec us;              \
                        ATTR_UNPACK(us);                        \
-                       v.tv_sec = us.tv_sec;                   \
-                       v.tv_nsec = us.tv_nsec;                 \
+                       v.tv_sec = (unsigned long)us.tv_sec;                   \
+                       v.tv_nsec = (long)us.tv_nsec;                 \
                } else {                                        \
                        struct user32_timespec us;              \
                        ATTR_UNPACK(us);                        \
                } else {                                        \
                        struct user32_timespec us;              \
                        ATTR_UNPACK(us);                        \
@@ -4325,9 +4329,7 @@ setattrlist_internal(vnode_t vp, struct setattrlist_args *uap, proc_t p, vfs_con
 
        /*
         * If the caller's bitmaps indicate that there are no attributes to set,
 
        /*
         * If the caller's bitmaps indicate that there are no attributes to set,
-        * then exit early.  In particular, we want to avoid the MALLOC below
-        * since the caller's bufferSize could be zero, and MALLOC of zero bytes
-        * returns a NULL pointer, which would cause setattrlist to return ENOMEM.
+        * then exit early.
         */
        if (al.commonattr == 0 &&
            (al.volattr & ~ATTR_VOL_INFO) == 0 &&
         */
        if (al.commonattr == 0 &&
            (al.volattr & ~ATTR_VOL_INFO) == 0 &&
@@ -4352,7 +4354,7 @@ setattrlist_internal(vnode_t vp, struct setattrlist_args *uap, proc_t p, vfs_con
                error = ENOMEM;
                goto out;
        }
                error = ENOMEM;
                goto out;
        }
-       MALLOC(user_buf, char *, uap->bufferSize, M_TEMP, M_WAITOK);
+       user_buf = kheap_alloc(KHEAP_DATA_BUFFERS, uap->bufferSize, Z_WAITOK);
        if (user_buf == NULL) {
                VFS_DEBUG(ctx, vp, "ATTRLIST - ERROR: could not allocate %d bytes for buffer", uap->bufferSize);
                error = ENOMEM;
        if (user_buf == NULL) {
                VFS_DEBUG(ctx, vp, "ATTRLIST - ERROR: could not allocate %d bytes for buffer", uap->bufferSize);
                error = ENOMEM;
@@ -4642,9 +4644,7 @@ setattrlist_internal(vnode_t vp, struct setattrlist_args *uap, proc_t p, vfs_con
        /* all done and successful */
 
 out:
        /* all done and successful */
 
 out:
-       if (user_buf != NULL) {
-               FREE(user_buf, M_TEMP);
-       }
+       kheap_free(KHEAP_DATA_BUFFERS, user_buf, uap->bufferSize);
        VFS_DEBUG(ctx, vp, "ATTRLIST - set returning %d", error);
        return error;
 }
        VFS_DEBUG(ctx, vp, "ATTRLIST - set returning %d", error);
        return error;
 }
@@ -4655,7 +4655,7 @@ setattrlist(proc_t p, struct setattrlist_args *uap, __unused int32_t *retval)
        struct vfs_context *ctx;
        struct nameidata nd;
        vnode_t         vp = NULL;
        struct vfs_context *ctx;
        struct nameidata nd;
        vnode_t         vp = NULL;
-       u_long          nameiflags;
+       uint32_t          nameiflags;
        int error = 0;
 
        ctx = vfs_context_current();
        int error = 0;
 
        ctx = vfs_context_current();