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)
committerBen Hutchings <ben@decadent.org.uk>
Sat, 13 Feb 2016 10:34:12 +0000 (10:34 +0000)
commit 37766586c965d63758ad542325a96d5384f4a8c9 upstream.

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

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
[bwh: Backported to 3.2: adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
crypto/af_alg.c
include/crypto/if_alg.h

index 0ca108f..de130c2 100644 (file)
@@ -76,6 +76,8 @@ int af_alg_register_type(const struct af_alg_type *type)
                goto unlock;
 
        type->ops->owner = THIS_MODULE;
                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;
        node->type = type;
        list_add(&node->list, &alg_types);
        err = 0;
@@ -257,6 +259,7 @@ int af_alg_accept(struct sock *sk, struct socket *newsock)
        const struct af_alg_type *type;
        struct sock *sk2;
        int err;
        const struct af_alg_type *type;
        struct sock *sk2;
        int err;
+       bool nokey;
 
        lock_sock(sk);
        type = ask->type;
 
        lock_sock(sk);
        type = ask->type;
@@ -275,12 +278,17 @@ int af_alg_accept(struct sock *sk, struct socket *newsock)
        security_sk_clone(sk, sk2);
 
        err = type->accept(ask->private, sk2);
        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 (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;
                sock_hold(sk);
        alg_sk(sk2)->parent = sk;
        alg_sk(sk2)->type = type;
@@ -288,6 +296,9 @@ int af_alg_accept(struct sock *sk, struct socket *newsock)
        newsock->ops = type->ops;
        newsock->state = SS_CONNECTED;
 
        newsock->ops = type->ops;
        newsock->state = SS_CONNECTED;
 
+       if (nokey)
+               newsock->ops = type->ops_nokey;
+
        err = 0;
 
 unlock:
        err = 0;
 
 unlock:
index 2f38daa..9e6a2f3 100644 (file)
@@ -51,8 +51,10 @@ 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);
        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);
 
        struct proto_ops *ops;
 
        struct proto_ops *ops;
+       struct proto_ops *ops_nokey;
        struct module *owner;
        char name[14];
 };
        struct module *owner;
        char name[14];
 };