Skip to content

Commit 493b2ed

Browse files
committed
crypto: algif_hash - Handle NULL hashes correctly
Right now attempting to read an empty hash simply returns zeroed bytes, this patch corrects this by calling the digest function using an empty input. Reported-by: Russell King - ARM Linux <linux@armlinux.org.uk> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
1 parent 5ba1c7b commit 493b2ed

File tree

1 file changed

+61
-12
lines changed

1 file changed

+61
-12
lines changed

crypto/algif_hash.c

Lines changed: 61 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,37 @@ struct algif_hash_tfm {
3939
bool has_key;
4040
};
4141

42+
static int hash_alloc_result(struct sock *sk, struct hash_ctx *ctx)
43+
{
44+
unsigned ds;
45+
46+
if (ctx->result)
47+
return 0;
48+
49+
ds = crypto_ahash_digestsize(crypto_ahash_reqtfm(&ctx->req));
50+
51+
ctx->result = sock_kmalloc(sk, ds, GFP_KERNEL);
52+
if (!ctx->result)
53+
return -ENOMEM;
54+
55+
memset(ctx->result, 0, ds);
56+
57+
return 0;
58+
}
59+
60+
static void hash_free_result(struct sock *sk, struct hash_ctx *ctx)
61+
{
62+
unsigned ds;
63+
64+
if (!ctx->result)
65+
return;
66+
67+
ds = crypto_ahash_digestsize(crypto_ahash_reqtfm(&ctx->req));
68+
69+
sock_kzfree_s(sk, ctx->result, ds);
70+
ctx->result = NULL;
71+
}
72+
4273
static int hash_sendmsg(struct socket *sock, struct msghdr *msg,
4374
size_t ignored)
4475
{
@@ -54,6 +85,9 @@ static int hash_sendmsg(struct socket *sock, struct msghdr *msg,
5485

5586
lock_sock(sk);
5687
if (!ctx->more) {
88+
if ((msg->msg_flags & MSG_MORE))
89+
hash_free_result(sk, ctx);
90+
5791
err = af_alg_wait_for_completion(crypto_ahash_init(&ctx->req),
5892
&ctx->completion);
5993
if (err)
@@ -90,6 +124,10 @@ static int hash_sendmsg(struct socket *sock, struct msghdr *msg,
90124

91125
ctx->more = msg->msg_flags & MSG_MORE;
92126
if (!ctx->more) {
127+
err = hash_alloc_result(sk, ctx);
128+
if (err)
129+
goto unlock;
130+
93131
ahash_request_set_crypt(&ctx->req, NULL, ctx->result, 0);
94132
err = af_alg_wait_for_completion(crypto_ahash_final(&ctx->req),
95133
&ctx->completion);
@@ -116,6 +154,13 @@ static ssize_t hash_sendpage(struct socket *sock, struct page *page,
116154
sg_init_table(ctx->sgl.sg, 1);
117155
sg_set_page(ctx->sgl.sg, page, size, offset);
118156

157+
if (!(flags & MSG_MORE)) {
158+
err = hash_alloc_result(sk, ctx);
159+
if (err)
160+
goto unlock;
161+
} else if (!ctx->more)
162+
hash_free_result(sk, ctx);
163+
119164
ahash_request_set_crypt(&ctx->req, ctx->sgl.sg, ctx->result, size);
120165

121166
if (!(flags & MSG_MORE)) {
@@ -153,6 +198,7 @@ static int hash_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
153198
struct alg_sock *ask = alg_sk(sk);
154199
struct hash_ctx *ctx = ask->private;
155200
unsigned ds = crypto_ahash_digestsize(crypto_ahash_reqtfm(&ctx->req));
201+
bool result;
156202
int err;
157203

158204
if (len > ds)
@@ -161,17 +207,29 @@ static int hash_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
161207
msg->msg_flags |= MSG_TRUNC;
162208

163209
lock_sock(sk);
210+
result = ctx->result;
211+
err = hash_alloc_result(sk, ctx);
212+
if (err)
213+
goto unlock;
214+
215+
ahash_request_set_crypt(&ctx->req, NULL, ctx->result, 0);
216+
164217
if (ctx->more) {
165218
ctx->more = 0;
166-
ahash_request_set_crypt(&ctx->req, NULL, ctx->result, 0);
167219
err = af_alg_wait_for_completion(crypto_ahash_final(&ctx->req),
168220
&ctx->completion);
169221
if (err)
170222
goto unlock;
223+
} else if (!result) {
224+
err = af_alg_wait_for_completion(
225+
crypto_ahash_digest(&ctx->req),
226+
&ctx->completion);
171227
}
172228

173229
err = memcpy_to_msg(msg, ctx->result, len);
174230

231+
hash_free_result(sk, ctx);
232+
175233
unlock:
176234
release_sock(sk);
177235

@@ -394,8 +452,7 @@ static void hash_sock_destruct(struct sock *sk)
394452
struct alg_sock *ask = alg_sk(sk);
395453
struct hash_ctx *ctx = ask->private;
396454

397-
sock_kzfree_s(sk, ctx->result,
398-
crypto_ahash_digestsize(crypto_ahash_reqtfm(&ctx->req)));
455+
hash_free_result(sk, ctx);
399456
sock_kfree_s(sk, ctx, ctx->len);
400457
af_alg_release_parent(sk);
401458
}
@@ -407,20 +464,12 @@ static int hash_accept_parent_nokey(void *private, struct sock *sk)
407464
struct algif_hash_tfm *tfm = private;
408465
struct crypto_ahash *hash = tfm->hash;
409466
unsigned len = sizeof(*ctx) + crypto_ahash_reqsize(hash);
410-
unsigned ds = crypto_ahash_digestsize(hash);
411467

412468
ctx = sock_kmalloc(sk, len, GFP_KERNEL);
413469
if (!ctx)
414470
return -ENOMEM;
415471

416-
ctx->result = sock_kmalloc(sk, ds, GFP_KERNEL);
417-
if (!ctx->result) {
418-
sock_kfree_s(sk, ctx, len);
419-
return -ENOMEM;
420-
}
421-
422-
memset(ctx->result, 0, ds);
423-
472+
ctx->result = NULL;
424473
ctx->len = len;
425474
ctx->more = 0;
426475
af_alg_init_completion(&ctx->completion);

0 commit comments

Comments
 (0)