Re: GPF in lrw_crypt
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
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
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
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 &