@@ -39,6 +39,37 @@ struct algif_hash_tfm {
39
39
bool has_key ;
40
40
};
41
41
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
+
42
73
static int hash_sendmsg (struct socket * sock , struct msghdr * msg ,
43
74
size_t ignored )
44
75
{
@@ -54,6 +85,9 @@ static int hash_sendmsg(struct socket *sock, struct msghdr *msg,
54
85
55
86
lock_sock (sk );
56
87
if (!ctx -> more ) {
88
+ if ((msg -> msg_flags & MSG_MORE ))
89
+ hash_free_result (sk , ctx );
90
+
57
91
err = af_alg_wait_for_completion (crypto_ahash_init (& ctx -> req ),
58
92
& ctx -> completion );
59
93
if (err )
@@ -90,6 +124,10 @@ static int hash_sendmsg(struct socket *sock, struct msghdr *msg,
90
124
91
125
ctx -> more = msg -> msg_flags & MSG_MORE ;
92
126
if (!ctx -> more ) {
127
+ err = hash_alloc_result (sk , ctx );
128
+ if (err )
129
+ goto unlock ;
130
+
93
131
ahash_request_set_crypt (& ctx -> req , NULL , ctx -> result , 0 );
94
132
err = af_alg_wait_for_completion (crypto_ahash_final (& ctx -> req ),
95
133
& ctx -> completion );
@@ -116,6 +154,13 @@ static ssize_t hash_sendpage(struct socket *sock, struct page *page,
116
154
sg_init_table (ctx -> sgl .sg , 1 );
117
155
sg_set_page (ctx -> sgl .sg , page , size , offset );
118
156
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
+
119
164
ahash_request_set_crypt (& ctx -> req , ctx -> sgl .sg , ctx -> result , size );
120
165
121
166
if (!(flags & MSG_MORE )) {
@@ -153,6 +198,7 @@ static int hash_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
153
198
struct alg_sock * ask = alg_sk (sk );
154
199
struct hash_ctx * ctx = ask -> private ;
155
200
unsigned ds = crypto_ahash_digestsize (crypto_ahash_reqtfm (& ctx -> req ));
201
+ bool result ;
156
202
int err ;
157
203
158
204
if (len > ds )
@@ -161,17 +207,29 @@ static int hash_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
161
207
msg -> msg_flags |= MSG_TRUNC ;
162
208
163
209
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
+
164
217
if (ctx -> more ) {
165
218
ctx -> more = 0 ;
166
- ahash_request_set_crypt (& ctx -> req , NULL , ctx -> result , 0 );
167
219
err = af_alg_wait_for_completion (crypto_ahash_final (& ctx -> req ),
168
220
& ctx -> completion );
169
221
if (err )
170
222
goto unlock ;
223
+ } else if (!result ) {
224
+ err = af_alg_wait_for_completion (
225
+ crypto_ahash_digest (& ctx -> req ),
226
+ & ctx -> completion );
171
227
}
172
228
173
229
err = memcpy_to_msg (msg , ctx -> result , len );
174
230
231
+ hash_free_result (sk , ctx );
232
+
175
233
unlock :
176
234
release_sock (sk );
177
235
@@ -394,8 +452,7 @@ static void hash_sock_destruct(struct sock *sk)
394
452
struct alg_sock * ask = alg_sk (sk );
395
453
struct hash_ctx * ctx = ask -> private ;
396
454
397
- sock_kzfree_s (sk , ctx -> result ,
398
- crypto_ahash_digestsize (crypto_ahash_reqtfm (& ctx -> req )));
455
+ hash_free_result (sk , ctx );
399
456
sock_kfree_s (sk , ctx , ctx -> len );
400
457
af_alg_release_parent (sk );
401
458
}
@@ -407,20 +464,12 @@ static int hash_accept_parent_nokey(void *private, struct sock *sk)
407
464
struct algif_hash_tfm * tfm = private ;
408
465
struct crypto_ahash * hash = tfm -> hash ;
409
466
unsigned len = sizeof (* ctx ) + crypto_ahash_reqsize (hash );
410
- unsigned ds = crypto_ahash_digestsize (hash );
411
467
412
468
ctx = sock_kmalloc (sk , len , GFP_KERNEL );
413
469
if (!ctx )
414
470
return - ENOMEM ;
415
471
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 ;
424
473
ctx -> len = len ;
425
474
ctx -> more = 0 ;
426
475
af_alg_init_completion (& ctx -> completion );
0 commit comments