Description: Fix CVE-2023-49933/49935/49936/49937/49938
 Fix improper enforcement of message integrity during transmission in a
 communication channel that allows attackers to modify RPC traffic in a way that
 bypasses message hash checks. Fix a NULL pointer dereference that leads to denial of
 service. Fix a double free that allows attackers to cause a denial of service or
 possibly execute arbitrary code. Fix incorrect access control that can enable
 an attacker to modify their extended group list that is used with the sbcast
 subsystem, and open files with an unauthorized set of extended groups.
Author: Tim Wickberg <tim@schedmd.com>
Last-Update: 2023-12-25

diff --git a/src/common/pack.c b/src/common/pack.c
index b7e048b02d..75238188a9 100644
--- a/src/common/pack.c
+++ b/src/common/pack.c
@@ -521,17 +521,16 @@ void pack16_array(uint16_t *valp, uint32_t size_val, buf_t *buffer)
  */
 int unpack16_array(uint16_t **valp, uint32_t *size_val, buf_t *buffer)
 {
-	uint32_t i = 0;
-
-	if (unpack32(size_val, buffer))
-		return SLURM_ERROR;
-
-	*valp = xmalloc_nz((*size_val) * sizeof(uint16_t));
-	for (i = 0; i < *size_val; i++) {
-		if (unpack16((*valp) + i, buffer))
-			return SLURM_ERROR;
-	}
+	*valp = NULL;
+	safe_unpack32(size_val, buffer);
+	safe_xcalloc(*valp, *size_val, sizeof(uint16_t));
+	for (uint32_t i = 0; i < *size_val; i++)
+		safe_unpack16(&(*valp)[i], buffer);
 	return SLURM_SUCCESS;
+
+unpack_error:
+	xfree(*valp);
+	return SLURM_ERROR;
 }
 
 /*
@@ -555,17 +554,16 @@ void pack32_array(uint32_t *valp, uint32_t size_val, buf_t *buffer)
  */
 int unpack32_array(uint32_t **valp, uint32_t *size_val, buf_t *buffer)
 {
-	uint32_t i = 0;
-
-	if (unpack32(size_val, buffer))
-		return SLURM_ERROR;
-
-	*valp = xmalloc_nz((*size_val) * sizeof(uint32_t));
-	for (i = 0; i < *size_val; i++) {
-		if (unpack32((*valp) + i, buffer))
-			return SLURM_ERROR;
-	}
+	*valp = NULL;
+	safe_unpack32(size_val, buffer);
+	safe_xcalloc(*valp, *size_val, sizeof(uint32_t));
+	for (uint32_t i = 0; i < *size_val; i++)
+		safe_unpack32(&(*valp)[i], buffer);
 	return SLURM_SUCCESS;
+
+unpack_error:
+	xfree(*valp);
+	return SLURM_ERROR;
 }
 
 /*
@@ -588,17 +586,16 @@ void pack64_array(uint64_t *valp, uint32_t size_val, buf_t *buffer)
  */
 int unpack64_array(uint64_t **valp, uint32_t *size_val, buf_t *buffer)
 {
-	uint32_t i = 0;
-
-	if (unpack32(size_val, buffer))
-		return SLURM_ERROR;
-
-	*valp = xmalloc_nz((*size_val) * sizeof(uint64_t));
-	for (i = 0; i < *size_val; i++) {
-		if (unpack64((*valp) + i, buffer))
-			return SLURM_ERROR;
-	}
+	*valp = NULL;
+	safe_unpack32(size_val, buffer);
+	safe_xcalloc(*valp, *size_val, sizeof(uint64_t));
+	for (uint32_t i = 0; i < *size_val; i++)
+		safe_unpack64(&(*valp)[i], buffer);
 	return SLURM_SUCCESS;
+
+unpack_error:
+	xfree(*valp);
+	return SLURM_ERROR;
 }
 
 void packdouble_array(double *valp, uint32_t size_val, buf_t *buffer)
