lkml.org 
[lkml]   [2017]   [Feb]   [5]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 3.10 006/319] crypto: algif_skcipher - Add nokey compatibility path
    Date
    From: Herbert Xu <herbert@gondor.apana.org.au>

    commit a0fa2d037129a9849918a92d91b79ed6c7bd2818 upstream.

    This patch adds a compatibility path to support old applications
    that do acept(2) before setkey.

    Cc: stable@vger.kernel.org
    Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
    Signed-off-by: Andrey Ryabinin <aryabinin@virtuozzo.com>
    Signed-off-by: Willy Tarreau <w@1wt.eu>
    ---
    crypto/algif_skcipher.c | 149 ++++++++++++++++++++++++++++++++++++++++++++++--
    1 file changed, 144 insertions(+), 5 deletions(-)

    diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
    index c4c121a..db5f0f0 100644
    --- a/crypto/algif_skcipher.c
    +++ b/crypto/algif_skcipher.c
    @@ -549,6 +549,99 @@ static struct proto_ops algif_skcipher_ops = {
    .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 kiocb *unused, struct socket *sock,
    + struct msghdr *msg, size_t size)
    +{
    + int err;
    +
    + err = skcipher_check_key(sock);
    + if (err)
    + return err;
    +
    + return skcipher_sendmsg(unused, 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 kiocb *unused, 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(unused, 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)
    {
    struct skcipher_tfm *tfm;
    @@ -588,7 +681,7 @@ static int skcipher_setkey(void *private, const u8 *key, unsigned int keylen)
    return err;
    }

    -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;
    @@ -597,10 +690,33 @@ static void skcipher_sock_destruct(struct sock *sk)
    skcipher_free_sgl(sk);
    sock_kfree_s(sk, ctx->iv, crypto_ablkcipher_ivsize(tfm));
    sock_kfree_s(sk, ctx, ctx->len);
    +}
    +
    +static void skcipher_sock_destruct(struct sock *sk)
    +{
    + skcipher_sock_destruct_common(sk);
    af_alg_release_parent(sk);
    }

    -static int skcipher_accept_parent(void *private, struct sock *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);
    @@ -608,9 +724,6 @@ static int skcipher_accept_parent(void *private, struct sock *sk)
    struct crypto_ablkcipher *skcipher = tfm->skcipher;
    unsigned int len = sizeof(*ctx) + crypto_ablkcipher_reqsize(skcipher);

    - if (!tfm->has_key)
    - return -ENOKEY;
    -
    ctx = sock_kmalloc(sk, len, GFP_KERNEL);
    if (!ctx)
    return -ENOMEM;
    @@ -642,12 +755,38 @@ static int skcipher_accept_parent(void *private, struct sock *sk)
    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
    };
    --
    2.8.0.rc2.1.gbe9624a
    \
     
     \ /
      Last update: 2017-02-05 20:17    [W:4.554 / U:0.672 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site