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},
} 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}};
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");
}
/*
- * 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;
}
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);
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) {
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;
}