Print this page
5548 Attempt to read ACLs from Illumos NFS client is toxic

*** 81,131 **** if (!xdr_o_mode(xdrs, &objp->a_perm)) return (FALSE); return (TRUE); } bool_t xdr_secattr(XDR *xdrs, vsecattr_t *objp) { ! uint_t count; ! if (!xdr_u_int(xdrs, &objp->vsa_mask)) return (FALSE); ! if (!xdr_int(xdrs, &objp->vsa_aclcnt)) return (FALSE); ! if (objp->vsa_aclentp != NULL) count = (uint_t)objp->vsa_aclcnt; ! else ! count = 0; if (!xdr_array(xdrs, (char **)&objp->vsa_aclentp, &count, ! NFS_ACL_MAX_ENTRIES, sizeof (aclent_t), (xdrproc_t)xdr_aclent)) return (FALSE); if (count != 0 && count != (uint_t)objp->vsa_aclcnt) { /* * Assign the actual array size to vsa_aclcnt before * aborting on error */ objp->vsa_aclcnt = (int)count; return (FALSE); } ! if (!xdr_int(xdrs, &objp->vsa_dfaclcnt)) return (FALSE); ! if (objp->vsa_dfaclentp != NULL) ! count = (uint_t)objp->vsa_dfaclcnt; ! else ! count = 0; ! if (!xdr_array(xdrs, (char **)&objp->vsa_dfaclentp, &count, ! NFS_ACL_MAX_ENTRIES, sizeof (aclent_t), (xdrproc_t)xdr_aclent)) return (FALSE); ! if (count != 0 && count != (uint_t)objp->vsa_dfaclcnt) { /* * Assign the actual array size to vsa_dfaclcnt before * aborting on error */ ! objp->vsa_dfaclcnt = (int)count; return (FALSE); } return (TRUE); } bool_t xdr_GETACL2args(XDR *xdrs, GETACL2args *objp) --- 81,183 ---- if (!xdr_o_mode(xdrs, &objp->a_perm)) return (FALSE); return (TRUE); } + /* + * Serialize and de-serialize access control attributes + */ bool_t xdr_secattr(XDR *xdrs, vsecattr_t *objp) { ! uint_t count = 0; ! uint_t dfacount = 0; ! if (!xdr_u_int(xdrs, &objp->vsa_mask)) { return (FALSE); ! } ! ! /* ! * Refuse request if we do not understand it completely. ! * There should be at least one valid bit set in the mask and ! * none of the unknown bits set. ! */ ! if ((objp->vsa_mask & ! (VSA_ACL | VSA_ACLCNT | VSA_DFACL | VSA_DFACLCNT)) == 0) { return (FALSE); ! } ! if ((objp->vsa_mask & ! ~(VSA_ACL | VSA_ACLCNT | VSA_DFACL | VSA_DFACLCNT)) != 0) { ! return (FALSE); ! } ! ! if (!xdr_int(xdrs, &objp->vsa_aclcnt)) { ! return (FALSE); ! } ! if (objp->vsa_aclentp != NULL) { count = (uint_t)objp->vsa_aclcnt; ! } ! if (!xdr_array(xdrs, (char **)&objp->vsa_aclentp, &count, ! NFS_ACL_MAX_ENTRIES, sizeof (aclent_t), (xdrproc_t)xdr_aclent)) { return (FALSE); + } + if (count != 0 && count != (uint_t)objp->vsa_aclcnt) { /* * Assign the actual array size to vsa_aclcnt before * aborting on error */ objp->vsa_aclcnt = (int)count; return (FALSE); } ! ! /* ! * For VSA_ACL the count should be zero or there should ! * be array attached. ! */ ! if ((objp->vsa_mask & VSA_ACL) != 0) { ! if ((objp->vsa_aclcnt != 0) && (objp->vsa_aclentp == NULL)) { ! objp->vsa_aclcnt = 0; return (FALSE); ! } ! } ! ! if (!xdr_int(xdrs, &objp->vsa_dfaclcnt)) { return (FALSE); ! } ! if (objp->vsa_dfaclentp != NULL) { ! dfacount = (uint_t)objp->vsa_dfaclcnt; ! } ! ! if (!xdr_array(xdrs, (char **)&objp->vsa_dfaclentp, &dfacount, ! NFS_ACL_MAX_ENTRIES, sizeof (aclent_t), (xdrproc_t)xdr_aclent)) { ! return (FALSE); ! } ! ! if (dfacount != 0 && dfacount != (uint_t)objp->vsa_dfaclcnt) { /* * Assign the actual array size to vsa_dfaclcnt before * aborting on error */ ! objp->vsa_dfaclcnt = (int)dfacount; return (FALSE); } + + /* + * for VSA_DFACL The count should be zero or there should + * be array attached + */ + if ((objp->vsa_mask & VSA_DFACL) != 0) { + if ((objp->vsa_dfaclcnt != 0) && + (objp->vsa_dfaclentp == NULL)) { + objp->vsa_dfaclcnt = 0; + return (FALSE); + } + } + + return (TRUE); } bool_t xdr_GETACL2args(XDR *xdrs, GETACL2args *objp)