crypto: af_alg - Add nokey compatibility path
authorHerbert Xu <herbert@gondor.apana.org.au>
Mon, 4 Jan 2016 04:35:18 +0000 (13:35 +0900)
committerHerbert Xu <herbert@gondor.apana.org.au>
Mon, 18 Jan 2016 10:16:10 +0000 (18:16 +0800)
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>
crypto/af_alg.c
include/crypto/if_alg.h

index eaf98e287d89ed8843b3141ef8c84bd11b3ee7a5..6566d2eb0142ef13dfcdb34772cdbb8f3d5c1647 100644 (file)
@@ -76,6 +76,8 @@ int af_alg_register_type(const struct af_alg_type *type)
                goto unlock;
 
        type->ops->owner = THIS_MODULE;
+       if (type->ops_nokey)
+               type->ops_nokey->owner = THIS_MODULE;
        node->type = type;
        list_add(&node->list, &alg_types);
        err = 0;
@@ -267,6 +269,7 @@ int af_alg_accept(struct sock *sk, struct socket *newsock)
        const struct af_alg_type *type;
        struct sock *sk2;
        int err;
+       bool nokey;
 
        lock_sock(sk);
        type = ask->type;
@@ -285,12 +288,17 @@ int af_alg_accept(struct sock *sk, struct socket *newsock)
        security_sk_clone(sk, sk2);
 
        err = type->accept(ask->private, sk2);
+
+       nokey = err == -ENOKEY;
+       if (nokey && type->accept_nokey)
+               err = type->accept_nokey(ask->private, sk2);
+
        if (err)
                goto unlock;
 
        sk2->sk_family = PF_ALG;
 
-       if (!ask->refcnt++)
+       if (nokey || !ask->refcnt++)
                sock_hold(sk);
        alg_sk(sk2)->parent = sk;
        alg_sk(sk2)->type = type;
@@ -298,6 +306,9 @@ int af_alg_accept(struct sock *sk, struct socket *newsock)
        newsock->ops = type->ops;
        newsock->state = SS_CONNECTED;
 
+       if (nokey)
+               newsock->ops = type->ops_nokey;
+
        err = 0;
 
 unlock:
index 589716f2ee8a47c4ef0488020719080a82e97042..df8284415c565da141d4b6a7476c92bc4f297b2b 100644 (file)
@@ -52,9 +52,11 @@ struct af_alg_type {
        void (*release)(void *private);
        int (*setkey)(void *private, const u8 *key, unsigned int keylen);
        int (*accept)(void *private, struct sock *sk);
+       int (*accept_nokey)(void *private, struct sock *sk);
        int (*setauthsize)(void *private, unsigned int authsize);
 
        struct proto_ops *ops;
+       struct proto_ops *ops_nokey;
        struct module *owner;
        char name[14];
 };