X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/6d2010ae8f7a6078e10b361c6962983bab233e0f..15129b1c8dbb3650c63b70adb1cad9af601c6c17:/bsd/nfs/nfs4_subs.c diff --git a/bsd/nfs/nfs4_subs.c b/bsd/nfs/nfs4_subs.c index 3d65f7985..50c657b94 100644 --- a/bsd/nfs/nfs4_subs.c +++ b/bsd/nfs/nfs4_subs.c @@ -69,6 +69,19 @@ #include #include +/* + * 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. @@ -426,7 +439,7 @@ out: * 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 @@ -1516,7 +1529,8 @@ nfs4_parsefattr( { 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; @@ -1652,6 +1666,8 @@ nfs4_parsefattr( 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); @@ -1661,11 +1677,12 @@ nfs4_parsefattr( 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)); @@ -1980,15 +1997,18 @@ nfs4_parsefattr( } 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; } @@ -2012,15 +2032,18 @@ nfs4_parsefattr( } 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; } @@ -2457,7 +2480,7 @@ restart: 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; @@ -2547,7 +2570,7 @@ 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; @@ -2603,7 +2626,7 @@ reclaim_locks: 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; @@ -2628,7 +2651,7 @@ reclaim_locks: 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; @@ -2667,4 +2690,3 @@ recheckdeleg: vfs_statfs(nmp->nm_mountp)->f_mntfromname, nmp->nm_stategenid, error); } } -