@@ -63,78 +63,102 @@ static void hash_free_result(struct sock *sk, struct hash_ctx *ctx)
63
63
static int hash_sendmsg (struct socket * sock , struct msghdr * msg ,
64
64
size_t ignored )
65
65
{
66
- int limit = ALG_MAX_PAGES * PAGE_SIZE ;
67
66
struct sock * sk = sock -> sk ;
68
67
struct alg_sock * ask = alg_sk (sk );
69
68
struct hash_ctx * ctx = ask -> private ;
70
- long copied = 0 ;
69
+ ssize_t copied = 0 ;
70
+ size_t len , max_pages , npages ;
71
+ bool continuing = ctx -> more , need_init = false;
71
72
int err ;
72
73
73
- if ( limit > sk -> sk_sndbuf )
74
- limit = sk -> sk_sndbuf ;
74
+ max_pages = min_t ( size_t , ALG_MAX_PAGES ,
75
+ DIV_ROUND_UP ( sk -> sk_sndbuf , PAGE_SIZE )) ;
75
76
76
77
lock_sock (sk );
77
- if (!ctx -> more ) {
78
+ if (!continuing ) {
78
79
if ((msg -> msg_flags & MSG_MORE ))
79
80
hash_free_result (sk , ctx );
80
-
81
- err = crypto_wait_req (crypto_ahash_init (& ctx -> req ), & ctx -> wait );
82
- if (err )
83
- goto unlock ;
81
+ need_init = true;
84
82
}
85
83
86
84
ctx -> more = false;
87
85
88
86
while (msg_data_left (msg )) {
89
- int len = msg_data_left (msg );
90
-
91
- if (len > limit )
92
- len = limit ;
93
-
94
87
ctx -> sgl .sgt .sgl = ctx -> sgl .sgl ;
95
88
ctx -> sgl .sgt .nents = 0 ;
96
89
ctx -> sgl .sgt .orig_nents = 0 ;
97
90
98
- len = extract_iter_to_sg (& msg -> msg_iter , len , & ctx -> sgl .sgt ,
99
- ALG_MAX_PAGES , 0 );
100
- if (len < 0 ) {
101
- err = copied ? 0 : len ;
102
- goto unlock ;
91
+ err = - EIO ;
92
+ npages = iov_iter_npages (& msg -> msg_iter , max_pages );
93
+ if (npages == 0 )
94
+ goto unlock_free ;
95
+
96
+ if (npages > ARRAY_SIZE (ctx -> sgl .sgl )) {
97
+ err = - ENOMEM ;
98
+ ctx -> sgl .sgt .sgl =
99
+ kvmalloc (array_size (npages ,
100
+ sizeof (* ctx -> sgl .sgt .sgl )),
101
+ GFP_KERNEL );
102
+ if (!ctx -> sgl .sgt .sgl )
103
+ goto unlock_free ;
103
104
}
104
- sg_mark_end (ctx -> sgl .sgt . sgl + ctx -> sgl . sgt . nents );
105
+ sg_init_table (ctx -> sgl .sgl , npages );
105
106
106
107
ctx -> sgl .need_unpin = iov_iter_extract_will_pin (& msg -> msg_iter );
107
108
108
- ahash_request_set_crypt (& ctx -> req , ctx -> sgl .sgt .sgl , NULL , len );
109
+ err = extract_iter_to_sg (& msg -> msg_iter , LONG_MAX ,
110
+ & ctx -> sgl .sgt , npages , 0 );
111
+ if (err < 0 )
112
+ goto unlock_free ;
113
+ len = err ;
114
+ sg_mark_end (ctx -> sgl .sgt .sgl + ctx -> sgl .sgt .nents - 1 );
109
115
110
- err = crypto_wait_req (crypto_ahash_update (& ctx -> req ),
111
- & ctx -> wait );
112
- af_alg_free_sg (& ctx -> sgl );
113
- if (err ) {
114
- iov_iter_revert (& msg -> msg_iter , len );
115
- goto unlock ;
116
+ if (!msg_data_left (msg )) {
117
+ err = hash_alloc_result (sk , ctx );
118
+ if (err )
119
+ goto unlock_free ;
116
120
}
117
121
118
- copied += len ;
119
- }
122
+ ahash_request_set_crypt ( & ctx -> req , ctx -> sgl . sgt . sgl ,
123
+ ctx -> result , len );
120
124
121
- err = 0 ;
125
+ if (!msg_data_left (msg ) && !continuing &&
126
+ !(msg -> msg_flags & MSG_MORE )) {
127
+ err = crypto_ahash_digest (& ctx -> req );
128
+ } else {
129
+ if (need_init ) {
130
+ err = crypto_wait_req (
131
+ crypto_ahash_init (& ctx -> req ),
132
+ & ctx -> wait );
133
+ if (err )
134
+ goto unlock_free ;
135
+ need_init = false;
136
+ }
137
+
138
+ if (msg_data_left (msg ) || (msg -> msg_flags & MSG_MORE ))
139
+ err = crypto_ahash_update (& ctx -> req );
140
+ else
141
+ err = crypto_ahash_finup (& ctx -> req );
142
+ continuing = true;
143
+ }
122
144
123
- ctx -> more = msg -> msg_flags & MSG_MORE ;
124
- if (!ctx -> more ) {
125
- err = hash_alloc_result (sk , ctx );
145
+ err = crypto_wait_req (err , & ctx -> wait );
126
146
if (err )
127
- goto unlock ;
147
+ goto unlock_free ;
128
148
129
- ahash_request_set_crypt (& ctx -> req , NULL , ctx -> result , 0 );
130
- err = crypto_wait_req (crypto_ahash_final (& ctx -> req ),
131
- & ctx -> wait );
149
+ copied += len ;
150
+ af_alg_free_sg (& ctx -> sgl );
132
151
}
133
152
153
+ ctx -> more = msg -> msg_flags & MSG_MORE ;
154
+ err = 0 ;
134
155
unlock :
135
156
release_sock (sk );
157
+ return copied ?: err ;
136
158
137
- return err ?: copied ;
159
+ unlock_free :
160
+ af_alg_free_sg (& ctx -> sgl );
161
+ goto unlock ;
138
162
}
139
163
140
164
static ssize_t hash_sendpage (struct socket * sock , struct page * page ,
0 commit comments