@@ -616,17 +613,16 @@ void packdouble_array(double *valp, uint32_t size_val, buf_t *buffer)
 
 int unpackdouble_array(double **valp, uint32_t* size_val, buf_t *buffer)
 {
-	uint32_t i = 0;
-
-	if (unpack32(size_val, buffer))
-		return SLURM_ERROR;
-
-	*valp = xmalloc_nz((*size_val) * sizeof(double));
-	for (i = 0; i < *size_val; i++) {
-		if (unpackdouble((*valp) + i, buffer))
-			return SLURM_ERROR;
-	}
+	*valp = NULL;
+	safe_unpack32(size_val, buffer);
+	safe_xcalloc(*valp, *size_val, sizeof(double));
+	for (uint32_t i = 0; i < *size_val; i++)
+		safe_unpackdouble(&(*valp)[i], buffer);
 	return SLURM_SUCCESS;
+
+unpack_error:
+	xfree(*valp);
+	return SLURM_ERROR;
 }
 
 void packlongdouble_array(long double *valp, uint32_t size_val, buf_t *buffer)
@@ -645,17 +641,16 @@ void packlongdouble_array(long double *valp, uint32_t size_val, buf_t *buffer)
 int unpacklongdouble_array(long double **valp, uint32_t *size_val,
 			   buf_t *buffer)
 {
-	uint32_t i = 0;
-
-	if (unpack32(size_val, buffer))
-		return SLURM_ERROR;
-
-	*valp = xmalloc_nz((*size_val) * sizeof(long double));
-	for (i = 0; i < *size_val; i++) {
-		if (unpacklongdouble((*valp) + i, buffer))
-			return SLURM_ERROR;
-	}
+	*valp = NULL;
+	safe_unpack32(size_val, buffer);
+	safe_xcalloc(*valp, *size_val, sizeof(long double));
+	for (uint32_t i = 0; i < *size_val; i++)
+		safe_unpacklongdouble(&(*valp)[i], buffer);
 	return SLURM_SUCCESS;
+
+unpack_error:
+	xfree(*valp);
+	return SLURM_ERROR;
 }
 
 
@@ -835,28 +830,29 @@ extern void packmem(void *valp, uint32_t size_val, buf_t *buffer)
  */
 int unpackmem_ptr(char **valp, uint32_t *size_valp, buf_t *buffer)
 {
-	uint32_t ns;
-
-	if (remaining_buf(buffer) < sizeof(ns))
-		return SLURM_ERROR;
+	*valp = NULL;
+	safe_unpack32(size_valp, buffer);
 
-	memcpy(&ns, &buffer->head[buffer->processed], sizeof(ns));
-	*size_valp = ntohl(ns);
-	buffer->processed += sizeof(ns);
+	if (!*size_valp)
+		return SLURM_SUCCESS;
 
 	if (*size_valp > MAX_PACK_MEM_LEN) {
 		error("%s: Buffer to be unpacked is too large (%u > %u)",
 		      __func__, *size_valp, MAX_PACK_MEM_LEN);
-		return SLURM_ERROR;
+		goto unpack_error;
 	}
-	else if (*size_valp > 0) {
-		if (remaining_buf(buffer) < *size_valp)
-			return SLURM_ERROR;
-		*valp = &buffer->head[buffer->processed];
-		buffer->processed += *size_valp;
-	} else
-		*valp = NULL;
+
+	if (remaining_buf(buffer) < *size_valp)
+		goto unpack_error;
+
+	*valp = &buffer->head[buffer->processed];
+	buffer->processed += *size_valp;
+
 	return SLURM_SUCCESS;
+
+unpack_error:
+	*size_valp = 0;
+	return SLURM_ERROR;
 }
 
 /*
@@ -870,30 +866,30 @@ int unpackmem_ptr(char **valp, uint32_t *size_valp, buf_t *buffer)
  */
 int unpackmem_xmalloc(char **valp, uint32_t *size_valp, buf_t *buffer)
 {
-	uint32_t ns;
-
-	if (remaining_buf(buffer) < sizeof(ns))
-		return SLURM_ERROR;
+	*valp = NULL;
+	safe_unpack32(size_valp, buffer);
 
-	memcpy(&ns, &buffer->head[buffer->processed], sizeof(ns));
-	*size_valp = ntohl(ns);
-	buffer->processed += sizeof(ns);
+	if (!*size_valp)
+		return SLURM_SUCCESS;
 
 	if (*size_valp > MAX_PACK_MEM_LEN) {
 		error("%s: Buffer to be unpacked is too large (%u > %u)",
 		      __func__, *size_valp, MAX_PACK_MEM_LEN);
-		return SLURM_ERROR;
+		goto unpack_error;
 	}
-	else if (*size_valp > 0) {
-		if (remaining_buf(buffer) < *size_valp)
-			return SLURM_ERROR;
-		*valp = xmalloc_nz(*size_valp);
-		memcpy(*valp, &buffer->head[buffer->processed],
-		       *size_valp);
-		buffer->processed += *size_valp;
-	} else
-		*valp = NULL;
+
+	if (remaining_buf(buffer) < *size_valp)
+		goto unpack_error;
+
+	safe_xmalloc(*valp, *size_valp);
+	memcpy(*valp, &buffer->head[buffer->processed], *size_valp);
+	buffer->processed += *size_valp;
+
 	return SLURM_SUCCESS;
+
+unpack_error:
+	*size_valp = 0;
+	return SLURM_ERROR;
 }
 
 /*
@@ -907,34 +903,31 @@ int unpackmem_xmalloc(char **valp, uint32_t *size_valp, buf_t *buffer)
  */
 int unpackmem_malloc(char **valp, uint32_t *size_valp, buf_t *buffer)
 {
-	uint32_t ns;
-
-	if (remaining_buf(buffer) < sizeof(ns))
-		return SLURM_ERROR;
+	*valp = NULL;
+	safe_unpack32(size_valp, buffer);
 
-	memcpy(&ns, &buffer->head[buffer->processed], sizeof(ns));
-	*size_valp = ntohl(ns);
-	buffer->processed += sizeof(ns);
+	if (!*size_valp)
+		return SLURM_SUCCESS;
 
 	if (*size_valp > MAX_PACK_MEM_LEN) {
 		error("%s: Buffer to be unpacked is too large (%u > %u)",
 		      __func__, *size_valp, MAX_PACK_MEM_LEN);
-		return SLURM_ERROR;
+		goto unpack_error;
 	}
-	else if (*size_valp > 0) {
-		if (remaining_buf(buffer) < *size_valp)
-			return SLURM_ERROR;
-		*valp = malloc(*size_valp);
-		if (*valp == NULL) {
-			log_oom(__FILE__, __LINE__, __func__);
-			abort();
-		}
-		memcpy(*valp, &buffer->head[buffer->processed],
-		       *size_valp);
-		buffer->processed += *size_valp;
-	} else
-		*valp = NULL;
+
+	if (remaining_buf(buffer) < *size_valp)
+		goto unpack_error;
+
+	if (!(*valp = malloc(*size_valp)))
+		goto unpack_error;
+	memcpy(*valp, &buffer->head[buffer->processed], *size_valp);
+	buffer->processed += *size_valp;
+
 	return SLURM_SUCCESS;
+
+unpack_error:
+	*size_valp = 0;
+	return SLURM_ERROR;
 }
 
 /*
@@ -953,52 +946,49 @@ int unpackmem_malloc(char **valp, uint32_t *size_valp, buf_t *buffer)
  */
 int unpackstr_xmalloc_escaped(char **valp, uint32_t *size_valp, buf_t *buffer)
 {
-	uint32_t ns;
+	uint32_t cnt;
+	char *copy = NULL, *str, tmp;
 
-	if (remaining_buf(buffer) < sizeof(ns))
-		return SLURM_ERROR;
+	*valp = NULL;
+	safe_unpack32(size_valp, buffer);
 
-	memcpy(&ns, &buffer->head[buffer->processed], sizeof(ns));
-	*size_valp = ntohl(ns);
-	buffer->processed += sizeof(ns);
+	if (!*size_valp)
+		return SLURM_SUCCESS;
 
 	if (*size_valp > MAX_PACK_MEM_LEN) {
 		error("%s: Buffer to be unpacked is too large (%u > %u)",
 		      __func__, *size_valp, MAX_PACK_MEM_LEN);
 		return SLURM_ERROR;
-	} else if (*size_valp > 0) {
-		uint32_t cnt = *size_valp;
-
-		if (remaining_buf(buffer) < cnt)
-			return SLURM_ERROR;
-
-		/* make a buffer 2 times the size just to be safe */
-		*valp = xmalloc_nz((cnt * 2) + 1);
-		if (*valp) {
-			char *copy = NULL, *str, tmp;
-			uint32_t i;
-			copy = *valp;
-			str = &buffer->head[buffer->processed];
-
-			for (i = 0; i < cnt && *str; i++) {
-				tmp = *str++;
-				if ((tmp == '\\') || (tmp == '\'')) {
-					*copy++ = '\\';
-					(*size_valp)++;
-				}
-
-				*copy++ = tmp;
-			}
-
-			/* Since we used xmalloc_nz, terminate the string. */
-			*copy++ = '\0';
+	}
+
+	cnt = *size_valp;
+
+	if (remaining_buf(buffer) < cnt)
+		return SLURM_ERROR;
+
+	/* make a buffer 2 times the size just to be safe */
+	safe_xmalloc(*valp, (cnt * 2) + 1);
+	copy = *valp;
+	str = &buffer->head[buffer->processed];
+
+	for (uint32_t i = 0; i < cnt && *str; i++) {
+		tmp = *str++;
+		if ((tmp == '\\') || (tmp == '\'')) {
+			*copy++ = '\\';
+			(*size_valp)++;
 		}
 
-		/* add the original value since that is what we processed */
-		buffer->processed += cnt;
-	} else
-		*valp = NULL;
+		*copy++ = tmp;
+	}
+
+	/* add the original value since that is what we processed */
+	buffer->processed += cnt;
+
 	return SLURM_SUCCESS;
+
+unpack_error:
+	*size_valp = 0;
+	return SLURM_ERROR;
 }
 
 int unpackstr_xmalloc_chooser(char **valp, uint32_t *size_valp, buf_t *buf)
