From patchwork Sun Oct 10 18:56:50 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Broz X-Patchwork-Id: 244591 Received: from mx01.colomx.prod.int.phx2.redhat.com (mx3-phx2.redhat.com [209.132.183.24]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id o9AJ905w021542 for ; Sun, 10 Oct 2010 19:09:21 GMT Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by mx01.colomx.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o9AJ6X28016493; Sun, 10 Oct 2010 15:06:34 -0400 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o9AIuviI028951 for ; Sun, 10 Oct 2010 14:56:57 -0400 Received: from [10.36.6.72] (vpn1-6-72.ams2.redhat.com [10.36.6.72]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o9AIuo7w015421; Sun, 10 Oct 2010 14:56:50 -0400 Message-ID: <4CB20C72.3030504@redhat.com> Date: Sun, 10 Oct 2010 20:56:50 +0200 From: Milan Broz User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.9) Gecko/20100914 Thunderbird/3.1.3 MIME-Version: 1.0 To: Mike Snitzer References: <20101010115941.GA8539@basil.fritz.box> <4CB1B3B9.4030205@redhat.com> <20101010130842.GE8256@basil.fritz.box> <4CB1DD1A.5080906@redhat.com> <20101010162257.GA1272@redhat.com> <4CB1ECCA.8040801@redhat.com> <20101010170750.GA1475@redhat.com> In-Reply-To: <20101010170750.GA1475@redhat.com> X-Enigmail-Version: 1.1.2 X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 X-loop: dm-devel@redhat.com X-Mailman-Approved-At: Sun, 10 Oct 2010 15:06:31 -0400 Cc: Andi Kleen , linux-kernel@vger.kernel.org, device-mapper development , Andi Kleen , pedrib@gmail.com, Alasdair G Kergon Subject: [dm-devel] [PATCH] Fix double free and use generic private pointer in per-cpu struct X-BeenThere: dm-devel@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk Reply-To: device-mapper development List-Id: device-mapper development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: dm-devel-bounces@redhat.com Errors-To: dm-devel-bounces@redhat.com X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Sun, 10 Oct 2010 19:09:21 +0000 (UTC) diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 8802e1d..88a2a05 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -82,11 +82,6 @@ struct iv_essiv_private { u8 *salt; }; -/* Duplicated per CPU state for cipher */ -struct iv_essiv_private_cpu { - struct crypto_cipher *tfm; -}; - struct iv_benbi_private { int shift; }; @@ -101,7 +96,9 @@ enum flags { DM_CRYPT_SUSPENDED, DM_CRYPT_KEY_VALID }; struct crypt_cpu { struct ablkcipher_request *req; struct crypto_ablkcipher *tfm; - struct iv_essiv_private_cpu ie; + + /* ESSIV: struct crypto_cipher *essiv_tfm */ + void *iv_private; }; /* @@ -234,6 +231,8 @@ static int crypt_iv_essiv_init(struct crypt_config *cc) struct iv_essiv_private *essiv = &cc->iv_gen_private.essiv; struct hash_desc desc; struct scatterlist sg; + struct crypt_cpu *cs; + struct crypto_cipher *essiv_tfm; int err, n, cpu; sg_init_one(&sg, cc->key, cc->key_size); @@ -245,9 +244,10 @@ static int crypt_iv_essiv_init(struct crypt_config *cc) return err; for_each_possible_cpu (cpu) { - struct crypt_cpu *cs = per_cpu_ptr(cc->cpu, cpu); + cs = per_cpu_ptr(cc->cpu, cpu); + essiv_tfm = cs->iv_private, - n = crypto_cipher_setkey(cs->ie.tfm, essiv->salt, + n = crypto_cipher_setkey(essiv_tfm, essiv->salt, crypto_hash_digestsize(essiv->hash_tfm)); if (n) { err = n; @@ -263,14 +263,17 @@ static int crypt_iv_essiv_wipe(struct crypt_config *cc) { struct iv_essiv_private *essiv = &cc->iv_gen_private.essiv; unsigned salt_size = crypto_hash_digestsize(essiv->hash_tfm); + struct crypt_cpu *cs; + struct crypto_cipher *essiv_tfm; int cpu, err, n; memset(essiv->salt, 0, salt_size); err = 0; for_each_possible_cpu (cpu) { - struct crypt_cpu *cs = per_cpu_ptr(cc->cpu, cpu); - n = crypto_cipher_setkey(cs->ie.tfm, essiv->salt, salt_size); + cs = per_cpu_ptr(cc->cpu, cpu); + essiv_tfm = cs->iv_private; + n = crypto_cipher_setkey(essiv_tfm, essiv->salt, salt_size); if (n) err = n; } @@ -312,6 +315,8 @@ static struct crypto_cipher *setup_essiv_cpu(struct crypt_config *cc, static void crypt_iv_essiv_dtr(struct crypt_config *cc) { int cpu; + struct crypt_cpu *cs; + struct crypto_cipher *essiv_tfm; struct iv_essiv_private *essiv = &cc->iv_gen_private.essiv; crypto_free_hash(essiv->hash_tfm); @@ -321,11 +326,11 @@ static void crypt_iv_essiv_dtr(struct crypt_config *cc) essiv->salt = NULL; for_each_possible_cpu (cpu) { - struct crypt_cpu *cs = per_cpu_ptr(cc->cpu, cpu); - if (cs->ie.tfm) { - crypto_free_cipher(cs->ie.tfm); - cs->ie.tfm = NULL; - } + cs = per_cpu_ptr(cc->cpu, cpu); + essiv_tfm = cs->iv_private; + if (essiv_tfm) + crypto_free_cipher(essiv_tfm); + cs->iv_private = NULL; } } @@ -365,11 +370,10 @@ static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti, essiv_tfm = setup_essiv_cpu(cc, ti, salt, crypto_hash_digestsize(hash_tfm)); if (IS_ERR(essiv_tfm)) { - kfree(salt); crypt_iv_essiv_dtr(cc); return PTR_ERR(essiv_tfm); } - per_cpu_ptr(cc->cpu, cpu)->ie.tfm = essiv_tfm; + per_cpu_ptr(cc->cpu, cpu)->iv_private = essiv_tfm; } return 0; @@ -382,9 +386,11 @@ bad: static int crypt_iv_essiv_gen(struct crypt_config *cc, u8 *iv, sector_t sector) { + struct crypto_cipher *essiv_tfm = crypt_me(cc)->iv_private; + memset(iv, 0, cc->iv_size); *(u64 *)iv = cpu_to_le64(sector); - crypto_cipher_encrypt_one(crypt_me(cc)->ie.tfm, iv, iv); + crypto_cipher_encrypt_one(essiv_tfm, iv, iv); return 0; }