From patchwork Sun Feb 21 16:40:05 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Broz X-Patchwork-Id: 8368561 X-Patchwork-Delegate: herbert@gondor.apana.org.au Return-Path: X-Original-To: patchwork-linux-crypto@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 148679F314 for ; Sun, 21 Feb 2016 17:38:32 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 0D036203DA for ; Sun, 21 Feb 2016 17:38:31 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id CA5EE20382 for ; Sun, 21 Feb 2016 17:38:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752547AbcBURiA (ORCPT ); Sun, 21 Feb 2016 12:38:00 -0500 Received: from mail-wm0-f50.google.com ([74.125.82.50]:38803 "EHLO mail-wm0-f50.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751648AbcBURgn (ORCPT ); Sun, 21 Feb 2016 12:36:43 -0500 Received: by mail-wm0-f50.google.com with SMTP id a4so133605268wme.1; Sun, 21 Feb 2016 09:36:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=subject:to:references:cc:from:message-id:date:user-agent :mime-version:in-reply-to:content-type:content-transfer-encoding; bh=IbiSznGfjsn0lMyKax/gqnbRm8if+Xj/cCfKWI1gEcQ=; b=zgbAXJkH8ECsTmNolf3CVLwNft264W0elO77omCnG2INfwPiiKYEN0q8dsQW9n1iNH 1pPRLUTildO+mq9ORRp7fZsxmpoFlXDM+fptgeMZ1ExG5pOTD9x6qaD561rNptztWeZx cdeBDbvyji6p+9SYCxicSyoLO4l1tKTRoR1UGTSC7RClmaVtwXoT9oFWl7mSuinAxHMU X4OTkcnARv7sSvwZaikOCKr4tEOFyeVxPDUPGendxCuz3sZtaX1cmGV1yTS3tS0T/yvE ghuH2Xno0HKDdXER7+H2VlGS1/7Wyo1JXUQxBBefJeDDdyrMlJxRjZV/zhfHTCEs8zwX rGmA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:subject:to:references:cc:from:message-id:date :user-agent:mime-version:in-reply-to:content-type :content-transfer-encoding; bh=IbiSznGfjsn0lMyKax/gqnbRm8if+Xj/cCfKWI1gEcQ=; b=MoJLN/PyGlpMIMrDuW1K7sX68XtfXWBsWU5TdYOrL6oYyy4Df9CTE1vWXxv/7KSLbi BIsRPv87IvH1n2BhqxuXhLcZSZSCM5vQ0B6wfodxvZ3PUO5xGVRbPuz0P85CXuhtq4ta GijQ7A5H7EmAytomTUTKzlLhPA0n2+DGRocf3UuwAvIGAcOCpgut1E8QYwT7eC2LK+sq aw5jEsswGo+mjqhMv/1+AHx874640TiiplXrkcIN6d8VI4+yP21HoLcpUi77jwdhR7O3 IKyFKYhmF2ZhM75APXQI9mIIrdSA+X38o1wWvW2XDFKjGNasbfRAp4lYMe5VoDmEm81P XDdA== X-Gm-Message-State: AG10YOR12XSIJSZNIaaMJigsr6/kbstaRAkesykM+6AwECZv0O2H9k6mhcNIwY1rBNUY3Q== X-Received: by 10.28.55.76 with SMTP id e73mr8288221wma.53.1456072807401; Sun, 21 Feb 2016 08:40:07 -0800 (PST) Received: from [192.168.2.27] (218.83.broadband9.iol.cz. [90.176.83.218]) by smtp.gmail.com with ESMTPSA id k8sm9352676wjr.38.2016.02.21.08.40.05 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 21 Feb 2016 08:40:06 -0800 (PST) Subject: [PATCH] Re: Broken userspace crypto in linux-4.1.18 To: "Thomas D." , Jiri Slaby , Stephan Mueller References: <56C47DF9.6030704@whissi.de> <20160217233353.GC31125@1wt.eu> <56C50725.6080408@whissi.de> <4580306.arupsYiYbb@positron.chronox.de> <56C591E7.5080808@suse.cz> <56C5A66E.5010905@whissi.de> <56C87929.8040304@whissi.de> Cc: Willy Tarreau , Sasha Levin , "herbert@gondor.apana.org.au" , "dvyukov@google.com" , "stable@vger.kernel.org" , "linux-crypto@vger.kernel.org" , Greg KH , Ondrej Kozina From: Milan Broz Message-ID: <56C9E865.3050500@gmail.com> Date: Sun, 21 Feb 2016 17:40:05 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.3.0 MIME-Version: 1.0 In-Reply-To: <56C87929.8040304@whissi.de> Sender: linux-crypto-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-crypto@vger.kernel.org X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP On 02/20/2016 03:33 PM, Thomas D. wrote: > Hi, > > FYI: v3.10.97, v3.14.61 and 3.18.27 are also affected. > > v4.3.6 works. Looks like the patch set is only compatible with >=linux-4.3. > > v3.12.54 works because it doesn't contain the patch in question. Hi, indeed, because whoever backported this patchset skipped two patches from series (because of skcipher interface file was introduced later). I tried to backport it (on 4.1.18 tree, see patch below) and it fixes the problem for me. Anyway, it is just quick test what is the problem, patch need proper review or backport from someone who knows the code better. I will release stable cryptsetup soon that will work with new kernel even without this patch but I would strongly recommend that stable kernels get these compatibility backports as well to avoid breaking existing userspace. Thanks, Milan - This patch backports missing parts of crypto API compatibility changes: dd504589577d8e8e70f51f997ad487a4cb6c026f crypto: algif_skcipher - Require setkey before accept(2) a0fa2d037129a9849918a92d91b79ed6c7bd2818 crypto: algif_skcipher - Add nokey compatibility path --- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html --- crypto/algif_skcipher.c.orig 2016-02-21 16:44:27.172312990 +0100 +++ crypto/algif_skcipher.c 2016-02-21 17:03:58.555785347 +0100 @@ -31,6 +31,11 @@ struct scatterlist sg[0]; }; +struct skcipher_tfm { + struct crypto_ablkcipher *skcipher; + bool has_key; +}; + struct skcipher_ctx { struct list_head tsgl; struct af_alg_sgl rsgl; @@ -750,19 +755,136 @@ .poll = skcipher_poll, }; +static int skcipher_check_key(struct socket *sock) +{ + int err; + struct sock *psk; + struct alg_sock *pask; + struct skcipher_tfm *tfm; + struct sock *sk = sock->sk; + struct alg_sock *ask = alg_sk(sk); + + if (ask->refcnt) + return 0; + + psk = ask->parent; + pask = alg_sk(ask->parent); + tfm = pask->private; + + err = -ENOKEY; + lock_sock(psk); + if (!tfm->has_key) + goto unlock; + + if (!pask->refcnt++) + sock_hold(psk); + + ask->refcnt = 1; + sock_put(psk); + + err = 0; + +unlock: + release_sock(psk); + + return err; +} + +static int skcipher_sendmsg_nokey(struct socket *sock, struct msghdr *msg, + size_t size) +{ + int err; + + err = skcipher_check_key(sock); + if (err) + return err; + + return skcipher_sendmsg(sock, msg, size); +} + +static ssize_t skcipher_sendpage_nokey(struct socket *sock, struct page *page, + int offset, size_t size, int flags) +{ + int err; + + err = skcipher_check_key(sock); + if (err) + return err; + + return skcipher_sendpage(sock, page, offset, size, flags); +} + +static int skcipher_recvmsg_nokey(struct socket *sock, struct msghdr *msg, + size_t ignored, int flags) +{ + int err; + + err = skcipher_check_key(sock); + if (err) + return err; + + return skcipher_recvmsg(sock, msg, ignored, flags); +} + +static struct proto_ops algif_skcipher_ops_nokey = { + .family = PF_ALG, + + .connect = sock_no_connect, + .socketpair = sock_no_socketpair, + .getname = sock_no_getname, + .ioctl = sock_no_ioctl, + .listen = sock_no_listen, + .shutdown = sock_no_shutdown, + .getsockopt = sock_no_getsockopt, + .mmap = sock_no_mmap, + .bind = sock_no_bind, + .accept = sock_no_accept, + .setsockopt = sock_no_setsockopt, + + .release = af_alg_release, + .sendmsg = skcipher_sendmsg_nokey, + .sendpage = skcipher_sendpage_nokey, + .recvmsg = skcipher_recvmsg_nokey, + .poll = skcipher_poll, +}; + static void *skcipher_bind(const char *name, u32 type, u32 mask) { - return crypto_alloc_ablkcipher(name, type, mask); + struct skcipher_tfm *tfm; + struct crypto_ablkcipher *skcipher; + + tfm = kzalloc(sizeof(*tfm), GFP_KERNEL); + if (!tfm) + return ERR_PTR(-ENOMEM); + + skcipher = crypto_alloc_ablkcipher(name, type, mask); + if (IS_ERR(skcipher)) { + kfree(tfm); + return ERR_CAST(skcipher); + } + + tfm->skcipher = skcipher; + + return tfm; } static void skcipher_release(void *private) { - crypto_free_ablkcipher(private); + struct skcipher_tfm *tfm = private; + + crypto_free_ablkcipher(tfm->skcipher); + kfree(tfm); } static int skcipher_setkey(void *private, const u8 *key, unsigned int keylen) { - return crypto_ablkcipher_setkey(private, key, keylen); + struct skcipher_tfm *tfm = private; + int err; + + err = crypto_ablkcipher_setkey(tfm->skcipher, key, keylen); + tfm->has_key = !err; + + return err; } static void skcipher_wait(struct sock *sk) @@ -775,7 +897,7 @@ msleep(100); } -static void skcipher_sock_destruct(struct sock *sk) +static void skcipher_sock_destruct_common(struct sock *sk) { struct alg_sock *ask = alg_sk(sk); struct skcipher_ctx *ctx = ask->private; @@ -790,24 +912,50 @@ af_alg_release_parent(sk); } -static int skcipher_accept_parent(void *private, struct sock *sk) +static void skcipher_sock_destruct(struct sock *sk) +{ + skcipher_sock_destruct_common(sk); + af_alg_release_parent(sk); +} + +static void skcipher_release_parent_nokey(struct sock *sk) +{ + struct alg_sock *ask = alg_sk(sk); + + if (!ask->refcnt) { + sock_put(ask->parent); + return; + } + + af_alg_release_parent(sk); +} + +static void skcipher_sock_destruct_nokey(struct sock *sk) +{ + skcipher_sock_destruct_common(sk); + skcipher_release_parent_nokey(sk); +} + +static int skcipher_accept_parent_common(void *private, struct sock *sk) { struct skcipher_ctx *ctx; struct alg_sock *ask = alg_sk(sk); - unsigned int len = sizeof(*ctx) + crypto_ablkcipher_reqsize(private); + struct skcipher_tfm *tfm = private; + struct crypto_ablkcipher *skcipher = tfm->skcipher; + unsigned int len = sizeof(*ctx) + crypto_ablkcipher_reqsize(skcipher); ctx = sock_kmalloc(sk, len, GFP_KERNEL); if (!ctx) return -ENOMEM; - ctx->iv = sock_kmalloc(sk, crypto_ablkcipher_ivsize(private), + ctx->iv = sock_kmalloc(sk, crypto_ablkcipher_ivsize(skcipher), GFP_KERNEL); if (!ctx->iv) { sock_kfree_s(sk, ctx, len); return -ENOMEM; } - memset(ctx->iv, 0, crypto_ablkcipher_ivsize(private)); + memset(ctx->iv, 0, crypto_ablkcipher_ivsize(skcipher)); INIT_LIST_HEAD(&ctx->tsgl); ctx->len = len; @@ -820,7 +968,7 @@ ask->private = ctx; - ablkcipher_request_set_tfm(&ctx->req, private); + ablkcipher_request_set_tfm(&ctx->req, skcipher); ablkcipher_request_set_callback(&ctx->req, CRYPTO_TFM_REQ_MAY_BACKLOG, af_alg_complete, &ctx->completion); @@ -829,12 +977,38 @@ return 0; } +static int skcipher_accept_parent(void *private, struct sock *sk) +{ + struct skcipher_tfm *tfm = private; + + if (!tfm->has_key) + return -ENOKEY; + + return skcipher_accept_parent_common(private, sk); +} + +static int skcipher_accept_parent_nokey(void *private, struct sock *sk) +{ + int err; + + err = skcipher_accept_parent_common(private, sk); + if (err) + goto out; + + sk->sk_destruct = skcipher_sock_destruct_nokey; + +out: + return err; +} + static const struct af_alg_type algif_type_skcipher = { .bind = skcipher_bind, .release = skcipher_release, .setkey = skcipher_setkey, .accept = skcipher_accept_parent, + .accept_nokey = skcipher_accept_parent_nokey, .ops = &algif_skcipher_ops, + .ops_nokey = &algif_skcipher_ops_nokey, .name = "skcipher", .owner = THIS_MODULE };