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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.