Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit eeeec288 authored by Rabin Vincent's avatar Rabin Vincent Committed by Sasha Levin
Browse files

cifs: fix crash due to race in hmac(md5) handling



[ Upstream commit bd975d1eead2558b76e1079e861eacf1f678b73b ]

The secmech hmac(md5) structures are present in the TCP_Server_Info
struct and can be shared among multiple CIFS sessions.  However, the
server mutex is not currently held when these structures are allocated
and used, which can lead to a kernel crashes, as in the scenario below:

mount.cifs(8) #1				mount.cifs(8) #2

Is secmech.sdeschmaccmd5 allocated?
// false

						Is secmech.sdeschmaccmd5 allocated?
						// false

secmech.hmacmd = crypto_alloc_shash..
secmech.sdeschmaccmd5 = kzalloc..
sdeschmaccmd5->shash.tfm = &secmec.hmacmd;

						secmech.sdeschmaccmd5 = kzalloc
						// sdeschmaccmd5->shash.tfm
						// not yet assigned

crypto_shash_update()
 deref NULL sdeschmaccmd5->shash.tfm

 Unable to handle kernel paging request at virtual address 00000030
 epc   : 8027ba34 crypto_shash_update+0x38/0x158
 ra    : 8020f2e8 setup_ntlmv2_rsp+0x4bc/0xa84
 Call Trace:
  crypto_shash_update+0x38/0x158
  setup_ntlmv2_rsp+0x4bc/0xa84
  build_ntlmssp_auth_blob+0xbc/0x34c
  sess_auth_rawntlmssp_authenticate+0xac/0x248
  CIFS_SessSetup+0xf0/0x178
  cifs_setup_session+0x4c/0x84
  cifs_get_smb_ses+0x2c8/0x314
  cifs_mount+0x38c/0x76c
  cifs_do_mount+0x98/0x440
  mount_fs+0x20/0xc0
  vfs_kern_mount+0x58/0x138
  do_mount+0x1e8/0xccc
  SyS_mount+0x88/0xd4
  syscall_common+0x30/0x54

Fix this by locking the srv_mutex around the code which uses these
hmac(md5) structures.  All the other secmech algos already have similar
locking.

Fixes: 95dc8dd1 ("Limit allocation of crypto mechanisms to dialect which requires")
Signed-off-by: default avatarRabin Vincent <rabinv@axis.com>
Acked-by: default avatarSachin Prabhu <sprabhu@redhat.com>
CC: Stable <stable@vger.kernel.org>
Signed-off-by: default avatarSteve French <smfrench@gmail.com>
Signed-off-by: default avatarSasha Levin <alexander.levin@verizon.com>
parent cb0a0062
Loading
Loading
Loading
Loading
+10 −6
Original line number Original line Diff line number Diff line
@@ -727,24 +727,26 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)


	memcpy(ses->auth_key.response + baselen, tiblob, tilen);
	memcpy(ses->auth_key.response + baselen, tiblob, tilen);


	mutex_lock(&ses->server->srv_mutex);

	rc = crypto_hmacmd5_alloc(ses->server);
	rc = crypto_hmacmd5_alloc(ses->server);
	if (rc) {
	if (rc) {
		cifs_dbg(VFS, "could not crypto alloc hmacmd5 rc %d\n", rc);
		cifs_dbg(VFS, "could not crypto alloc hmacmd5 rc %d\n", rc);
		goto setup_ntlmv2_rsp_ret;
		goto unlock;
	}
	}


	/* calculate ntlmv2_hash */
	/* calculate ntlmv2_hash */
	rc = calc_ntlmv2_hash(ses, ntlmv2_hash, nls_cp);
	rc = calc_ntlmv2_hash(ses, ntlmv2_hash, nls_cp);
	if (rc) {
	if (rc) {
		cifs_dbg(VFS, "could not get v2 hash rc %d\n", rc);
		cifs_dbg(VFS, "could not get v2 hash rc %d\n", rc);
		goto setup_ntlmv2_rsp_ret;
		goto unlock;
	}
	}


	/* calculate first part of the client response (CR1) */
	/* calculate first part of the client response (CR1) */
	rc = CalcNTLMv2_response(ses, ntlmv2_hash);
	rc = CalcNTLMv2_response(ses, ntlmv2_hash);
	if (rc) {
	if (rc) {
		cifs_dbg(VFS, "Could not calculate CR1 rc: %d\n", rc);
		cifs_dbg(VFS, "Could not calculate CR1 rc: %d\n", rc);
		goto setup_ntlmv2_rsp_ret;
		goto unlock;
	}
	}


	/* now calculate the session key for NTLMv2 */
	/* now calculate the session key for NTLMv2 */
@@ -753,13 +755,13 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
	if (rc) {
	if (rc) {
		cifs_dbg(VFS, "%s: Could not set NTLMV2 Hash as a key\n",
		cifs_dbg(VFS, "%s: Could not set NTLMV2 Hash as a key\n",
			 __func__);
			 __func__);
		goto setup_ntlmv2_rsp_ret;
		goto unlock;
	}
	}


	rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
	rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
	if (rc) {
	if (rc) {
		cifs_dbg(VFS, "%s: Could not init hmacmd5\n", __func__);
		cifs_dbg(VFS, "%s: Could not init hmacmd5\n", __func__);
		goto setup_ntlmv2_rsp_ret;
		goto unlock;
	}
	}


	rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
	rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
@@ -767,7 +769,7 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
		CIFS_HMAC_MD5_HASH_SIZE);
		CIFS_HMAC_MD5_HASH_SIZE);
	if (rc) {
	if (rc) {
		cifs_dbg(VFS, "%s: Could not update with response\n", __func__);
		cifs_dbg(VFS, "%s: Could not update with response\n", __func__);
		goto setup_ntlmv2_rsp_ret;
		goto unlock;
	}
	}


	rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash,
	rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash,
@@ -775,6 +777,8 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
	if (rc)
	if (rc)
		cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
		cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);


unlock:
	mutex_unlock(&ses->server->srv_mutex);
setup_ntlmv2_rsp_ret:
setup_ntlmv2_rsp_ret:
	kfree(tiblob);
	kfree(tiblob);