@@ -1050,29 +1040,24 @@ void packstr_array(char **valp, uint32_t size_val, buf_t *buffer)
  */
 int unpackstr_array(char ***valp, uint32_t *size_valp, buf_t *buffer)
 {
-	int i;
-	uint32_t ns;
-	uint32_t uint32_tmp;
+	*valp = NULL;
+	safe_unpack32(size_valp, buffer);
 
-	if (remaining_buf(buffer) < sizeof(ns))
-		return SLURM_ERROR;
+	if (!*size_valp)
+		return SLURM_SUCCESS;
 
-	memcpy(&ns, &buffer->head[buffer->processed], sizeof(ns));
-	*size_valp = ntohl(ns);
-	buffer->processed += sizeof(ns);
+	if (*size_valp > MAX_PACK_MEM_LEN)
+		goto unpack_error;
 
-	if (*size_valp > 0) {
-		*valp = xcalloc(*size_valp + 1, sizeof(char *));
-		for (i = 0; i < *size_valp; i++) {
-			if (unpackmem_xmalloc(&(*valp)[i], &uint32_tmp, buffer)) {
-				*size_valp = 0;
-				xfree_array(*valp);
-				return SLURM_ERROR;
-			}
-		}
-	} else
-		*valp = NULL;
+	safe_xcalloc(*valp, *size_valp + 1, sizeof(char *));
+	for (uint32_t i = 0; i < *size_valp; i++)
+		safe_unpackstr(&(*valp)[i], buffer);
 	return SLURM_SUCCESS;
+
+unpack_error:
+	*size_valp = 0;
+	xfree_array(*valp);
+	return SLURM_ERROR;
 }
 
 /*
diff --git a/src/common/slurm_cred.c b/src/common/slurm_cred.c
index be333665fb..51f0f42e3d 100644
--- a/src/common/slurm_cred.c
+++ b/src/common/slurm_cred.c
@@ -185,7 +185,8 @@ typedef struct {
 	int   (*cred_verify_sign)	(void *key, char *buffer,
 					 uint32_t buf_size,
 					 char *signature,
-					 uint32_t sig_size);
+					 uint32_t sig_size,
+					 bool replay_okay);
 	const char *(*cred_str_error)	(int);
 } slurm_cred_ops_t;
 
@@ -269,8 +270,6 @@ static void _cred_state_pack(slurm_cred_ctx_t ctx, buf_t *buffer);
 static void _job_state_pack_one(job_state_t *j, buf_t *buffer);
 static void _cred_state_pack_one(cred_state_t *s, buf_t *buffer);
 
-static void _sbast_cache_add(sbcast_cred_t *sbcast_cred);
-
 static int _slurm_cred_init(void)
 {
 	char *tok;
@@ -1773,11 +1772,11 @@ static void _cred_verify_signature(slurm_cred_ctx_t ctx, slurm_cred_t *cred)
 
 	rc = (*(ops.cred_verify_sign))(ctx->key, start, len,
 				       cred->signature,
-				       cred->siglen);
+				       cred->siglen, true);
 	if (rc && _exkey_is_valid(ctx)) {
 		rc = (*(ops.cred_verify_sign))(ctx->exkey, start, len,
 					       cred->signature,
-					       cred->siglen);
+					       cred->siglen, true);
 	}
 
 	if (rc) {
@@ -2444,25 +2443,6 @@ void delete_sbcast_cred(sbcast_cred_t *sbcast_cred)
 	xfree(sbcast_cred);
 }
 
-static void _sbast_cache_add(sbcast_cred_t *sbcast_cred)
-{
-	int i;
-	uint32_t sig_num = 0;
-	struct sbcast_cache *new_cache_rec;
-
-	/* Using two bytes at a time gives us a larger number
-	 * and reduces the possibility of a duplicate value */
-	for (i = 0; i < sbcast_cred->siglen; i += 2) {
-		sig_num += (sbcast_cred->signature[i] << 8) +
-			   sbcast_cred->signature[i+1];
-	}
-
-	new_cache_rec = xmalloc(sizeof(struct sbcast_cache));
-	new_cache_rec->expire = sbcast_cred->expiration;
-	new_cache_rec->value  = sig_num;
-	list_append(sbcast_cache_list, new_cache_rec);
-}
-
 /* Extract contents of an sbcast credential verifying the digital signature.
  * NOTE: We can only perform the full credential validation once with
  *	Munge without generating a credential replay error, so we only
@@ -2477,9 +2457,7 @@ sbcast_cred_arg_t *extract_sbcast_cred(slurm_cred_ctx_t ctx,
 				       uint16_t protocol_version)
 {
 	sbcast_cred_arg_t *arg;
-	struct sbcast_cache *next_cache_rec;
-	uint32_t sig_num = 0;
-	int i, rc;
+	int rc;
 	time_t now = time(NULL);
 	buf_t *buffer;
 
@@ -2491,14 +2469,14 @@ sbcast_cred_arg_t *extract_sbcast_cred(slurm_cred_ctx_t ctx,
 	if (now > sbcast_cred->expiration)
 		return NULL;
 
-	if (block_no == 1 && !(flags & FILE_BCAST_SO)) {
+	if (block_no == 1) {
 		buffer = init_buf(4096);
 		_pack_sbcast_cred(sbcast_cred, buffer, protocol_version);
 		/* NOTE: the verification checks that the credential was
 		 * created by SlurmUser or root */
 		rc = (*(ops.cred_verify_sign)) (
 			ctx->key, get_buf_data(buffer), get_buf_offset(buffer),
-			sbcast_cred->signature, sbcast_cred->siglen);
+			sbcast_cred->signature, sbcast_cred->siglen, false);
 		free_buf(buffer);
 
 		if (rc) {
@@ -2506,51 +2484,6 @@ sbcast_cred_arg_t *extract_sbcast_cred(slurm_cred_ctx_t ctx,
 			      (*(ops.cred_str_error))(rc));
 			return NULL;
 		}
