#include <netinet/in.h>
#include <net/kpi_interface.h>
+/*
+ * NFS_MAX_WHO is the maximum length of a string representation used
+ * in as an ace who, owner, or group. There is no explicit limit in the
+ * protocol, however the kauth routines have a limit of MAPATHLEN for
+ * strings including the trailing null character, so we impose that
+ * limit. This should be changed if kauth routines change.
+ *
+ * We also want some reasonable maximum, as 32 bits worth of string length
+ * is liable to cause problems. At the very least this limit must guarantee
+ * that any express that contains the 32 bit length from off the wire used in
+ * allocations does not overflow.
+ */
+#define NFS_MAX_WHO MAXPATHLEN
/*
* Create the unique client ID to use for this mount.
* get the list of supported security flavors
*
* How we get them depends on what args we are given:
- *
+ *
* FH? Name? Action
* ----- ----- ------
* YES YES Use the fh and name provided
{
int error = 0, error2, rderror = 0, attrbytes;
uint32_t val, val2, val3, i;
- uint32_t bitmap[NFS_ATTR_BITMAP_LEN], len, slen;
+ uint32_t bitmap[NFS_ATTR_BITMAP_LEN], len;
+ size_t slen;
char sbuf[64], *s;
struct nfs_fsattr nfsa_dummy;
struct nfs_vattr nva_dummy;
nfsm_chain_get_32(error, nmc, ace_flags);
nfsm_chain_get_32(error, nmc, ace_mask);
nfsm_chain_get_32(error, nmc, len);
+ if (!error && len >= NFS_MAX_WHO)
+ error = EBADRPC;
acl->acl_ace[i].ace_flags = nfs4_ace_nfstype_to_vfstype(ace_type, &error);
acl->acl_ace[i].ace_flags |= nfs4_ace_nfsflags_to_vfsflags(ace_flags);
acl->acl_ace[i].ace_rights = nfs4_ace_nfsmask_to_vfsrights(ace_mask);
s = sbuf;
slen = sizeof(sbuf);
}
- MALLOC(s, char*, len+16, M_TEMP, M_WAITOK);
+ /* Let's add a bit more if we can to the allocation as to try and avoid future allocations */
+ MALLOC(s, char*, (len + 16 < NFS_MAX_WHO) ? len+16 : NFS_MAX_WHO, M_TEMP, M_WAITOK);
if (s)
- slen = len+16;
+ slen = (len + 16 < NFS_MAX_WHO) ? len+16 : NFS_MAX_WHO;
else
- error2 = ENOMEM;
+ error = ENOMEM;
}
if (error2)
nfsm_chain_adv(error, nmc, nfsm_rndup(len));
}
if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_OWNER)) {
nfsm_chain_get_32(error, nmc, len);
+ if (!error && len >= NFS_MAX_WHO)
+ error = EBADRPC;
if (!error && (len >= slen)) {
if (s != sbuf) {
FREE(s, M_TEMP);
s = sbuf;
slen = sizeof(sbuf);
}
- MALLOC(s, char*, len+16, M_TEMP, M_WAITOK);
+ /* Let's add a bit more if we can to the allocation as to try and avoid future allocations */
+ MALLOC(s, char*, (len + 16 < NFS_MAX_WHO) ? len+16 : NFS_MAX_WHO, M_TEMP, M_WAITOK);
if (s)
- slen = len+16;
+ slen = (len + 16 < NFS_MAX_WHO) ? len+16 : NFS_MAX_WHO;
else
error = ENOMEM;
}
}
if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_OWNER_GROUP)) {
nfsm_chain_get_32(error, nmc, len);
+ if (!error && len >= NFS_MAX_WHO)
+ error = EBADRPC;
if (!error && (len >= slen)) {
if (s != sbuf) {
FREE(s, M_TEMP);
s = sbuf;
slen = sizeof(sbuf);
}
- MALLOC(s, char*, len+16, M_TEMP, M_WAITOK);
+ /* Let's add a bit more if we can to the allocation as to try and avoid future allocations */
+ MALLOC(s, char*, (len + 16 < NFS_MAX_WHO) ? len+16 : NFS_MAX_WHO, M_TEMP, M_WAITOK);
if (s)
- slen = len+16;
+ slen = (len + 16 < NFS_MAX_WHO) ? len+16 : NFS_MAX_WHO;
else
error = ENOMEM;
}
if (now.tv_sec == nmp->nm_recover_start) {
printf("nfs recovery throttled for %s, 0x%x\n", vfs_statfs(nmp->nm_mountp)->f_mntfromname, nmp->nm_stategenid);
lck_mtx_unlock(&nmp->nm_lock);
- tsleep(&lbolt, (PZERO-1), "nfsrecoverrestart", hz);
+ tsleep(nfs_recover, (PZERO-1), "nfsrecoverrestart", hz);
goto restart;
}
nmp->nm_recover_start = now.tv_sec;
if ((error == ETIMEDOUT) || nfs_mount_state_error_should_restart(error)) {
if (error == ETIMEDOUT)
nfs_need_reconnect(nmp);
- tsleep(&lbolt, (PZERO-1), "nfsrecoverrestart", 0);
+ tsleep(nfs_recover, (PZERO-1), "nfsrecoverrestart", hz);
printf("nfs recovery restarting for %s, 0x%x, error %d\n",
vfs_statfs(nmp->nm_mountp)->f_mntfromname, nmp->nm_stategenid, error);
goto restart;
if ((error == ETIMEDOUT) || nfs_mount_state_error_should_restart(error)) {
if (error == ETIMEDOUT)
nfs_need_reconnect(nmp);
- tsleep(&lbolt, (PZERO-1), "nfsrecoverrestart", 0);
+ tsleep(nfs_recover, (PZERO-1), "nfsrecoverrestart", hz);
printf("nfs recovery restarting for %s, 0x%x, error %d\n",
vfs_statfs(nmp->nm_mountp)->f_mntfromname, nmp->nm_stategenid, error);
goto restart;
nfs4_delegation_return(nofp->nof_np, R_RECOVER, thd, noop->noo_cred);
if (!(nmp->nm_sockflags & NMSOCK_READY)) {
/* looks like we need a reconnect */
- tsleep(&lbolt, (PZERO-1), "nfsrecoverrestart", 0);
+ tsleep(nfs_recover, (PZERO-1), "nfsrecoverrestart", hz);
printf("nfs recovery restarting for %s, 0x%x, error %d\n",
vfs_statfs(nmp->nm_mountp)->f_mntfromname, nmp->nm_stategenid, error);
goto restart;
vfs_statfs(nmp->nm_mountp)->f_mntfromname, nmp->nm_stategenid, error);
}
}
-