Re: GPF in lrw_crypt

2015-12-24 Thread Herbert Xu
On Thu, Dec 17, 2015 at 01:59:11PM +0100, Dmitry Vyukov wrote:
> 
> The following program causes GPF in lrw_crypt:

OK, this is a result of certain implementations (such as lrw)
not coping with there being no key gracefully.

I think the easiest way is probably to check this in algif_skcipher.

---8<---
Subject: crypto: algif_skcipher - Require setkey before accept(2)

Some cipher implementations will crash if you try to use them
without calling setkey first.  This patch adds a check so that
the accept(2) call will fail with -ENOKEY if setkey hasn't been
done on the socket yet.

Cc: sta...@vger.kernel.org
Reported-by: Dmitry Vyukov <dvyu...@google.com>
Signed-off-by: Herbert Xu <herb...@gondor.apana.org.au>

diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
index 5c756b3..b62c973 100644
--- a/crypto/algif_skcipher.c
+++ b/crypto/algif_skcipher.c
@@ -31,6 +31,11 @@ struct skcipher_sg_list {
struct scatterlist sg[0];
 };
 
+struct skcipher_tfm {
+   struct crypto_skcipher *skcipher;
+   bool has_key;
+};
+
 struct skcipher_ctx {
struct list_head tsgl;
struct af_alg_sgl rsgl;
@@ -750,17 +755,38 @@ static struct proto_ops algif_skcipher_ops = {
 
 static void *skcipher_bind(const char *name, u32 type, u32 mask)
 {
-   return crypto_alloc_skcipher(name, type, mask);
+   struct skcipher_tfm *tfm;
+
+   tfm = kzalloc(sizeof(*tfm), GFP_KERNEL);
+   if (!tfm)
+   return ERR_PTR(-ENOMEM);
+
+   tfm->skcipher = crypto_alloc_skcipher(name, type, mask);
+   if (IS_ERR(tfm->skcipher)) {
+   kfree(tfm);
+   return ERR_CAST(tfm->skcipher);
+   }
+
+   return tfm;
 }
 
 static void skcipher_release(void *private)
 {
-   crypto_free_skcipher(private);
+   struct skcipher_tfm *tfm = private;
+
+   crypto_free_skcipher(tfm->skcipher);
+   kfree(tfm);
 }
 
 static int skcipher_setkey(void *private, const u8 *key, unsigned int keylen)
 {
-   return crypto_skcipher_setkey(private, key, keylen);
+   struct skcipher_tfm *tfm = private;
+   int err;
+
+   err = crypto_skcipher_setkey(tfm->skcipher, key, keylen);
+   tfm->has_key = !err;
+
+   return err;
 }
 
 static void skcipher_wait(struct sock *sk)
@@ -792,20 +818,25 @@ static int skcipher_accept_parent(void *private, struct 
sock *sk)
 {
struct skcipher_ctx *ctx;
struct alg_sock *ask = alg_sk(sk);
-   unsigned int len = sizeof(*ctx) + crypto_skcipher_reqsize(private);
+   struct skcipher_tfm *tfm = private;
+   struct crypto_skcipher *skcipher = tfm->skcipher;
+   unsigned int len = sizeof(*ctx) + crypto_skcipher_reqsize(skcipher);
+
+   if (!tfm->has_key)
+   return -ENOKEY;
 
ctx = sock_kmalloc(sk, len, GFP_KERNEL);
if (!ctx)
return -ENOMEM;
 
-   ctx->iv = sock_kmalloc(sk, crypto_skcipher_ivsize(private),
+   ctx->iv = sock_kmalloc(sk, crypto_skcipher_ivsize(skcipher),
   GFP_KERNEL);
if (!ctx->iv) {
sock_kfree_s(sk, ctx, len);
return -ENOMEM;
}
 
-   memset(ctx->iv, 0, crypto_skcipher_ivsize(private));
+   memset(ctx->iv, 0, crypto_skcipher_ivsize(skcipher));
 
INIT_LIST_HEAD(>tsgl);
ctx->len = len;
@@ -818,7 +849,7 @@ static int skcipher_accept_parent(void *private, struct 
sock *sk)
 
ask->private = ctx;
 
-   skcipher_request_set_tfm(>req, private);
+   skcipher_request_set_tfm(>req, skcipher);
skcipher_request_set_callback(>req, CRYPTO_TFM_REQ_MAY_BACKLOG,
  af_alg_complete, >completion);
 
-- 
Email: Herbert Xu <herb...@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: GPF in lrw_crypt

2015-12-24 Thread Dmitry Vyukov
On Thu, Dec 24, 2015 at 10:39 AM, Herbert Xu
<herb...@gondor.apana.org.au> wrote:
> On Thu, Dec 17, 2015 at 01:59:11PM +0100, Dmitry Vyukov wrote:
>>
>> The following program causes GPF in lrw_crypt:
>
> OK, this is a result of certain implementations (such as lrw)
> not coping with there being no key gracefully.
>
> I think the easiest way is probably to check this in algif_skcipher.
>
> ---8<---
> Subject: crypto: algif_skcipher - Require setkey before accept(2)
>
> Some cipher implementations will crash if you try to use them
> without calling setkey first.  This patch adds a check so that
> the accept(2) call will fail with -ENOKEY if setkey hasn't been
> done on the socket yet.
>
> Cc: sta...@vger.kernel.org
> Reported-by: Dmitry Vyukov <dvyu...@google.com>
> Signed-off-by: Herbert Xu <herb...@gondor.apana.org.au>
>
> diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
> index 5c756b3..b62c973 100644
> --- a/crypto/algif_skcipher.c
> +++ b/crypto/algif_skcipher.c
> @@ -31,6 +31,11 @@ struct skcipher_sg_list {
> struct scatterlist sg[0];
>  };
>
> +struct skcipher_tfm {
> +   struct crypto_skcipher *skcipher;
> +   bool has_key;
> +};
> +
>  struct skcipher_ctx {
> struct list_head tsgl;
> struct af_alg_sgl rsgl;
> @@ -750,17 +755,38 @@ static struct proto_ops algif_skcipher_ops = {
>
>  static void *skcipher_bind(const char *name, u32 type, u32 mask)
>  {
> -   return crypto_alloc_skcipher(name, type, mask);
> +   struct skcipher_tfm *tfm;
> +
> +   tfm = kzalloc(sizeof(*tfm), GFP_KERNEL);
> +   if (!tfm)
> +   return ERR_PTR(-ENOMEM);
> +
> +   tfm->skcipher = crypto_alloc_skcipher(name, type, mask);
> +   if (IS_ERR(tfm->skcipher)) {
> +   kfree(tfm);
> +   return ERR_CAST(tfm->skcipher);
> +   }
> +
> +   return tfm;
>  }
>
>  static void skcipher_release(void *private)
>  {
> -   crypto_free_skcipher(private);
> +   struct skcipher_tfm *tfm = private;
> +
> +   crypto_free_skcipher(tfm->skcipher);
> +   kfree(tfm);
>  }
>
>  static int skcipher_setkey(void *private, const u8 *key, unsigned int keylen)
>  {
> -   return crypto_skcipher_setkey(private, key, keylen);
> +   struct skcipher_tfm *tfm = private;
> +   int err;
> +
> +   err = crypto_skcipher_setkey(tfm->skcipher, key, keylen);
> +   tfm->has_key = !err;
> +
> +   return err;
>  }
>
>  static void skcipher_wait(struct sock *sk)
> @@ -792,20 +818,25 @@ static int skcipher_accept_parent(void *private, struct 
> sock *sk)
>  {
> struct skcipher_ctx *ctx;
> struct alg_sock *ask = alg_sk(sk);
> -   unsigned int len = sizeof(*ctx) + crypto_skcipher_reqsize(private);
> +   struct skcipher_tfm *tfm = private;
> +   struct crypto_skcipher *skcipher = tfm->skcipher;
> +   unsigned int len = sizeof(*ctx) + crypto_skcipher_reqsize(skcipher);
> +
> +   if (!tfm->has_key)
> +   return -ENOKEY;
>
> ctx = sock_kmalloc(sk, len, GFP_KERNEL);
> if (!ctx)
> return -ENOMEM;
>
> -   ctx->iv = sock_kmalloc(sk, crypto_skcipher_ivsize(private),
> +   ctx->iv = sock_kmalloc(sk, crypto_skcipher_ivsize(skcipher),
>GFP_KERNEL);
> if (!ctx->iv) {
> sock_kfree_s(sk, ctx, len);
> return -ENOMEM;
> }
>
> -   memset(ctx->iv, 0, crypto_skcipher_ivsize(private));
> +   memset(ctx->iv, 0, crypto_skcipher_ivsize(skcipher));
>
> INIT_LIST_HEAD(>tsgl);
> ctx->len = len;
> @@ -818,7 +849,7 @@ static int skcipher_accept_parent(void *private, struct 
> sock *sk)
>
> ask->private = ctx;
>
> -   skcipher_request_set_tfm(>req, private);
> +   skcipher_request_set_tfm(>req, skcipher);
> skcipher_request_set_callback(>req, CRYPTO_TFM_REQ_MAY_BACKLOG,
>   af_alg_complete, >completion);
>


Hi Herbert,

I am testing with your two patches:
crypto: algif_skcipher - Use new skcipher interface
crypto: algif_skcipher - Require setkey before accept(2)
on top of a88164345b81292b55a8d4829fdd35c8d611cd7d (Dec 23).

Now the following program causes a bunch of use-after-frees and them
kills kernel:

// autogenerated by syzkaller (http://github.com/google/syzkaller)
#include 
#include 
#include 
#include 
#include 

long r[10];

int main()
{
memset(r, -1, sizeof(r));
r[0] = syscall(SYS_mmap, 0x2000ul, 0xca7000ul, 0x3ul,
0x32ul, 0xu

Re: GPF in lrw_crypt

2015-12-21 Thread Stephan Mueller
Am Donnerstag, 17. Dezember 2015, 13:59:11 schrieb Dmitry Vyukov:

Hi Dmitry,

> Hello,
> 
> The following program causes GPF in lrw_crypt:

Here we are: this problem looks very much like the error reprt about a GFP in 
gf128mul_64_bbe.
> 
> // autogenerated by syzkaller (http://github.com/google/syzkaller)
> #include 
> #include 
> #include 
> 
> int main()
> {
> long r0 = syscall(SYS_socket, 0x26ul, 0x5ul, 0x0ul, 0, 0, 0);
> long r1 = syscall(SYS_mmap, 0x2000ul, 0x1ul, 0x2ul,
> 0x32ul, 0xul, 0x0ul);
> *(uint16_t*)0x20001000 = 0x26;
> memcpy((void*)0x20001002,
> "\x73\x6b\x63\x69\x70\x68\x65\x72\x00\x00\x00\x00\x00\x00", 14);
> *(uint32_t*)0x20001010 = 0xf;
> *(uint32_t*)0x20001014 = 0x100;
> memcpy((void*)0x20001018,
> "\x6c\x72\x77\x28\x74\x77\x6f\x66\x69\x73\x68\x29\x00\x00\x00\x00\x00\x00\x0
> 0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0
> 0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0
> 0\x00\x00\x00\x00\x00\x00\x00", 64);
> long r7 = syscall(SYS_bind, r0, 0x20001000ul, 0x58ul, 0, 0, 0);
> long r8 = syscall(SYS_accept4, r0, 0x0ul, 0x200023fdul, 0x800ul, 0,
> 0); memcpy((void*)0x20002fd8,
> "\x09\xf1\x98\x36\x3f\x7d\x29\x96\x55\xe6\xa2\x42\x45\x67\x8f\x7c\x27\x44\x5
> 1\x6f\xbe\x4d\x52\x6f\x40\xaf\xe0\xd6\x04\x8d\x86\x36\x08\xc8\x55\xb8\xfe\x6
> e\x89\xef\x15\x2d\x07\x9a\x74\xab\xc7\x47\x26\xb5\x00\x93\x3b\x59\xe2\x1f\x6
> a\x29\x76\x7f\x9d\x3a\x86\x38\xda\x3e\xfb\xbe\x63\x2e\x38\x2f\x5c\x1c\x4d\xb
> 8\x53\xf9\x97\xdb\x4a\xcc\xad\x55\xb3\xb5\xa0\xb4\xad\xfb\x39\xe5\x44\x12\x0
> b\x5f\x03\xbf\xc7\x28\x36\x1a\x7b\x4a\xff\x3e\x71\x17\x44\xf3\x09\xfb\x44\x4
> 1\x55\x1b\x6e\x6c\xcd\x03\x39\x66\xe2\x87\x65\xdd\x66\x7c\x00\x9f\x46\x54\x6
> 6\xf1\xa8\x4b\xd9\x10\xdc\x45\xd0\x57\x5c\x5e\x97\x42\x3a\xc9\x26\x5a\x55\x5
> 7\x65\x5f\x38\x54\xdd\x1e\xd8\x89\xe0\x34\xf0\x9e\x65\xf8\x89\x8e\xe4\x02\xd
> c\xa2\xa8\x45\x9c\xe9\xca\xef\xad\xdc\x74\xb5", 182);
> long r10 = syscall(SYS_write, r8, 0x20002fd8ul, 0xb6ul, 0, 0, 0);
> *(uint64_t*)0x2fb8 = 0x20004fff;
> *(uint64_t*)0x2fc0 = 0x94;
> *(uint64_t*)0x2fc8 = 0x2000;
> *(uint64_t*)0x2fd0 = 0x5d;
> *(uint64_t*)0x2fd8 = 0x2f1b;
> *(uint64_t*)0x2fe0 = 0xe5;
> *(uint64_t*)0x2fe8 = 0x20004b08;
> *(uint64_t*)0x2ff0 = 0xe9;
> *(uint64_t*)0x2ff8 = 0x20002000;
> *(uint64_t*)0x20001000 = 0x1000;
> long r21 = syscall(SYS_readv, r8, 0x2fb8ul, 0x5ul, 0, 0, 0);
> return 0;
> }
> 
> 
> 
>  kasan: CONFIG_KASAN_INLINE enabled
> kasan: GPF could be caused by NULL-ptr deref or user memory
> accessgeneral protection fault:  [#1] SMP KASAN
> Modules linked in:
> CPU: 2 PID: 6912 Comm: a.out Not tainted 4.4.0-rc3+ #151
> Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
> task: 88005ee61680 ti: 88005fef task.ti: 88005fef RIP:
> 0010:[]  [] gf128mul_64k_bbe+0x89/0x3f0
> RSP: 0018:88005fef7590  EFLAGS: 00010246
> RAX: dc00 RBX: 0001 RCX: 
> RDX: ed000bfdee9f RSI: 88005ee61e40 RDI: ed000bfdeeab
> RBP: 88005fef7650 R08: 0001 R09: 
> R10:  R11:  R12: 88005fef7870
> R13:  R14:  R15: 11000bfdeeb8
> FS:  026a3880(0063) GS:88006ce0() knlGS:
> CS:  0010 DS:  ES:  CR0: 8005003b
> CR2: 2fb8 CR3: 5ffa CR4: 06e0
> Stack:
>  88005fef7730 88000fff 11000bfdeeb8 88005fef7870
>  88005fef7710  41b58ab3 87ab3a79
>  82bf9580 82bafa9b 88005ee61680 0001
> Call Trace:
>  [] lrw_crypt+0x29d/0xd20 crypto/lrw.c:248
>  [] lrw_decrypt+0xf2/0x150
> arch/x86/crypto/serpent_avx2_glue.c:270
>  [] async_decrypt+0x1c1/0x2c0 crypto/blkcipher.c:443
>  [< inline >] crypto_ablkcipher_decrypt include/linux/crypto.h:921
>  [< inline >] skcipher_recvmsg_sync crypto/algif_skcipher.c:676
>  [] skcipher_recvmsg+0x1029/0x1f10
> crypto/algif_skcipher.c:706 [< inline >] sock_recvmsg_nosec
> net/socket.c:712
>  [] sock_recvmsg+0xaa/0xe0 net/socket.c:720
>  [] sock_read_iter+0x273/0x3d0 net/socket.c:797
>  [] do_iter_readv_writev+0x14e/0x2c0 fs/read_write.c:664
>  [] do_readv_writev+0x2e2/0x880 fs/read_write.c:808
>  [] vfs_readv+0x95/0xd0

GPF in lrw_crypt

2015-12-17 Thread Dmitry Vyukov
Hello,

The following program causes GPF in lrw_crypt:

// autogenerated by syzkaller (http://github.com/google/syzkaller)
#include 
#include 
#include 

int main()
{
long r0 = syscall(SYS_socket, 0x26ul, 0x5ul, 0x0ul, 0, 0, 0);
long r1 = syscall(SYS_mmap, 0x2000ul, 0x1ul, 0x2ul,
0x32ul, 0xul, 0x0ul);
*(uint16_t*)0x20001000 = 0x26;
memcpy((void*)0x20001002,
"\x73\x6b\x63\x69\x70\x68\x65\x72\x00\x00\x00\x00\x00\x00", 14);
*(uint32_t*)0x20001010 = 0xf;
*(uint32_t*)0x20001014 = 0x100;
memcpy((void*)0x20001018,
"\x6c\x72\x77\x28\x74\x77\x6f\x66\x69\x73\x68\x29\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
64);
long r7 = syscall(SYS_bind, r0, 0x20001000ul, 0x58ul, 0, 0, 0);
long r8 = syscall(SYS_accept4, r0, 0x0ul, 0x200023fdul, 0x800ul, 0, 0);
memcpy((void*)0x20002fd8,
"\x09\xf1\x98\x36\x3f\x7d\x29\x96\x55\xe6\xa2\x42\x45\x67\x8f\x7c\x27\x44\x51\x6f\xbe\x4d\x52\x6f\x40\xaf\xe0\xd6\x04\x8d\x86\x36\x08\xc8\x55\xb8\xfe\x6e\x89\xef\x15\x2d\x07\x9a\x74\xab\xc7\x47\x26\xb5\x00\x93\x3b\x59\xe2\x1f\x6a\x29\x76\x7f\x9d\x3a\x86\x38\xda\x3e\xfb\xbe\x63\x2e\x38\x2f\x5c\x1c\x4d\xb8\x53\xf9\x97\xdb\x4a\xcc\xad\x55\xb3\xb5\xa0\xb4\xad\xfb\x39\xe5\x44\x12\x0b\x5f\x03\xbf\xc7\x28\x36\x1a\x7b\x4a\xff\x3e\x71\x17\x44\xf3\x09\xfb\x44\x41\x55\x1b\x6e\x6c\xcd\x03\x39\x66\xe2\x87\x65\xdd\x66\x7c\x00\x9f\x46\x54\x66\xf1\xa8\x4b\xd9\x10\xdc\x45\xd0\x57\x5c\x5e\x97\x42\x3a\xc9\x26\x5a\x55\x57\x65\x5f\x38\x54\xdd\x1e\xd8\x89\xe0\x34\xf0\x9e\x65\xf8\x89\x8e\xe4\x02\xdc\xa2\xa8\x45\x9c\xe9\xca\xef\xad\xdc\x74\xb5",
182);
long r10 = syscall(SYS_write, r8, 0x20002fd8ul, 0xb6ul, 0, 0, 0);
*(uint64_t*)0x2fb8 = 0x20004fff;
*(uint64_t*)0x2fc0 = 0x94;
*(uint64_t*)0x2fc8 = 0x2000;
*(uint64_t*)0x2fd0 = 0x5d;
*(uint64_t*)0x2fd8 = 0x2f1b;
*(uint64_t*)0x2fe0 = 0xe5;
*(uint64_t*)0x2fe8 = 0x20004b08;
*(uint64_t*)0x2ff0 = 0xe9;
*(uint64_t*)0x2ff8 = 0x20002000;
*(uint64_t*)0x20001000 = 0x1000;
long r21 = syscall(SYS_readv, r8, 0x2fb8ul, 0x5ul, 0, 0, 0);
return 0;
}



kasan: CONFIG_KASAN_INLINE enabled
kasan: GPF could be caused by NULL-ptr deref or user memory
accessgeneral protection fault:  [#1] SMP KASAN
Modules linked in:
CPU: 2 PID: 6912 Comm: a.out Not tainted 4.4.0-rc3+ #151
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
task: 88005ee61680 ti: 88005fef task.ti: 88005fef
RIP: 0010:[]  [] gf128mul_64k_bbe+0x89/0x3f0
RSP: 0018:88005fef7590  EFLAGS: 00010246
RAX: dc00 RBX: 0001 RCX: 
RDX: ed000bfdee9f RSI: 88005ee61e40 RDI: ed000bfdeeab
RBP: 88005fef7650 R08: 0001 R09: 
R10:  R11:  R12: 88005fef7870
R13:  R14:  R15: 11000bfdeeb8
FS:  026a3880(0063) GS:88006ce0() knlGS:
CS:  0010 DS:  ES:  CR0: 8005003b
CR2: 2fb8 CR3: 5ffa CR4: 06e0
Stack:
 88005fef7730 88000fff 11000bfdeeb8 88005fef7870
 88005fef7710  41b58ab3 87ab3a79
 82bf9580 82bafa9b 88005ee61680 0001
Call Trace:
 [] lrw_crypt+0x29d/0xd20 crypto/lrw.c:248
 [] lrw_decrypt+0xf2/0x150
arch/x86/crypto/serpent_avx2_glue.c:270
 [] async_decrypt+0x1c1/0x2c0 crypto/blkcipher.c:443
 [< inline >] crypto_ablkcipher_decrypt include/linux/crypto.h:921
 [< inline >] skcipher_recvmsg_sync crypto/algif_skcipher.c:676
 [] skcipher_recvmsg+0x1029/0x1f10 crypto/algif_skcipher.c:706
 [< inline >] sock_recvmsg_nosec net/socket.c:712
 [] sock_recvmsg+0xaa/0xe0 net/socket.c:720
 [] sock_read_iter+0x273/0x3d0 net/socket.c:797
 [] do_iter_readv_writev+0x14e/0x2c0 fs/read_write.c:664
 [] do_readv_writev+0x2e2/0x880 fs/read_write.c:808
 [] vfs_readv+0x95/0xd0 fs/read_write.c:834
 [< inline >] SYSC_readv fs/read_write.c:860
 [] SyS_readv+0x111/0x2f0 fs/read_write.c:852
 [] entry_SYSCALL_64_fastpath+0x16/0x7a
arch/x86/entry/entry_64.S:185
Code: 04 00 00 f4 f4 c7 40 08 f3 f3 f3 f3 e8 d1 e9 a0 fe 4d 85 f6 0f
84 f6 01 00 00 4c 89 f1 48 b8 00 00 00 00 00 fc ff df 48 c1 e9 03 <80>
3c 01 00 0f 85 48 03 00 00 48 8b 5c 24 18 4d 8b 26 48 83 c3
RIP  [] gf128mul_64k_bbe+0x89/0x3f0 crypto/gf128mul.c:379
 RSP 
---[ end trace 018c54843b88ec1d ]---


On upstream commit 31ade3b83e1821da5fbb2f11b5b3d4ab2ec39db8 (Nov 29).
--
To unsubscribe from this list: send the line &