diff options
author | Elena Reshetova <elena.reshetova@intel.com> | 2017-03-06 09:21:11 -0500 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2017-05-02 01:20:43 -0400 |
commit | 5981c245a890db6a6e16fb6d3838cc9fc9fdf0ff (patch) | |
tree | a1aa3f65fa046e1ac40b923e97b8b2f36b347c08 | |
parent | a5d68ba85801a78c892a0eb8efb711e293ed314b (diff) |
target/iblock: convert iblock_req.pending from atomic_t to refcount_t
refcount_t type and corresponding API should be
used instead of atomic_t when the variable is used as
a reference counter. This allows to avoid accidental
refcounter overflows that might lead to use-after-free
situations.
Signed-off-by: Elena Reshetova <elena.reshetova@intel.com>
Signed-off-by: Hans Liljestrand <ishkamiel@gmail.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
Signed-off-by: David Windsor <dwindsor@gmail.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
-rw-r--r-- | drivers/target/target_core_iblock.c | 12 | ||||
-rw-r--r-- | drivers/target/target_core_iblock.h | 3 |
2 files changed, 8 insertions, 7 deletions
diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index d316ed537d59..bb069ebe4aa6 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c | |||
@@ -279,7 +279,7 @@ static void iblock_complete_cmd(struct se_cmd *cmd) | |||
279 | struct iblock_req *ibr = cmd->priv; | 279 | struct iblock_req *ibr = cmd->priv; |
280 | u8 status; | 280 | u8 status; |
281 | 281 | ||
282 | if (!atomic_dec_and_test(&ibr->pending)) | 282 | if (!refcount_dec_and_test(&ibr->pending)) |
283 | return; | 283 | return; |
284 | 284 | ||
285 | if (atomic_read(&ibr->ib_bio_err_cnt)) | 285 | if (atomic_read(&ibr->ib_bio_err_cnt)) |
@@ -487,7 +487,7 @@ iblock_execute_write_same(struct se_cmd *cmd) | |||
487 | bio_list_init(&list); | 487 | bio_list_init(&list); |
488 | bio_list_add(&list, bio); | 488 | bio_list_add(&list, bio); |
489 | 489 | ||
490 | atomic_set(&ibr->pending, 1); | 490 | refcount_set(&ibr->pending, 1); |
491 | 491 | ||
492 | while (sectors) { | 492 | while (sectors) { |
493 | while (bio_add_page(bio, sg_page(sg), sg->length, sg->offset) | 493 | while (bio_add_page(bio, sg_page(sg), sg->length, sg->offset) |
@@ -498,7 +498,7 @@ iblock_execute_write_same(struct se_cmd *cmd) | |||
498 | if (!bio) | 498 | if (!bio) |
499 | goto fail_put_bios; | 499 | goto fail_put_bios; |
500 | 500 | ||
501 | atomic_inc(&ibr->pending); | 501 | refcount_inc(&ibr->pending); |
502 | bio_list_add(&list, bio); | 502 | bio_list_add(&list, bio); |
503 | } | 503 | } |
504 | 504 | ||
@@ -706,7 +706,7 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, | |||
706 | cmd->priv = ibr; | 706 | cmd->priv = ibr; |
707 | 707 | ||
708 | if (!sgl_nents) { | 708 | if (!sgl_nents) { |
709 | atomic_set(&ibr->pending, 1); | 709 | refcount_set(&ibr->pending, 1); |
710 | iblock_complete_cmd(cmd); | 710 | iblock_complete_cmd(cmd); |
711 | return 0; | 711 | return 0; |
712 | } | 712 | } |
@@ -719,7 +719,7 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, | |||
719 | bio_list_init(&list); | 719 | bio_list_init(&list); |
720 | bio_list_add(&list, bio); | 720 | bio_list_add(&list, bio); |
721 | 721 | ||
722 | atomic_set(&ibr->pending, 2); | 722 | refcount_set(&ibr->pending, 2); |
723 | bio_cnt = 1; | 723 | bio_cnt = 1; |
724 | 724 | ||
725 | for_each_sg(sgl, sg, sgl_nents, i) { | 725 | for_each_sg(sgl, sg, sgl_nents, i) { |
@@ -740,7 +740,7 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, | |||
740 | if (!bio) | 740 | if (!bio) |
741 | goto fail_put_bios; | 741 | goto fail_put_bios; |
742 | 742 | ||
743 | atomic_inc(&ibr->pending); | 743 | refcount_inc(&ibr->pending); |
744 | bio_list_add(&list, bio); | 744 | bio_list_add(&list, bio); |
745 | bio_cnt++; | 745 | bio_cnt++; |
746 | } | 746 | } |
diff --git a/drivers/target/target_core_iblock.h b/drivers/target/target_core_iblock.h index 718d3fcd3e7c..f2a5797217d4 100644 --- a/drivers/target/target_core_iblock.h +++ b/drivers/target/target_core_iblock.h | |||
@@ -2,6 +2,7 @@ | |||
2 | #define TARGET_CORE_IBLOCK_H | 2 | #define TARGET_CORE_IBLOCK_H |
3 | 3 | ||
4 | #include <linux/atomic.h> | 4 | #include <linux/atomic.h> |
5 | #include <linux/refcount.h> | ||
5 | #include <target/target_core_base.h> | 6 | #include <target/target_core_base.h> |
6 | 7 | ||
7 | #define IBLOCK_VERSION "4.0" | 8 | #define IBLOCK_VERSION "4.0" |
@@ -10,7 +11,7 @@ | |||
10 | #define IBLOCK_LBA_SHIFT 9 | 11 | #define IBLOCK_LBA_SHIFT 9 |
11 | 12 | ||
12 | struct iblock_req { | 13 | struct iblock_req { |
13 | atomic_t pending; | 14 | refcount_t pending; |
14 | atomic_t ib_bio_err_cnt; | 15 | atomic_t ib_bio_err_cnt; |
15 | } ____cacheline_aligned; | 16 | } ____cacheline_aligned; |
16 | 17 | ||