infiniband: ulp/iser, fix error retval in iser_create_ib_conn_res
Subsystems (2)
PATCH 1/1 infiniband: ulp/iser, fix error retval in iser_create_ib_conn_res
Stanse foudn unreachable code in iser_create_ib_conn_res. Namely there is switched goto and ret assignment. Switch them to make sense and return ENOMEM in case of error.
--- drivers/infiniband/ulp/iser/iser_verbs.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/infiniband/ulp/iser/iser_verbs.c +1 -1
@@ -149,8 +149,8 @@ static int iser_create_ib_conn_res(struct iser_conn *ib_conn) ib_conn->login_buf =kmalloc (ISER_RX_LOGIN_SIZE ,GFP_KERNEL );if (!ib_conn->login_buf) { - goto alloc_err; ret = -ENOMEM ; + goto alloc_err; } ib_conn->login_dma = ib_dma_map_single(ib_conn->device->ib_device,
Signature · 1 line
1.7.0.1
drivers/infiniband/ulp/iser/iser_verbs.c static int iser_create_ib_conn_res(struct iser_conn *ib_conn) · line 154
Quoted 6 lines
drivers/infiniband/ulp/iser/iser_verbs.c +1
-1ib_conn->login_buf =kmalloc (ISER_RX_LOGIN_SIZE ,GFP_KERNEL );if (!ib_conn->login_buf) { - goto alloc_err; ret = -ENOMEM ; + goto alloc_err; }
This looks like a valid fix but it's the same part of the code that Dan found more extensive bugs in. Or, can I assume you'll sort this out and make sure a final patch is sorted out?
Thanks,
Roland
Signature · 3 lines
Roland Dreier <[email protected]> For corporate legal information go to: http://www.cisco.com/web/about/doing_business/legal/cri/index.html
Quoted 11 lines · Roland Dreier
drivers/infiniband/ulp/iser/iser_verbs.c static int iser_create_ib_conn_res(struct iser_conn *ib_conn) · line 154
Quoted 6 lines
drivers/infiniband/ulp/iser/iser_verbs.c +1
-1ib_conn->login_buf =kmalloc (ISER_RX_LOGIN_SIZE ,GFP_KERNEL );if (!ib_conn->login_buf) { - goto alloc_err; ret = -ENOMEM ; + goto alloc_err; }This looks like a valid fix but it's the same part of the code that Dan found more extensive bugs in. Or, can I assume you'll sort this out and make sure a final patch is sorted out?
My patch is the one to take. It addresses this problem here and fixes some double frees.
http://marc.info/?l=linux-rdma&m=126872745710910&w=2
Sorry about that Jiri. Btw. Julia Lawall, Daren Jenkins and I normally CC kernel-janitors for static checker patches.
regards,
dan carpenter
Quoted 6 lines
Thanks,
RolandSignature · 3 lines
Roland Dreier <[email protected]> For corporate legal information go to: http://www.cisco.com/web/about/doing_business/legal/cri/index.html
So looking at merging this finally, I think I see one problem with the proposed patch. We have:
Review static int iser_create_ib_conn_res(struct iser_conn *ib_conn) · line 184
Quoted 7 lines
(quoted diff) +1
-1@@ -183,7 +180,7 @@ static int iser_create_ib_conn_res(struct iser_conn *ib_conn) ib_conn->fmr_pool = ib_create_fmr_pool(device->pd, ¶ms); if (IS_ERR(ib_conn->fmr_pool)) { ret = PTR_ERR(ib_conn->fmr_pool); - goto fmr_pool_err; + goto out_err; }
and
Quoted 4 lines
(quoted diff) +0
-0@@ -209,12 +206,7 @@ static int iser_create_ib_conn_res(struct iser_conn *ib_conn) ib_conn->fmr_pool, ib_conn->cma_id->qp); return ret;
Review static int iser_create_ib_conn_res(struct iser_conn *ib_conn) · line 212
Quoted 10 lines
(quoted diff) +1
-6-qp_err: - (void)ib_destroy_fmr_pool(ib_conn->fmr_pool); -fmr_pool_err: - kfree(ib_conn->page_vec); - kfree(ib_conn->login_buf); -alloc_err: +out_err: iser_err("unable to alloc mem or create resource, err %d\n", ret); return ret; }
so if ib_create_fmr_pool() fails, we're left with ib_conn->fmr_pool holding an error pointer, right? But we're relying on iser_free_ib_conn_res() to clean up after us, and that has:
if (ib_conn->fmr_pool != NULL) ib_destroy_fmr_pool(ib_conn->fmr_pool);
so we're going to end up trying to free an error pointer, which will probably crash.
I think.
Dan or Or, am I wrong here or do we need another iteration of this patch? (the login_buf and page_vec changes do look correct to me, since a failed kmalloc() will leave us with a NULL pointer that it is safe to kfree() later)
- R.
Signature · 2 lines
Roland Dreier <[email protected]> || For corporate legal information go to: http://www.cisco.com/web/about/doing_business/legal/cri/index.html
Quoted 38 lines · Roland Dreier
So looking at merging this finally, I think I see one problem with the proposed patch. We have:
Review static int iser_create_ib_conn_res(struct iser_conn *ib_conn) · line 184
Quoted 7 lines
(quoted diff) +1
-1@@ -183,7 +180,7 @@ static int iser_create_ib_conn_res(struct iser_conn *ib_conn) ib_conn->fmr_pool = ib_create_fmr_pool(device->pd, ¶ms); if (IS_ERR(ib_conn->fmr_pool)) { ret = PTR_ERR(ib_conn->fmr_pool); - goto fmr_pool_err; + goto out_err; }and
Quoted 4 lines
(quoted diff) +0
-0@@ -209,12 +206,7 @@ static int iser_create_ib_conn_res(struct iser_conn *ib_conn) ib_conn->fmr_pool, ib_conn->cma_id->qp); return ret;Review static int iser_create_ib_conn_res(struct iser_conn *ib_conn) · line 212
Quoted 10 lines
(quoted diff) +1
-6-qp_err: - (void)ib_destroy_fmr_pool(ib_conn->fmr_pool); -fmr_pool_err: - kfree(ib_conn->page_vec); - kfree(ib_conn->login_buf); -alloc_err: +out_err: iser_err("unable to alloc mem or create resource, err %d\n", ret); return ret; }so if
ib_create_fmr_pool()fails, we're left withib_conn->fmr_poolholding an error pointer, right? But we're relying oniser_free_ib_conn_res()to clean up after us, and that has:if (ib_conn->fmr_pool != NULL) ib_destroy_fmr_pool(ib_conn->fmr_pool);so we're going to end up trying to free an error pointer, which will probably crash.
Quoted 6 lines
I think.
Dan or Or, am I wrong here or do we need another iteration of this patch? (the
login_bufandpage_vecchanges do look correct to me, since a failedkmalloc()will leave us with a NULL pointer that it is safe tokfree()later)
You're right. I missed that.
I will send an updated patch tomorrow.
regards,
dan carpenter
Quoted 5 lines
- R.
Signature · 2 lines
Roland Dreier <[email protected]> || For corporate legal information go to: http://www.cisco.com/web/about/doing_business/legal/cri/index.html
PATCH v3 1/1 infiniband: ulp/iser, fix error retval in iser_create_ib_conn_res
In reply to Roland DreierWe shouldn't free things here because we free them later. The call tree looks like this:iser_connect() => iser_cma_handler() => iser_route_handler()
=> iser_create_ib_conn_res()
We fail here and return failures back down the tree.
iser_connect() => iser_conn_release()
Double free.
---
V1 fixed unreachable code
V2 noticed that the original code had a double free V3 Roland Dreier points out that I left a dangling ERR_PTR() in
"ib_conn->fmr_pool" which would be freed later on.
drivers/infiniband/ulp/iser/iser_verbs.c +9 -16
@@ -148,10 +148,8 @@ static int iser_create_ib_conn_res(struct iser_conn *ib_conn) device = ib_conn->device; ib_conn->login_buf =kmalloc (ISER_RX_LOGIN_SIZE ,GFP_KERNEL ); -if (!ib_conn->login_buf) { - goto alloc_err; - ret = -ENOMEM ; - } +if (!ib_conn->login_buf) + goto out_err; ib_conn->login_dma = ib_dma_map_single(ib_conn->device->ib_device, (void *)ib_conn->login_buf, ISER_RX_LOGIN_SIZE,
@@ -160,10 +158,9 @@ static int iser_create_ib_conn_res(struct iser_conn *ib_conn) ib_conn->page_vec =kmalloc (sizeof (struct iser_page_vec ) + (sizeof (u64) * (ISCSI_ISER_SG_TABLESIZE +1 )),GFP_KERNEL ); -if (!ib_conn->page_vec) { - ret = -ENOMEM ; - goto alloc_err; - } +if (!ib_conn->page_vec) + goto out_err; + ib_conn->page_vec->pages = (u64 *) (ib_conn->page_vec +1 ); params.page_shift =SHIFT_4K ;
@@ -183,7 +180,8 @@ static int iser_create_ib_conn_res(struct iser_conn *ib_conn) ib_conn->fmr_pool =ib_create_fmr_pool (device->pd, ¶ms);if (IS_ERR (ib_conn->fmr_pool)) { ret =PTR_ERR (ib_conn->fmr_pool); - goto fmr_pool_err; + ib_conn->fmr_pool =NULL ; + goto out_err; }memset (&init_attr,0 ,sizeof init_attr);
@@ -201,7 +199,7 @@ static int iser_create_ib_conn_res(struct iser_conn *ib_conn) ret =rdma_create_qp (ib_conn->cma_id, device->pd, &init_attr);if (ret) - goto qp_err; + goto out_err; ib_conn->qp = ib_conn->cma_id->qp; iser_err("setting conn %p cma_id %p: fmr_pool %p qp %p\n",
@@ -209,12 +207,7 @@ static int iser_create_ib_conn_res(struct iser_conn *ib_conn) ib_conn->fmr_pool, ib_conn->cma_id->qp);return ret; -qp_err: - (void )ib_destroy_fmr_pool (ib_conn->fmr_pool); -fmr_pool_err: -kfree (ib_conn->page_vec); -kfree (ib_conn->login_buf); -alloc_err: +out_err:iser_err ("unable to alloc mem or create resource, err %d\n" , ret);return ret; }
Or, I don't think we ever fixed this. This patch looks correct to me, any problem with merging this for 2.6.35?
Signature · 2 lines
Roland Dreier <[email protected]> || For corporate legal information go to: http://www.cisco.com/web/about/doing_business/legal/cri/index.html
Quoted 2 lines · Roland Dreier
Or, I don't think we ever fixed this. This patch looks correct to me, any problem with merging this for 2.6.35?
Roland, please use V4 below, the patch is okay and would apply before and after applying the multipathing patches I sent yesterday (same goes for them).
[PATCH V4] ib/iser: fix error flow in iser_create_ib_conn_res
From: Dan Carpenter <[email protected]>
We shouldn't free things here because we free them later. The call tree looks like this:
iser_connect() ==> initiating the connection establishment and later iser_cma_handler() => iser_route_handler() => iser_create_ib_conn_res()
if we fail here, eventually iser_conn_release() is called, resulted in double free.
---
V1 fixed unreachable code
V2 noticed that the original code had a double free V3 Roland Dreier points out that I left a dangling ERR_PTR() in
"ib_conn->fmr_pool" which would be freed later on.
V4 reviewed/enhanced the change-log
--- drivers/infiniband/ulp/iser/iser_verbs.c | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-)
drivers/infiniband/ulp/iser/iser_verbs.c +9 -16
@@ -163,10 +163,8 @@ static int iser_create_ib_conn_res(struc device = ib_conn->device; ib_conn->login_buf =kmalloc (ISER_RX_LOGIN_SIZE ,GFP_KERNEL ); -if (!ib_conn->login_buf) { - goto alloc_err; - ret = -ENOMEM ; - } +if (!ib_conn->login_buf) + goto out_err; ib_conn->login_dma = ib_dma_map_single(ib_conn->device->ib_device, (void *)ib_conn->login_buf, ISER_RX_LOGIN_SIZE,
@@ -175,10 +173,9 @@ static int iser_create_ib_conn_res(struc ib_conn->page_vec =kmalloc (sizeof (struct iser_page_vec ) + (sizeof (u64) * (ISCSI_ISER_SG_TABLESIZE +1 )),GFP_KERNEL ); -if (!ib_conn->page_vec) { - ret = -ENOMEM ; - goto alloc_err; - } +if (!ib_conn->page_vec) + goto out_err; + ib_conn->page_vec->pages = (u64 *) (ib_conn->page_vec +1 ); params.page_shift =SHIFT_4K ;
@@ -198,7 +195,8 @@ static int iser_create_ib_conn_res(struc ib_conn->fmr_pool =ib_create_fmr_pool (device->pd, ¶ms);if (IS_ERR (ib_conn->fmr_pool)) { ret =PTR_ERR (ib_conn->fmr_pool); - goto fmr_pool_err; + ib_conn->fmr_pool =NULL ; + goto out_err; }memset (&init_attr,0 ,sizeof init_attr);
@@ -216,7 +214,7 @@ static int iser_create_ib_conn_res(struc ret =rdma_create_qp (ib_conn->cma_id, device->pd, &init_attr);if (ret) - goto qp_err; + goto out_err; ib_conn->qp = ib_conn->cma_id->qp; iser_err("setting conn %p cma_id %p: fmr_pool %p qp %p\n",
@@ -224,12 +222,7 @@ static int iser_create_ib_conn_res(struc ib_conn->fmr_pool, ib_conn->cma_id->qp);return ret; -qp_err: - (void )ib_destroy_fmr_pool (ib_conn->fmr_pool); -fmr_pool_err: -kfree (ib_conn->page_vec); -kfree (ib_conn->login_buf); -alloc_err: +out_err:iser_err ("unable to alloc mem or create resource, err %d\n" , ret);return ret; }