#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 <kern/kalloc.h>
+#include <kern/zalloc.h>
#include <miscfs/specfs/specdev.h>
#include <security/audit/audit.h>
#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.
*/
* 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));
/*
* 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;
/*
* 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));
/*
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
* 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);
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 = 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}
};
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';
}
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);
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;
}
* 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 &&
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 {
- 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) {
- kfree(vs.f_vol_name, MAXPATHLEN);
+ zfree(ZV_NAMEI, vs.f_vol_name);
}
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) {
}
}
+ 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;
}
//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;
}
// 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)) {
- 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;
}
* 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 {
/*
* 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) {
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) {
- error = uiomove(ab.base, copy_size, auio);
+ error = uiomove(ab.base, (int)copy_size, auio);
} else {
off_t orig_offset = uio_offset(auio);
vnode_putname(vname);
}
if (fullpathptr) {
- kfree(fullpathptr, MAXPATHLEN);
+ zfree(ZV_NAMEI, fullpathptr);
}
if (relpathptr) {
- kfree(relpathptr, MAXPATHLEN);
+ zfree(ZV_NAMEI, relpathptr);
}
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;
}
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;
&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) {
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
/*
* 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;
}
}
- 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 (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 (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);
}
}
- va.va_name = authoritative_name ? NULL : va_name;
+ va->va_name = authoritative_name ? NULL : va_name;
if (options & FSOPT_RETURN_REALDEV) {
- va.va_vaflags |= VA_REALFSID;
+ va->va_vaflags |= VA_REALFSID;
}
/*
* 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;
}
* 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;
* 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) {
- 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) {
- 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;
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;
}
+ 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;
}
*/
error = copyin(uap->alist, &al, sizeof(al));
if (error) {
- goto out;
+ goto out_vnode_put;
}
/* Default to using the vnode's name. */
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:
- 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;
}
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;
* 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_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
* 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;
* 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;
{
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);
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;
}
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;
*/
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';
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) {
}
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
*/
- 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
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)
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);
*/
#if CONFIG_MACF
error = mac_file_check_change_offset(vfs_context_ucred(ctx),
- fp->f_fglob);
+ fp->fp_glob);
if (error) {
goto out;
}
#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;
- if ((al.commonattr & ~ATTR_CMN_NAME) || al.fileattr || al.dirattr) {
+ if ((al.commonattr & ~LIST_DIR_ATTRS) || al.fileattr || al.dirattr) {
action |= KAUTH_VNODE_SEARCH;
}
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");
}
* 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;
- 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;
!(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) {
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));
/*
* 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;
- FREE(va_name, M_TEMP);
+ zfree(ZV_NAMEI, va_name);
+ kheap_free(KHEAP_TEMP, va, sizeof(struct vnode_attr));
/*
* cache state of eofflag.
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) {
}
#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); \
- 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); \
/*
* 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 &&
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;
/* 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;
}
struct vfs_context *ctx;
struct nameidata nd;
vnode_t vp = NULL;
- u_long nameiflags;
+ uint32_t nameiflags;
int error = 0;
ctx = vfs_context_current();