-		_sbast_cache_add(sbcast_cred);
-
-	} else {
-		char *err_str = NULL;
-		bool cache_match_found = false;
-		ListIterator sbcast_iter;
-		for (i = 0; i < sbcast_cred->siglen; i += 2) {
-			sig_num += (sbcast_cred->signature[i] << 8) +
-				   sbcast_cred->signature[i+1];
-		}
-
-		sbcast_iter = list_iterator_create(sbcast_cache_list);
-		while ((next_cache_rec =
-			(struct sbcast_cache *) list_next(sbcast_iter))) {
-			if ((next_cache_rec->expire == sbcast_cred->expiration) &&
-			    (next_cache_rec->value  == sig_num)) {
-				cache_match_found = true;
-				break;
-			}
-			if (next_cache_rec->expire <= now)
-				list_delete_item(sbcast_iter);
-		}
-		list_iterator_destroy(sbcast_iter);
-
-		if (!cache_match_found) {
-			error("sbcast_cred verify: signature not in cache");
-			if (SLURM_DIFFTIME(now, cred_restart_time) > 60)
-				return NULL;	/* restarted >60 secs ago */
-			buffer = init_buf(4096);
-			_pack_sbcast_cred(sbcast_cred, buffer,
-					  protocol_version);
-			rc = (*(ops.cred_verify_sign)) (
-				ctx->key, get_buf_data(buffer),
-				get_buf_offset(buffer),
-				sbcast_cred->signature, sbcast_cred->siglen);
-			free_buf(buffer);
-			if (rc)
-				err_str = (char *)(*(ops.cred_str_error))(rc);
-			if (err_str && xstrcmp(err_str, "Credential replayed")){
-				error("sbcast_cred verify: %s", err_str);
-				return NULL;
-			}
-			info("sbcast_cred verify: signature revalidated");
-			_sbast_cache_add(sbcast_cred);
-		}
 	}
 
 	arg = xmalloc(sizeof(sbcast_cred_arg_t));
