| From 38da0f49e8aa1649af397d53f88e163d0e60c058 Mon Sep 17 00:00:00 2001 |
| From: Akinobu Mita <akinobu.mita@gmail.com> |
| Date: Mon, 13 Apr 2015 23:21:56 +0900 |
| Subject: target/file: Fix BUG() when CONFIG_DEBUG_SG=y and DIF protection enabled |
| |
| From: Akinobu Mita <akinobu.mita@gmail.com> |
| |
| commit 38da0f49e8aa1649af397d53f88e163d0e60c058 upstream. |
| |
| When CONFIG_DEBUG_SG=y and DIF protection support enabled, kernel |
| BUG()s are triggered due to the following two issues: |
| |
| 1) prot_sg is not initialized by sg_init_table(). |
| |
| When CONFIG_DEBUG_SG=y, scatterlist helpers check sg entry has a |
| correct magic value. |
| |
| 2) vmalloc'ed buffer is passed to sg_set_buf(). |
| |
| sg_set_buf() uses virt_to_page() to convert virtual address to struct |
| page, but it doesn't work with vmalloc address. vmalloc_to_page() |
| should be used instead. As prot_buf isn't usually too large, so |
| fix it by allocating prot_buf by kmalloc instead of vmalloc. |
| |
| Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com> |
| Cc: Sagi Grimberg <sagig@mellanox.com> |
| Cc: "Martin K. Petersen" <martin.petersen@oracle.com> |
| Cc: Christoph Hellwig <hch@lst.de> |
| Cc: "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com> |
| Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/target/target_core_file.c | 15 ++++++++------- |
| 1 file changed, 8 insertions(+), 7 deletions(-) |
| |
| --- a/drivers/target/target_core_file.c |
| +++ b/drivers/target/target_core_file.c |
| @@ -274,7 +274,7 @@ static int fd_do_prot_rw(struct se_cmd * |
| se_dev->prot_length; |
| |
| if (!is_write) { |
| - fd_prot->prot_buf = vzalloc(prot_size); |
| + fd_prot->prot_buf = kzalloc(prot_size, GFP_KERNEL); |
| if (!fd_prot->prot_buf) { |
| pr_err("Unable to allocate fd_prot->prot_buf\n"); |
| return -ENOMEM; |
| @@ -286,9 +286,10 @@ static int fd_do_prot_rw(struct se_cmd * |
| fd_prot->prot_sg_nents, GFP_KERNEL); |
| if (!fd_prot->prot_sg) { |
| pr_err("Unable to allocate fd_prot->prot_sg\n"); |
| - vfree(fd_prot->prot_buf); |
| + kfree(fd_prot->prot_buf); |
| return -ENOMEM; |
| } |
| + sg_init_table(fd_prot->prot_sg, fd_prot->prot_sg_nents); |
| size = prot_size; |
| |
| for_each_sg(fd_prot->prot_sg, sg, fd_prot->prot_sg_nents, i) { |
| @@ -318,7 +319,7 @@ static int fd_do_prot_rw(struct se_cmd * |
| |
| if (is_write || ret < 0) { |
| kfree(fd_prot->prot_sg); |
| - vfree(fd_prot->prot_buf); |
| + kfree(fd_prot->prot_buf); |
| } |
| |
| return ret; |
| @@ -658,11 +659,11 @@ fd_execute_rw(struct se_cmd *cmd, struct |
| 0, fd_prot.prot_sg, 0); |
| if (rc) { |
| kfree(fd_prot.prot_sg); |
| - vfree(fd_prot.prot_buf); |
| + kfree(fd_prot.prot_buf); |
| return rc; |
| } |
| kfree(fd_prot.prot_sg); |
| - vfree(fd_prot.prot_buf); |
| + kfree(fd_prot.prot_buf); |
| } |
| } else { |
| memset(&fd_prot, 0, sizeof(struct fd_prot)); |
| @@ -678,7 +679,7 @@ fd_execute_rw(struct se_cmd *cmd, struct |
| 0, fd_prot.prot_sg, 0); |
| if (rc) { |
| kfree(fd_prot.prot_sg); |
| - vfree(fd_prot.prot_buf); |
| + kfree(fd_prot.prot_buf); |
| return rc; |
| } |
| } |
| @@ -714,7 +715,7 @@ fd_execute_rw(struct se_cmd *cmd, struct |
| |
| if (ret < 0) { |
| kfree(fd_prot.prot_sg); |
| - vfree(fd_prot.prot_buf); |
| + kfree(fd_prot.prot_buf); |
| return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
| } |
| |