Skip to content

Commit a0fa2d0

Browse files
committed
crypto: algif_skcipher - Add nokey compatibility path
This patch adds a compatibility path to support old applications that do acept(2) before setkey. Cc: [email protected] Signed-off-by: Herbert Xu <[email protected]>
1 parent 3776658 commit a0fa2d0

File tree

1 file changed

+144
-5
lines changed

1 file changed

+144
-5
lines changed

crypto/algif_skcipher.c

Lines changed: 144 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -753,6 +753,99 @@ static struct proto_ops algif_skcipher_ops = {
753753
.poll = skcipher_poll,
754754
};
755755

756+
static int skcipher_check_key(struct socket *sock)
757+
{
758+
int err;
759+
struct sock *psk;
760+
struct alg_sock *pask;
761+
struct skcipher_tfm *tfm;
762+
struct sock *sk = sock->sk;
763+
struct alg_sock *ask = alg_sk(sk);
764+
765+
if (ask->refcnt)
766+
return 0;
767+
768+
psk = ask->parent;
769+
pask = alg_sk(ask->parent);
770+
tfm = pask->private;
771+
772+
err = -ENOKEY;
773+
lock_sock(psk);
774+
if (!tfm->has_key)
775+
goto unlock;
776+
777+
if (!pask->refcnt++)
778+
sock_hold(psk);
779+
780+
ask->refcnt = 1;
781+
sock_put(psk);
782+
783+
err = 0;
784+
785+
unlock:
786+
release_sock(psk);
787+
788+
return err;
789+
}
790+
791+
static int skcipher_sendmsg_nokey(struct socket *sock, struct msghdr *msg,
792+
size_t size)
793+
{
794+
int err;
795+
796+
err = skcipher_check_key(sock);
797+
if (err)
798+
return err;
799+
800+
return skcipher_sendmsg(sock, msg, size);
801+
}
802+
803+
static ssize_t skcipher_sendpage_nokey(struct socket *sock, struct page *page,
804+
int offset, size_t size, int flags)
805+
{
806+
int err;
807+
808+
err = skcipher_check_key(sock);
809+
if (err)
810+
return err;
811+
812+
return skcipher_sendpage(sock, page, offset, size, flags);
813+
}
814+
815+
static int skcipher_recvmsg_nokey(struct socket *sock, struct msghdr *msg,
816+
size_t ignored, int flags)
817+
{
818+
int err;
819+
820+
err = skcipher_check_key(sock);
821+
if (err)
822+
return err;
823+
824+
return skcipher_recvmsg(sock, msg, ignored, flags);
825+
}
826+
827+
static struct proto_ops algif_skcipher_ops_nokey = {
828+
.family = PF_ALG,
829+
830+
.connect = sock_no_connect,
831+
.socketpair = sock_no_socketpair,
832+
.getname = sock_no_getname,
833+
.ioctl = sock_no_ioctl,
834+
.listen = sock_no_listen,
835+
.shutdown = sock_no_shutdown,
836+
.getsockopt = sock_no_getsockopt,
837+
.mmap = sock_no_mmap,
838+
.bind = sock_no_bind,
839+
.accept = sock_no_accept,
840+
.setsockopt = sock_no_setsockopt,
841+
842+
.release = af_alg_release,
843+
.sendmsg = skcipher_sendmsg_nokey,
844+
.sendpage = skcipher_sendpage_nokey,
845+
.recvmsg = skcipher_recvmsg_nokey,
846+
.poll = skcipher_poll,
847+
};
848+
756849
static void *skcipher_bind(const char *name, u32 type, u32 mask)
757850
{
758851
struct skcipher_tfm *tfm;
@@ -802,7 +895,7 @@ static void skcipher_wait(struct sock *sk)
802895
msleep(100);
803896
}
804897

805-
static void skcipher_sock_destruct(struct sock *sk)
898+
static void skcipher_sock_destruct_common(struct sock *sk)
806899
{
807900
struct alg_sock *ask = alg_sk(sk);
808901
struct skcipher_ctx *ctx = ask->private;
@@ -814,20 +907,40 @@ static void skcipher_sock_destruct(struct sock *sk)
814907
skcipher_free_sgl(sk);
815908
sock_kzfree_s(sk, ctx->iv, crypto_skcipher_ivsize(tfm));
816909
sock_kfree_s(sk, ctx, ctx->len);
910+
}
911+
912+
static void skcipher_sock_destruct(struct sock *sk)
913+
{
914+
skcipher_sock_destruct_common(sk);
817915
af_alg_release_parent(sk);
818916
}
819917

820-
static int skcipher_accept_parent(void *private, struct sock *sk)
918+
static void skcipher_release_parent_nokey(struct sock *sk)
919+
{
920+
struct alg_sock *ask = alg_sk(sk);
921+
922+
if (!ask->refcnt) {
923+
sock_put(ask->parent);
924+
return;
925+
}
926+
927+
af_alg_release_parent(sk);
928+
}
929+
930+
static void skcipher_sock_destruct_nokey(struct sock *sk)
931+
{
932+
skcipher_sock_destruct_common(sk);
933+
skcipher_release_parent_nokey(sk);
934+
}
935+
936+
static int skcipher_accept_parent_common(void *private, struct sock *sk)
821937
{
822938
struct skcipher_ctx *ctx;
823939
struct alg_sock *ask = alg_sk(sk);
824940
struct skcipher_tfm *tfm = private;
825941
struct crypto_skcipher *skcipher = tfm->skcipher;
826942
unsigned int len = sizeof(*ctx) + crypto_skcipher_reqsize(skcipher);
827943

828-
if (!tfm->has_key)
829-
return -ENOKEY;
830-
831944
ctx = sock_kmalloc(sk, len, GFP_KERNEL);
832945
if (!ctx)
833946
return -ENOMEM;
@@ -861,12 +974,38 @@ static int skcipher_accept_parent(void *private, struct sock *sk)
861974
return 0;
862975
}
863976

977+
static int skcipher_accept_parent(void *private, struct sock *sk)
978+
{
979+
struct skcipher_tfm *tfm = private;
980+
981+
if (!tfm->has_key)
982+
return -ENOKEY;
983+
984+
return skcipher_accept_parent_common(private, sk);
985+
}
986+
987+
static int skcipher_accept_parent_nokey(void *private, struct sock *sk)
988+
{
989+
int err;
990+
991+
err = skcipher_accept_parent_common(private, sk);
992+
if (err)
993+
goto out;
994+
995+
sk->sk_destruct = skcipher_sock_destruct_nokey;
996+
997+
out:
998+
return err;
999+
}
1000+
8641001
static const struct af_alg_type algif_type_skcipher = {
8651002
.bind = skcipher_bind,
8661003
.release = skcipher_release,
8671004
.setkey = skcipher_setkey,
8681005
.accept = skcipher_accept_parent,
1006+
.accept_nokey = skcipher_accept_parent_nokey,
8691007
.ops = &algif_skcipher_ops,
1008+
.ops_nokey = &algif_skcipher_ops_nokey,
8701009
.name = "skcipher",
8711010
.owner = THIS_MODULE
8721011
};

0 commit comments

Comments
 (0)