diff --git a/src/common/slurm_protocol_api.c b/src/common/slurm_protocol_api.c
index daaca01aab..f8d8c4e466 100644
--- a/src/common/slurm_protocol_api.c
+++ b/src/common/slurm_protocol_api.c
@@ -1091,7 +1091,7 @@ extern int slurm_unpack_received_msg(slurm_msg_t *msg, int fd, buf_t *buffer)
 
 	msg->body_offset =  get_buf_offset(buffer);
 
-	if ((header.body_length > remaining_buf(buffer)) ||
+	if ((header.body_length != remaining_buf(buffer)) ||
 	    _check_hash(buffer, &header, msg, auth_cred) ||
 	    (unpack_msg(msg, buffer) != SLURM_SUCCESS)) {
 		rc = ESLURM_PROTOCOL_INCOMPLETE_PACKET;
@@ -1380,7 +1380,7 @@ List slurm_receive_msgs(int fd, int steps, int timeout)
 	msg.msg_type = header.msg_type;
 	msg.flags = header.flags;
 
-	if ((header.body_length > remaining_buf(buffer)) ||
+	if ((header.body_length != remaining_buf(buffer)) ||
 	    _check_hash(buffer, &header, &msg, auth_cred) ||
 	    (unpack_msg(&msg, buffer) != SLURM_SUCCESS)) {
 		(void) auth_g_destroy(auth_cred);
@@ -1804,7 +1804,7 @@ int slurm_receive_msg_and_forward(int fd, slurm_addr_t *orig_addr,
 	msg->msg_type = header.msg_type;
 	msg->flags = header.flags;
 
-	if ( (header.body_length > remaining_buf(buffer)) ||
+	if ((header.body_length != remaining_buf(buffer)) ||
 	    _check_hash(buffer, &header, msg, auth_cred) ||
 	     (unpack_msg(msg, buffer) != SLURM_SUCCESS) ) {
 		(void) auth_g_destroy(auth_cred);
@@ -2119,7 +2119,7 @@ extern int slurm_unpack_addr_array(slurm_addr_t **addr_array_ptr,
 	slurm_addr_t *addr_array = NULL;
 
 	safe_unpack32(size_val, buffer);
-	addr_array = xcalloc(*size_val, sizeof(slurm_addr_t));
+	safe_xcalloc(addr_array, *size_val, sizeof(slurm_addr_t));
 
 	for (int i = 0; i < *size_val; i++) {
 		if (slurm_unpack_addr_no_alloc(&addr_array[i], buffer))
diff --git a/src/common/slurm_protocol_pack.c b/src/common/slurm_protocol_pack.c
index 1bd356687c..ca385ba57a 100644
--- a/src/common/slurm_protocol_pack.c
+++ b/src/common/slurm_protocol_pack.c
@@ -7719,6 +7719,7 @@ static int _unpack_node_reg_resp(
 
 unpack_error:
 	slurm_free_node_reg_resp_msg(msg_ptr);
+	*msg = NULL;
 	return SLURM_ERROR;
 }
 
@@ -13915,6 +13916,15 @@ unpack_msg(slurm_msg_t * msg, buf_t *buffer)
 	if (rc) {
 		error("Malformed RPC of type %s(%u) received",
 		      rpc_num2string(msg->msg_type), msg->msg_type);
+
+		/*
+		 * The unpack functions should not leave this set on error,
+		 * doing so would likely result in a double xfree() if we
+		 * did not proactively clear it. (Which, instead, may cause
+		 * a memory leak. But that's preferrable.)
+		 */
+		xassert(msg->data);
+		msg->data = NULL;
 	}
 	return rc;
 }
diff --git a/src/common/slurm_protocol_socket.c b/src/common/slurm_protocol_socket.c
index ad064516ac..b245d71d5d 100644
--- a/src/common/slurm_protocol_socket.c
+++ b/src/common/slurm_protocol_socket.c
@@ -144,7 +144,8 @@ extern ssize_t slurm_msg_recvfrom_timeout(int fd, char **pbuf, size_t *lenp,
 	/*
 	 *  Allocate memory on heap for message
 	 */
-	*pbuf = xmalloc_nz(msglen);
+	if (!(*pbuf = try_xmalloc(msglen)))
+		slurm_seterrno_ret(ENOMEM);
 
 	if (slurm_recv_timeout(fd, *pbuf, msglen, 0, tmout) != msglen) {
 		xfree(*pbuf);
diff --git a/src/plugins/cred/munge/cred_munge.c b/src/plugins/cred/munge/cred_munge.c
index e7d052eddc..1c2b3f174a 100644
--- a/src/plugins/cred/munge/cred_munge.c
+++ b/src/plugins/cred/munge/cred_munge.c
@@ -234,7 +234,8 @@ again:
 }
 
 extern int cred_p_verify_sign(void *key, char *buffer, uint32_t buf_size,
-			      char *signature, uint32_t sig_size)
+			      char *signature, uint32_t sig_size,
+			      bool replay_okay)
 {
 	int retry = RETRY_COUNT;
 	uid_t uid;
@@ -245,6 +246,10 @@ extern int cred_p_verify_sign(void *key, char *buffer, uint32_t buf_size,
 	munge_err_t err;
 	munge_ctx_t ctx = (munge_ctx_t) key;
 
+#ifdef MULTIPLE_SLURMD
+	replay_okay = true;
+#endif
+
 again:
 	err = munge_decode(signature, ctx, &buf_out, &buf_out_size,
 			   &uid, &gid);
@@ -259,20 +264,17 @@ again:
 		if (err == EMUNGE_SOCKET)
 			error("If munged is up, restart with --num-threads=10");
 
-#ifdef MULTIPLE_SLURMD
 		if (err != EMUNGE_CRED_REPLAYED) {
 			rc = err;
 			goto end_it;
-		} else {
-			debug2("We had a replayed credential, but this is expected in multiple slurmd mode.");
 		}
-#else
-		if (err == EMUNGE_CRED_REPLAYED)
+
+		if (!replay_okay) {
 			rc = ESIG_CRED_REPLAYED;
-		else
-			rc = err;
-		goto end_it;
-#endif
+			goto end_it;
+		}
+
+		debug2("We had a replayed credential, but this is expected.");
 	}
 
 	if ((uid != slurm_conf.slurm_user_id) && (uid != 0)) {
diff --git a/src/plugins/cred/none/cred_none.c b/src/plugins/cred/none/cred_none.c
index e89ec17822..1ee42b1ef1 100644
--- a/src/plugins/cred/none/cred_none.c
+++ b/src/plugins/cred/none/cred_none.c
@@ -129,7 +129,8 @@ extern int cred_p_sign(void *key, char *buffer, int buf_size,
 }
 
 extern int cred_p_verify_sign(void *key, char *buffer, uint32_t buf_size,
-			      char *signature, uint32_t sig_size)
+			      char *signature, uint32_t sig_size,
+			      bool replay_okay)
 {
 	char *correct_signature = "fake signature";
 	if (xstrncmp(signature, correct_signature, sig_size))
