From: Sachin Prabhu <sprabhu-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
To: Rabin Vincent <rabin.vincent-VrBV9hrLPhE@public.gmane.org>
Cc: sfrench-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org,
linux-cifs-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Subject: Re: [PATCH] cifs: fix crash due to race in hmac(md5) handling
Date: Mon, 25 Jul 2016 10:51:30 +0100 [thread overview]
Message-ID: <1469440290.8377.6.camel@redhat.com> (raw)
In-Reply-To: <20160721073053.GA31832-VrBV9hrLPhE@public.gmane.org>
On Thu, 2016-07-21 at 09:30 +0200, Rabin Vincent wrote:
> On Wed, Jul 20, 2016 at 02:57:29PM +0100, Sachin Prabhu wrote:
> >
> > Rabin, do you have a reliable reproducer for this case? If yes, can
> > you
> > please point me to it.
> I have only seen one report of the oops in real testing, so I don't
> have
> a case that would reproduce easily on an unmodified kernel, but while
> investigating this I made a debug patch which forces the faulty
> sequence
> to occur and provides a 100% reliable reproducer.
>
> The below patched forces the race condition by making two mount.cifs
> processes wait for each other in the appropriate places.
>
> With the force-race patch applied and without this fix, the crash
> occurs
> every time when the following sequence of commands is run. Tested in
> a
> KVM guest on latest mainline with my "unbreak TCP session reuse"
> patch
> applied.
>
> With the force-race patch applied and with this fix, the mount
> processes
> hang since the race condition can never be satisfied.
Thanks Rabin.
Sachin Prabhu
>
> cp /sbin/mount.cifs /sbin/cifs1
> cp /sbin/mount.cifs /sbin/cifs2
> mkdir -p cifs cifs2
> cifs1 //192.168.1.1/test cifs -o credentials=/creds &
> sleep 2
> cifs2 //192.168.1.1/test2 cifs2 -o credentials=/creds
>
> 8<-------------------------
> diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
> index 8347c90..1ed6dfd 100644
> --- a/fs/cifs/cifsencrypt.c
> +++ b/fs/cifs/cifsencrypt.c
> @@ -35,6 +35,32 @@
> #include <linux/highmem.h>
> #include <crypto/skcipher.h>
>
> +static struct completion completions[100];
> +
> +void hack_set_state(int newstate)
> +{
> + printk("%s: caller %pF sets state to %d\n", current->comm,
> (void *)_RET_IP_, newstate);
> + complete(&completions[newstate]);
> +}
> +
> +void hack_wait_for_state(int state)
> +{
> + printk("%s caller %pF wants state %d\n", current->comm,
> (void *)_RET_IP_, state);
> + wait_for_completion(&completions[state]);
> + printk("%s caller %pF got state %d\n", current->comm, (void
> *)_RET_IP_, state);
> +}
> +
> +static int hack_init(void)
> +{
> + int i;
> +
> + for (i = 0; i < ARRAY_SIZE(completions); i++)
> + init_completion(&completions[i]);
> +
> + return 0;
> +}
> +late_initcall(hack_init);
> +
> static int
> cifs_crypto_shash_md5_allocate(struct TCP_Server_Info *server)
> {
> @@ -54,6 +80,7 @@ cifs_crypto_shash_md5_allocate(struct
> TCP_Server_Info *server)
>
> size = sizeof(struct shash_desc) +
> crypto_shash_descsize(server->secmech.md5);
> +
> server->secmech.sdescmd5 = kmalloc(size, GFP_KERNEL);
> if (!server->secmech.sdescmd5) {
> crypto_free_shash(server->secmech.md5);
> @@ -661,8 +688,10 @@ static int crypto_hmacmd5_alloc(struct
> TCP_Server_Info *server)
> unsigned int size;
>
> /* check if already allocated */
> - if (server->secmech.sdeschmacmd5)
> + if (server->secmech.sdeschmacmd5) {
> + printk("%s: server %p already allocated\n",
> __func__, server);
> return 0;
> + }
>
> server->secmech.hmacmd5 = crypto_alloc_shash("hmac(md5)", 0,
> 0);
> if (IS_ERR(server->secmech.hmacmd5)) {
> @@ -674,12 +703,28 @@ static int crypto_hmacmd5_alloc(struct
> TCP_Server_Info *server)
>
> size = sizeof(struct shash_desc) +
> crypto_shash_descsize(server-
> >secmech.hmacmd5);
> +
> + if (!strcmp(current->comm, "cifs1")) {
> + hack_wait_for_state(10);
> + }
> + if (!strcmp(current->comm, "cifs2")) {
> + hack_set_state(10);
> + hack_wait_for_state(20);
> + }
> +
> server->secmech.sdeschmacmd5 = kmalloc(size, GFP_KERNEL);
> + printk("%s: %s: server %p alloc sdeschmacmd5=%p\n",
> __func__, current->comm, server, server->secmech.sdeschmacmd5);
> if (!server->secmech.sdeschmacmd5) {
> crypto_free_shash(server->secmech.hmacmd5);
> server->secmech.hmacmd5 = NULL;
> return -ENOMEM;
> }
> +
> + if (!strcmp(current->comm, "cifs2")) {
> + hack_set_state(30);
> + hack_wait_for_state(40);
> + }
> +
> server->secmech.sdeschmacmd5->shash.tfm = server-
> >secmech.hmacmd5;
> server->secmech.sdeschmacmd5->shash.flags = 0x0;
>
> @@ -745,6 +790,7 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const
> struct nls_table *nls_cp)
>
> mutex_lock(&ses->server->srv_mutex);
>
> + printk("%s: ses %p ses->server %p\n", __func__, ses, ses-
> >server);
> rc = crypto_hmacmd5_alloc(ses->server);
> if (rc) {
> cifs_dbg(VFS, "could not crypto alloc hmacmd5 rc
> %d\n", rc);
> @@ -780,6 +826,11 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const
> struct nls_table *nls_cp)
> goto unlock;
> }
>
> + if (!strcmp(current->comm, "cifs1")) {
> + hack_set_state(20);
> + hack_wait_for_state(30);
> + }
> +
> rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5-
> >shash,
> ntlmv2->ntlmv2_hash,
> CIFS_HMAC_MD5_HASH_SIZE);
> @@ -788,6 +839,8 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const
> struct nls_table *nls_cp)
> goto unlock;
> }
>
> + hack_set_state(40);
> +
> rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5-
> >shash,
> ses->auth_key.response);
> if (rc)
next prev parent reply other threads:[~2016-07-25 9:51 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-07-19 7:26 [PATCH] cifs: fix crash due to race in hmac(md5) handling Rabin Vincent
[not found] ` <1468913181-28163-1-git-send-email-rabin.vincent-VrBV9hrLPhE@public.gmane.org>
2016-07-20 13:57 ` Sachin Prabhu
[not found] ` <1469023049.4942.21.camel-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2016-07-21 7:30 ` Rabin Vincent
[not found] ` <20160721073053.GA31832-VrBV9hrLPhE@public.gmane.org>
2016-07-25 9:51 ` Sachin Prabhu [this message]
2016-07-20 15:54 ` Steve French
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1469440290.8377.6.camel@redhat.com \
--to=sprabhu-h+wxahxf7alqt0dzr+alfa@public.gmane.org \
--cc=linux-cifs-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=rabin.vincent-VrBV9hrLPhE@public.gmane.org \
--cc=sfrench-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox