aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/crypto
diff options
context:
space:
mode:
authorHoria Geantă <horia.geanta@nxp.com>2019-01-26 13:02:15 -0500
committerHerbert Xu <herbert@gondor.apana.org.au>2019-02-01 01:44:38 -0500
commitc19650d6ea99bcd903d3e55dd61860026c701339 (patch)
tree45170f328c5daac8a4bf21ee9cd63b75206af99f /drivers/crypto
parent5a22b198cd5274470d637d45f0e3bcdc0175a349 (diff)
crypto: caam - fix DMA mapping of stack memory
Roland reports the following issue and provides a root cause analysis: "On a v4.19 i.MX6 system with IMA and CONFIG_DMA_API_DEBUG enabled, a warning is generated when accessing files on a filesystem for which IMA measurement is enabled: ------------[ cut here ]------------ WARNING: CPU: 0 PID: 1 at kernel/dma/debug.c:1181 check_for_stack.part.9+0xd0/0x120 caam_jr 2101000.jr0: DMA-API: device driver maps memory from stack [addr=b668049e] Modules linked in: CPU: 0 PID: 1 Comm: switch_root Not tainted 4.19.0-20181214-1 #2 Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree) Backtrace: [<c010efb8>] (dump_backtrace) from [<c010f2d0>] (show_stack+0x20/0x24) [<c010f2b0>] (show_stack) from [<c08b04f4>] (dump_stack+0xa0/0xcc) [<c08b0454>] (dump_stack) from [<c012b610>] (__warn+0xf0/0x108) [<c012b520>] (__warn) from [<c012b680>] (warn_slowpath_fmt+0x58/0x74) [<c012b62c>] (warn_slowpath_fmt) from [<c0199acc>] (check_for_stack.part.9+0xd0/0x120) [<c01999fc>] (check_for_stack.part.9) from [<c019a040>] (debug_dma_map_page+0x144/0x174) [<c0199efc>] (debug_dma_map_page) from [<c065f7f4>] (ahash_final_ctx+0x5b4/0xcf0) [<c065f240>] (ahash_final_ctx) from [<c065b3c4>] (ahash_final+0x1c/0x20) [<c065b3a8>] (ahash_final) from [<c03fe278>] (crypto_ahash_op+0x38/0x80) [<c03fe240>] (crypto_ahash_op) from [<c03fe2e0>] (crypto_ahash_final+0x20/0x24) [<c03fe2c0>] (crypto_ahash_final) from [<c03f19a8>] (ima_calc_file_hash+0x29c/0xa40) [<c03f170c>] (ima_calc_file_hash) from [<c03f2b24>] (ima_collect_measurement+0x1dc/0x240) [<c03f2948>] (ima_collect_measurement) from [<c03f0a60>] (process_measurement+0x4c4/0x6b8) [<c03f059c>] (process_measurement) from [<c03f0cdc>] (ima_file_check+0x88/0xa4) [<c03f0c54>] (ima_file_check) from [<c02d8adc>] (path_openat+0x5d8/0x1364) [<c02d8504>] (path_openat) from [<c02dad24>] (do_filp_open+0x84/0xf0) [<c02daca0>] (do_filp_open) from [<c02cf50c>] (do_open_execat+0x84/0x1b0) [<c02cf488>] (do_open_execat) from [<c02d1058>] (__do_execve_file+0x43c/0x890) [<c02d0c1c>] (__do_execve_file) from [<c02d1770>] (sys_execve+0x44/0x4c) [<c02d172c>] (sys_execve) from [<c0101000>] (ret_fast_syscall+0x0/0x28) ---[ end trace 3455789a10e3aefd ]--- The cause is that the struct ahash_request *req is created as a stack-local variable up in the stack (presumably somewhere in the IMA implementation), then passed down into the CAAM driver, which tries to dma_single_map the req->result (indirectly via map_seq_out_ptr_result) in order to make that buffer available for the CAAM to store the result of the following hash operation. The calling code doesn't know how req will be used by the CAAM driver, and there could be other such occurrences where stack memory is passed down to the CAAM driver. Therefore we should rather fix this issue in the CAAM driver where the requirements are known." Fix this problem by: -instructing the crypto engine to write the final hash in state->caam_ctx -subsequently memcpy-ing the final hash into req->result Cc: <stable@vger.kernel.org> # v4.19+ Reported-by: Roland Hieber <rhi@pengutronix.de> Signed-off-by: Horia Geantă <horia.geanta@nxp.com> Tested-by: Roland Hieber <rhi@pengutronix.de> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'drivers/crypto')
-rw-r--r--drivers/crypto/caam/caamhash.c85
1 files changed, 21 insertions, 64 deletions
diff --git a/drivers/crypto/caam/caamhash.c b/drivers/crypto/caam/caamhash.c
index 5855d03f52d1..3bba3cb92f03 100644
--- a/drivers/crypto/caam/caamhash.c
+++ b/drivers/crypto/caam/caamhash.c
@@ -184,18 +184,6 @@ static inline int map_seq_out_ptr_ctx(u32 *desc, struct device *jrdev,
184 return 0; 184 return 0;
185} 185}
186 186
187/* Map req->result, and append seq_out_ptr command that points to it */
188static inline dma_addr_t map_seq_out_ptr_result(u32 *desc, struct device *jrdev,
189 u8 *result, int digestsize)
190{
191 dma_addr_t dst_dma;
192
193 dst_dma = dma_map_single(jrdev, result, digestsize, DMA_FROM_DEVICE);
194 append_seq_out_ptr(desc, dst_dma, digestsize, 0);
195
196 return dst_dma;
197}
198
199/* Map current buffer in state (if length > 0) and put it in link table */ 187/* Map current buffer in state (if length > 0) and put it in link table */
200static inline int buf_map_to_sec4_sg(struct device *jrdev, 188static inline int buf_map_to_sec4_sg(struct device *jrdev,
201 struct sec4_sg_entry *sec4_sg, 189 struct sec4_sg_entry *sec4_sg,
@@ -568,7 +556,6 @@ static int acmac_setkey(struct crypto_ahash *ahash, const u8 *key,
568 556
569/* 557/*
570 * ahash_edesc - s/w-extended ahash descriptor 558 * ahash_edesc - s/w-extended ahash descriptor
571 * @dst_dma: physical mapped address of req->result
572 * @sec4_sg_dma: physical mapped address of h/w link table 559 * @sec4_sg_dma: physical mapped address of h/w link table
573 * @src_nents: number of segments in input scatterlist 560 * @src_nents: number of segments in input scatterlist
574 * @sec4_sg_bytes: length of dma mapped sec4_sg space 561 * @sec4_sg_bytes: length of dma mapped sec4_sg space
@@ -576,7 +563,6 @@ static int acmac_setkey(struct crypto_ahash *ahash, const u8 *key,
576 * @sec4_sg: h/w link table 563 * @sec4_sg: h/w link table
577 */ 564 */
578struct ahash_edesc { 565struct ahash_edesc {
579 dma_addr_t dst_dma;
580 dma_addr_t sec4_sg_dma; 566 dma_addr_t sec4_sg_dma;
581 int src_nents; 567 int src_nents;
582 int sec4_sg_bytes; 568 int sec4_sg_bytes;
@@ -592,8 +578,6 @@ static inline void ahash_unmap(struct device *dev,
592 578
593 if (edesc->src_nents) 579 if (edesc->src_nents)
594 dma_unmap_sg(dev, req->src, edesc->src_nents, DMA_TO_DEVICE); 580 dma_unmap_sg(dev, req->src, edesc->src_nents, DMA_TO_DEVICE);
595 if (edesc->dst_dma)
596 dma_unmap_single(dev, edesc->dst_dma, dst_len, DMA_FROM_DEVICE);
597 581
598 if (edesc->sec4_sg_bytes) 582 if (edesc->sec4_sg_bytes)
599 dma_unmap_single(dev, edesc->sec4_sg_dma, 583 dma_unmap_single(dev, edesc->sec4_sg_dma,
@@ -628,9 +612,9 @@ static void ahash_done(struct device *jrdev, u32 *desc, u32 err,
628 struct ahash_edesc *edesc; 612 struct ahash_edesc *edesc;
629 struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); 613 struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
630 int digestsize = crypto_ahash_digestsize(ahash); 614 int digestsize = crypto_ahash_digestsize(ahash);
615 struct caam_hash_state *state = ahash_request_ctx(req);
631#ifdef DEBUG 616#ifdef DEBUG
632 struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); 617 struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
633 struct caam_hash_state *state = ahash_request_ctx(req);
634 618
635 dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err); 619 dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
636#endif 620#endif
@@ -639,17 +623,14 @@ static void ahash_done(struct device *jrdev, u32 *desc, u32 err,
639 if (err) 623 if (err)
640 caam_jr_strstatus(jrdev, err); 624 caam_jr_strstatus(jrdev, err);
641 625
642 ahash_unmap(jrdev, edesc, req, digestsize); 626 ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_FROM_DEVICE);
627 memcpy(req->result, state->caam_ctx, digestsize);
643 kfree(edesc); 628 kfree(edesc);
644 629
645#ifdef DEBUG 630#ifdef DEBUG
646 print_hex_dump(KERN_ERR, "ctx@"__stringify(__LINE__)": ", 631 print_hex_dump(KERN_ERR, "ctx@"__stringify(__LINE__)": ",
647 DUMP_PREFIX_ADDRESS, 16, 4, state->caam_ctx, 632 DUMP_PREFIX_ADDRESS, 16, 4, state->caam_ctx,
648 ctx->ctx_len, 1); 633 ctx->ctx_len, 1);
649 if (req->result)
650 print_hex_dump(KERN_ERR, "result@"__stringify(__LINE__)": ",
651 DUMP_PREFIX_ADDRESS, 16, 4, req->result,
652 digestsize, 1);
653#endif 634#endif
654 635
655 req->base.complete(&req->base, err); 636 req->base.complete(&req->base, err);
@@ -697,9 +678,9 @@ static void ahash_done_ctx_src(struct device *jrdev, u32 *desc, u32 err,
697 struct ahash_edesc *edesc; 678 struct ahash_edesc *edesc;
698 struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); 679 struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
699 int digestsize = crypto_ahash_digestsize(ahash); 680 int digestsize = crypto_ahash_digestsize(ahash);
681 struct caam_hash_state *state = ahash_request_ctx(req);
700#ifdef DEBUG 682#ifdef DEBUG
701 struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); 683 struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
702 struct caam_hash_state *state = ahash_request_ctx(req);
703 684
704 dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err); 685 dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
705#endif 686#endif
@@ -708,17 +689,14 @@ static void ahash_done_ctx_src(struct device *jrdev, u32 *desc, u32 err,
708 if (err) 689 if (err)
709 caam_jr_strstatus(jrdev, err); 690 caam_jr_strstatus(jrdev, err);
710 691
711 ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_TO_DEVICE); 692 ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_BIDIRECTIONAL);
693 memcpy(req->result, state->caam_ctx, digestsize);
712 kfree(edesc); 694 kfree(edesc);
713 695
714#ifdef DEBUG 696#ifdef DEBUG
715 print_hex_dump(KERN_ERR, "ctx@"__stringify(__LINE__)": ", 697 print_hex_dump(KERN_ERR, "ctx@"__stringify(__LINE__)": ",
716 DUMP_PREFIX_ADDRESS, 16, 4, state->caam_ctx, 698 DUMP_PREFIX_ADDRESS, 16, 4, state->caam_ctx,
717 ctx->ctx_len, 1); 699 ctx->ctx_len, 1);
718 if (req->result)
719 print_hex_dump(KERN_ERR, "result@"__stringify(__LINE__)": ",
720 DUMP_PREFIX_ADDRESS, 16, 4, req->result,
721 digestsize, 1);
722#endif 700#endif
723 701
724 req->base.complete(&req->base, err); 702 req->base.complete(&req->base, err);
@@ -991,7 +969,7 @@ static int ahash_final_ctx(struct ahash_request *req)
991 edesc->sec4_sg_bytes = sec4_sg_bytes; 969 edesc->sec4_sg_bytes = sec4_sg_bytes;
992 970
993 ret = ctx_map_to_sec4_sg(jrdev, state, ctx->ctx_len, 971 ret = ctx_map_to_sec4_sg(jrdev, state, ctx->ctx_len,
994 edesc->sec4_sg, DMA_TO_DEVICE); 972 edesc->sec4_sg, DMA_BIDIRECTIONAL);
995 if (ret) 973 if (ret)
996 goto unmap_ctx; 974 goto unmap_ctx;
997 975
@@ -1011,14 +989,7 @@ static int ahash_final_ctx(struct ahash_request *req)
1011 989
1012 append_seq_in_ptr(desc, edesc->sec4_sg_dma, ctx->ctx_len + buflen, 990 append_seq_in_ptr(desc, edesc->sec4_sg_dma, ctx->ctx_len + buflen,
1013 LDST_SGF); 991 LDST_SGF);
1014 992 append_seq_out_ptr(desc, state->ctx_dma, digestsize, 0);
1015 edesc->dst_dma = map_seq_out_ptr_result(desc, jrdev, req->result,
1016 digestsize);
1017 if (dma_mapping_error(jrdev, edesc->dst_dma)) {
1018 dev_err(jrdev, "unable to map dst\n");
1019 ret = -ENOMEM;
1020 goto unmap_ctx;
1021 }
1022 993
1023#ifdef DEBUG 994#ifdef DEBUG
1024 print_hex_dump(KERN_ERR, "jobdesc@"__stringify(__LINE__)": ", 995 print_hex_dump(KERN_ERR, "jobdesc@"__stringify(__LINE__)": ",
@@ -1031,7 +1002,7 @@ static int ahash_final_ctx(struct ahash_request *req)
1031 1002
1032 return -EINPROGRESS; 1003 return -EINPROGRESS;
1033 unmap_ctx: 1004 unmap_ctx:
1034 ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_FROM_DEVICE); 1005 ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_BIDIRECTIONAL);
1035 kfree(edesc); 1006 kfree(edesc);
1036 return ret; 1007 return ret;
1037} 1008}
@@ -1085,7 +1056,7 @@ static int ahash_finup_ctx(struct ahash_request *req)
1085 edesc->src_nents = src_nents; 1056 edesc->src_nents = src_nents;
1086 1057
1087 ret = ctx_map_to_sec4_sg(jrdev, state, ctx->ctx_len, 1058 ret = ctx_map_to_sec4_sg(jrdev, state, ctx->ctx_len,
1088 edesc->sec4_sg, DMA_TO_DEVICE); 1059 edesc->sec4_sg, DMA_BIDIRECTIONAL);
1089 if (ret) 1060 if (ret)
1090 goto unmap_ctx; 1061 goto unmap_ctx;
1091 1062
@@ -1099,13 +1070,7 @@ static int ahash_finup_ctx(struct ahash_request *req)
1099 if (ret) 1070 if (ret)
1100 goto unmap_ctx; 1071 goto unmap_ctx;
1101 1072
1102 edesc->dst_dma = map_seq_out_ptr_result(desc, jrdev, req->result, 1073 append_seq_out_ptr(desc, state->ctx_dma, digestsize, 0);
1103 digestsize);
1104 if (dma_mapping_error(jrdev, edesc->dst_dma)) {
1105 dev_err(jrdev, "unable to map dst\n");
1106 ret = -ENOMEM;
1107 goto unmap_ctx;
1108 }
1109 1074
1110#ifdef DEBUG 1075#ifdef DEBUG
1111 print_hex_dump(KERN_ERR, "jobdesc@"__stringify(__LINE__)": ", 1076 print_hex_dump(KERN_ERR, "jobdesc@"__stringify(__LINE__)": ",
@@ -1118,7 +1083,7 @@ static int ahash_finup_ctx(struct ahash_request *req)
1118 1083
1119 return -EINPROGRESS; 1084 return -EINPROGRESS;
1120 unmap_ctx: 1085 unmap_ctx:
1121 ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_FROM_DEVICE); 1086 ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_BIDIRECTIONAL);
1122 kfree(edesc); 1087 kfree(edesc);
1123 return ret; 1088 return ret;
1124} 1089}
@@ -1177,10 +1142,8 @@ static int ahash_digest(struct ahash_request *req)
1177 1142
1178 desc = edesc->hw_desc; 1143 desc = edesc->hw_desc;
1179 1144
1180 edesc->dst_dma = map_seq_out_ptr_result(desc, jrdev, req->result, 1145 ret = map_seq_out_ptr_ctx(desc, jrdev, state, digestsize);
1181 digestsize); 1146 if (ret) {
1182 if (dma_mapping_error(jrdev, edesc->dst_dma)) {
1183 dev_err(jrdev, "unable to map dst\n");
1184 ahash_unmap(jrdev, edesc, req, digestsize); 1147 ahash_unmap(jrdev, edesc, req, digestsize);
1185 kfree(edesc); 1148 kfree(edesc);
1186 return -ENOMEM; 1149 return -ENOMEM;
@@ -1195,7 +1158,7 @@ static int ahash_digest(struct ahash_request *req)
1195 if (!ret) { 1158 if (!ret) {
1196 ret = -EINPROGRESS; 1159 ret = -EINPROGRESS;
1197 } else { 1160 } else {
1198 ahash_unmap(jrdev, edesc, req, digestsize); 1161 ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_FROM_DEVICE);
1199 kfree(edesc); 1162 kfree(edesc);
1200 } 1163 }
1201 1164
@@ -1237,12 +1200,9 @@ static int ahash_final_no_ctx(struct ahash_request *req)
1237 append_seq_in_ptr(desc, state->buf_dma, buflen, 0); 1200 append_seq_in_ptr(desc, state->buf_dma, buflen, 0);
1238 } 1201 }
1239 1202
1240 edesc->dst_dma = map_seq_out_ptr_result(desc, jrdev, req->result, 1203 ret = map_seq_out_ptr_ctx(desc, jrdev, state, digestsize);
1241 digestsize); 1204 if (ret)
1242 if (dma_mapping_error(jrdev, edesc->dst_dma)) {
1243 dev_err(jrdev, "unable to map dst\n");
1244 goto unmap; 1205 goto unmap;
1245 }
1246 1206
1247#ifdef DEBUG 1207#ifdef DEBUG
1248 print_hex_dump(KERN_ERR, "jobdesc@"__stringify(__LINE__)": ", 1208 print_hex_dump(KERN_ERR, "jobdesc@"__stringify(__LINE__)": ",
@@ -1253,7 +1213,7 @@ static int ahash_final_no_ctx(struct ahash_request *req)
1253 if (!ret) { 1213 if (!ret) {
1254 ret = -EINPROGRESS; 1214 ret = -EINPROGRESS;
1255 } else { 1215 } else {
1256 ahash_unmap(jrdev, edesc, req, digestsize); 1216 ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_FROM_DEVICE);
1257 kfree(edesc); 1217 kfree(edesc);
1258 } 1218 }
1259 1219
@@ -1464,12 +1424,9 @@ static int ahash_finup_no_ctx(struct ahash_request *req)
1464 goto unmap; 1424 goto unmap;
1465 } 1425 }
1466 1426
1467 edesc->dst_dma = map_seq_out_ptr_result(desc, jrdev, req->result, 1427 ret = map_seq_out_ptr_ctx(desc, jrdev, state, digestsize);
1468 digestsize); 1428 if (ret)
1469 if (dma_mapping_error(jrdev, edesc->dst_dma)) {
1470 dev_err(jrdev, "unable to map dst\n");
1471 goto unmap; 1429 goto unmap;
1472 }
1473 1430
1474#ifdef DEBUG 1431#ifdef DEBUG
1475 print_hex_dump(KERN_ERR, "jobdesc@"__stringify(__LINE__)": ", 1432 print_hex_dump(KERN_ERR, "jobdesc@"__stringify(__LINE__)": ",
@@ -1480,7 +1437,7 @@ static int ahash_finup_no_ctx(struct ahash_request *req)
1480 if (!ret) { 1437 if (!ret) {
1481 ret = -EINPROGRESS; 1438 ret = -EINPROGRESS;
1482 } else { 1439 } else {
1483 ahash_unmap(jrdev, edesc, req, digestsize); 1440 ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_FROM_DEVICE);
1484 kfree(edesc); 1441 kfree(edesc);
1485 } 1442 }
1486 1443