summaryrefslogtreecommitdiffstats
path: root/lib/mpi
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2016-06-29 07:32:22 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2016-07-01 11:45:18 -0400
commit127827b9c295db35fa7e49d00ac5d14faeda9461 (patch)
tree67e4d277b950edc54b1f611ba810c35ad958e253 /lib/mpi
parent9b45b7bba3d22de52e09df63c50f390a193a3f53 (diff)
lib/mpi: Do not do sg_virt
Currently the mpi SG helpers use sg_virt which is completely broken. It happens to work with normal kernel memory but will fail with anything that is not linearly mapped. This patch fixes this by using the SG iterator helpers. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'lib/mpi')
-rw-r--r--lib/mpi/mpicoder.c86
1 files changed, 50 insertions, 36 deletions
diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c
index 7150e5c23604..c6272ae2015e 100644
--- a/lib/mpi/mpicoder.c
+++ b/lib/mpi/mpicoder.c
@@ -21,6 +21,7 @@
21#include <linux/bitops.h> 21#include <linux/bitops.h>
22#include <linux/count_zeros.h> 22#include <linux/count_zeros.h>
23#include <linux/byteorder/generic.h> 23#include <linux/byteorder/generic.h>
24#include <linux/scatterlist.h>
24#include <linux/string.h> 25#include <linux/string.h>
25#include "mpi-internal.h" 26#include "mpi-internal.h"
26 27
@@ -255,7 +256,9 @@ int mpi_write_to_sgl(MPI a, struct scatterlist *sgl, unsigned nbytes,
255#error please implement for this limb size. 256#error please implement for this limb size.
256#endif 257#endif
257 unsigned int n = mpi_get_size(a); 258 unsigned int n = mpi_get_size(a);
259 struct sg_mapping_iter miter;
258 int i, x, buf_len; 260 int i, x, buf_len;
261 int nents;
259 262
260 if (sign) 263 if (sign)
261 *sign = a->sign; 264 *sign = a->sign;
@@ -263,23 +266,27 @@ int mpi_write_to_sgl(MPI a, struct scatterlist *sgl, unsigned nbytes,
263 if (nbytes < n) 266 if (nbytes < n)
264 return -EOVERFLOW; 267 return -EOVERFLOW;
265 268
266 buf_len = sgl->length; 269 nents = sg_nents_for_len(sgl, nbytes);
267 p2 = sg_virt(sgl); 270 if (nents < 0)
271 return -EINVAL;
268 272
269 while (nbytes > n) { 273 sg_miter_start(&miter, sgl, nents, SG_MITER_ATOMIC | SG_MITER_TO_SG);
270 if (!buf_len) { 274 sg_miter_next(&miter);
271 sgl = sg_next(sgl); 275 buf_len = miter.length;
272 if (!sgl) 276 p2 = miter.addr;
273 return -EINVAL;
274 buf_len = sgl->length;
275 p2 = sg_virt(sgl);
276 }
277 277
278 while (nbytes > n) {
278 i = min_t(unsigned, nbytes - n, buf_len); 279 i = min_t(unsigned, nbytes - n, buf_len);
279 memset(p2, 0, i); 280 memset(p2, 0, i);
280 p2 += i; 281 p2 += i;
281 buf_len -= i;
282 nbytes -= i; 282 nbytes -= i;
283
284 buf_len -= i;
285 if (!buf_len) {
286 sg_miter_next(&miter);
287 buf_len = miter.length;
288 p2 = miter.addr;
289 }
283 } 290 }
284 291
285 for (i = a->nlimbs - 1; i >= 0; i--) { 292 for (i = a->nlimbs - 1; i >= 0; i--) {
@@ -293,17 +300,16 @@ int mpi_write_to_sgl(MPI a, struct scatterlist *sgl, unsigned nbytes,
293 p = (u8 *)&alimb; 300 p = (u8 *)&alimb;
294 301
295 for (x = 0; x < sizeof(alimb); x++) { 302 for (x = 0; x < sizeof(alimb); x++) {
296 if (!buf_len) {
297 sgl = sg_next(sgl);
298 if (!sgl)
299 return -EINVAL;
300 buf_len = sgl->length;
301 p2 = sg_virt(sgl);
302 }
303 *p2++ = *p++; 303 *p2++ = *p++;
304 buf_len--; 304 if (!--buf_len) {
305 sg_miter_next(&miter);
306 buf_len = miter.length;
307 p2 = miter.addr;
308 }
305 } 309 }
306 } 310 }
311
312 sg_miter_stop(&miter);
307 return 0; 313 return 0;
308} 314}
309EXPORT_SYMBOL_GPL(mpi_write_to_sgl); 315EXPORT_SYMBOL_GPL(mpi_write_to_sgl);
@@ -323,19 +329,23 @@ EXPORT_SYMBOL_GPL(mpi_write_to_sgl);
323 */ 329 */
324MPI mpi_read_raw_from_sgl(struct scatterlist *sgl, unsigned int nbytes) 330MPI mpi_read_raw_from_sgl(struct scatterlist *sgl, unsigned int nbytes)
325{ 331{
326 struct scatterlist *sg; 332 struct sg_mapping_iter miter;
327 int x, i, j, z, lzeros, ents;
328 unsigned int nbits, nlimbs; 333 unsigned int nbits, nlimbs;
334 int x, j, z, lzeros, ents;
335 unsigned int len;
336 const u8 *buff;
329 mpi_limb_t a; 337 mpi_limb_t a;
330 MPI val = NULL; 338 MPI val = NULL;
331 339
332 lzeros = 0; 340 ents = sg_nents_for_len(sgl, nbytes);
333 ents = sg_nents(sgl); 341 if (ents < 0)
342 return NULL;
334 343
335 for_each_sg(sgl, sg, ents, i) { 344 sg_miter_start(&miter, sgl, ents, SG_MITER_ATOMIC | SG_MITER_FROM_SG);
336 const u8 *buff = sg_virt(sg);
337 int len = sg->length;
338 345
346 lzeros = 0;
347 len = 0;
348 while (nbytes > 0) {
339 while (len && !*buff) { 349 while (len && !*buff) {
340 lzeros++; 350 lzeros++;
341 len--; 351 len--;
@@ -345,12 +355,14 @@ MPI mpi_read_raw_from_sgl(struct scatterlist *sgl, unsigned int nbytes)
345 if (len && *buff) 355 if (len && *buff)
346 break; 356 break;
347 357
348 ents--; 358 sg_miter_next(&miter);
359 buff = miter.addr;
360 len = miter.length;
361
349 nbytes -= lzeros; 362 nbytes -= lzeros;
350 lzeros = 0; 363 lzeros = 0;
351 } 364 }
352 365
353 sgl = sg;
354 nbytes -= lzeros; 366 nbytes -= lzeros;
355 nbits = nbytes * 8; 367 nbits = nbytes * 8;
356 if (nbits > MAX_EXTERN_MPI_BITS) { 368 if (nbits > MAX_EXTERN_MPI_BITS) {
@@ -359,8 +371,7 @@ MPI mpi_read_raw_from_sgl(struct scatterlist *sgl, unsigned int nbytes)
359 } 371 }
360 372
361 if (nbytes > 0) 373 if (nbytes > 0)
362 nbits -= count_leading_zeros(*(u8 *)(sg_virt(sgl) + lzeros)) - 374 nbits -= count_leading_zeros(*buff) - (BITS_PER_LONG - 8);
363 (BITS_PER_LONG - 8);
364 375
365 nlimbs = DIV_ROUND_UP(nbytes, BYTES_PER_MPI_LIMB); 376 nlimbs = DIV_ROUND_UP(nbytes, BYTES_PER_MPI_LIMB);
366 val = mpi_alloc(nlimbs); 377 val = mpi_alloc(nlimbs);
@@ -379,21 +390,24 @@ MPI mpi_read_raw_from_sgl(struct scatterlist *sgl, unsigned int nbytes)
379 z = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; 390 z = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
380 z %= BYTES_PER_MPI_LIMB; 391 z %= BYTES_PER_MPI_LIMB;
381 392
382 for_each_sg(sgl, sg, ents, i) { 393 for (;;) {
383 const u8 *buffer = sg_virt(sg) + lzeros;
384 int len = sg->length - lzeros;
385
386 for (x = 0; x < len; x++) { 394 for (x = 0; x < len; x++) {
387 a <<= 8; 395 a <<= 8;
388 a |= *buffer++; 396 a |= *buff++;
389 if (((z + x + 1) % BYTES_PER_MPI_LIMB) == 0) { 397 if (((z + x + 1) % BYTES_PER_MPI_LIMB) == 0) {
390 val->d[j--] = a; 398 val->d[j--] = a;
391 a = 0; 399 a = 0;
392 } 400 }
393 } 401 }
394 z += x; 402 z += x;
395 lzeros = 0; 403
404 if (!sg_miter_next(&miter))
405 break;
406
407 buff = miter.addr;
408 len = miter.length;
396 } 409 }
410
397 return val; 411 return val;
398} 412}
399EXPORT_SYMBOL_GPL(mpi_read_raw_from_sgl); 413EXPORT_SYMBOL_GPL(mpi_read_raw_from_sgl);