2022-01-26 07:25:46

by Dan Aloni

[permalink] [raw]
Subject: [PATCH] xrpcrdma: add missing error checks in rpcrdma_ep_destroy

These pointers can be non-NULL and contain errors if initialization is
aborted early. This is similar to how `__svc_rdma_free` takes care of
it.

Signed-off-by: Dan Aloni <[email protected]>
---
net/sunrpc/xprtrdma/verbs.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c
index f172d1298013..7f3173073e72 100644
--- a/net/sunrpc/xprtrdma/verbs.c
+++ b/net/sunrpc/xprtrdma/verbs.c
@@ -336,14 +336,14 @@ static void rpcrdma_ep_destroy(struct kref *kref)
ep->re_id->qp = NULL;
}

- if (ep->re_attr.recv_cq)
+ if (ep->re_attr.recv_cq && !IS_ERR(ep->re_attr.recv_cq))
ib_free_cq(ep->re_attr.recv_cq);
ep->re_attr.recv_cq = NULL;
- if (ep->re_attr.send_cq)
+ if (ep->re_attr.send_cq && !IS_ERR(ep->re_attr.send_cq))
ib_free_cq(ep->re_attr.send_cq);
ep->re_attr.send_cq = NULL;

- if (ep->re_pd)
+ if (ep->re_pd && !IS_ERR(ep->re_pd))
ib_dealloc_pd(ep->re_pd);
ep->re_pd = NULL;

--
2.23.0


2022-01-26 08:05:52

by Chuck Lever

[permalink] [raw]
Subject: Re: [PATCH] xrpcrdma: add missing error checks in rpcrdma_ep_destroy



> On Jan 25, 2022, at 2:17 PM, Dan Aloni <[email protected]> wrote:
>
> These pointers can be non-NULL and contain errors if initialization is
> aborted early. This is similar to how `__svc_rdma_free` takes care of
> it.

IIUC the only place that can set these values to an
ERR_PTR is rpcrdma_ep_create() ? I think I'd rather
have rpcrdma_ep_create() set the fields to NULL in
the error cases.

Good catch. I'm afraid to ask how you found this.

> Signed-off-by: Dan Aloni <[email protected]>
> ---
> net/sunrpc/xprtrdma/verbs.c | 6 +++---
> 1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c
> index f172d1298013..7f3173073e72 100644
> --- a/net/sunrpc/xprtrdma/verbs.c
> +++ b/net/sunrpc/xprtrdma/verbs.c
> @@ -336,14 +336,14 @@ static void rpcrdma_ep_destroy(struct kref *kref)
> ep->re_id->qp = NULL;
> }
>
> - if (ep->re_attr.recv_cq)
> + if (ep->re_attr.recv_cq && !IS_ERR(ep->re_attr.recv_cq))
> ib_free_cq(ep->re_attr.recv_cq);
> ep->re_attr.recv_cq = NULL;
> - if (ep->re_attr.send_cq)
> + if (ep->re_attr.send_cq && !IS_ERR(ep->re_attr.send_cq))
> ib_free_cq(ep->re_attr.send_cq);
> ep->re_attr.send_cq = NULL;
>
> - if (ep->re_pd)
> + if (ep->re_pd && !IS_ERR(ep->re_pd))
> ib_dealloc_pd(ep->re_pd);
> ep->re_pd = NULL;
>
> --
> 2.23.0
>

--
Chuck Lever



2022-01-26 08:32:04

by Dan Aloni

[permalink] [raw]
Subject: Re: [PATCH] xrpcrdma: add missing error checks in rpcrdma_ep_destroy

On Tue, Jan 25, 2022 at 07:30:05PM +0000, Chuck Lever III wrote:
>
>
> > On Jan 25, 2022, at 2:17 PM, Dan Aloni <[email protected]> wrote:
> >
> > These pointers can be non-NULL and contain errors if initialization is
> > aborted early. This is similar to how `__svc_rdma_free` takes care of
> > it.
>
> IIUC the only place that can set these values to an
> ERR_PTR is rpcrdma_ep_create() ? I think I'd rather
> have rpcrdma_ep_create() set the fields to NULL in
> the error cases.

Actually that was my initialization draft but then I saw
`__svc_rdma_free`. Will send over.

> Good catch. I'm afraid to ask how you found this.

Just some adapter entering error state in firmware.

--
Dan Aloni

2022-01-26 09:04:45

by Dan Aloni

[permalink] [raw]
Subject: [PATCH] xprtrdma: fix pointer derefs in error cases of rpcrdma_ep_create

If there are failures then we must not leave the non-NULL pointers with
the error value, otherwise `rpcrdma_ep_destroy` gets confused and tries
free them, resulting in an Oops.

Signed-off-by: Dan Aloni <[email protected]>
---
net/sunrpc/xprtrdma/verbs.c | 3 +++
1 file changed, 3 insertions(+)

diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c
index 3d3673ba9e1e..2a2e1514ac79 100644
--- a/net/sunrpc/xprtrdma/verbs.c
+++ b/net/sunrpc/xprtrdma/verbs.c
@@ -436,6 +436,7 @@ static int rpcrdma_ep_create(struct rpcrdma_xprt *r_xprt)
IB_POLL_WORKQUEUE);
if (IS_ERR(ep->re_attr.send_cq)) {
rc = PTR_ERR(ep->re_attr.send_cq);
+ ep->re_attr.send_cq = NULL;
goto out_destroy;
}

@@ -444,6 +445,7 @@ static int rpcrdma_ep_create(struct rpcrdma_xprt *r_xprt)
IB_POLL_WORKQUEUE);
if (IS_ERR(ep->re_attr.recv_cq)) {
rc = PTR_ERR(ep->re_attr.recv_cq);
+ ep->re_attr.recv_cq = NULL;
goto out_destroy;
}
ep->re_receive_count = 0;
@@ -482,6 +484,7 @@ static int rpcrdma_ep_create(struct rpcrdma_xprt *r_xprt)
ep->re_pd = ib_alloc_pd(device, 0);
if (IS_ERR(ep->re_pd)) {
rc = PTR_ERR(ep->re_pd);
+ ep->re_pd = NULL;
goto out_destroy;
}

--
2.23.0

2022-01-26 09:05:25

by Chuck Lever

[permalink] [raw]
Subject: Re: [PATCH] xprtrdma: fix pointer derefs in error cases of rpcrdma_ep_create

Hi Anna-

> On Jan 25, 2022, at 3:06 PM, Dan Aloni <[email protected]> wrote:
>
> If there are failures then we must not leave the non-NULL pointers with
> the error value, otherwise `rpcrdma_ep_destroy` gets confused and tries
> free them, resulting in an Oops.
>
> Signed-off-by: Dan Aloni <[email protected]>

Acked-by: Chuck Lever <[email protected]>


> ---
> net/sunrpc/xprtrdma/verbs.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c
> index 3d3673ba9e1e..2a2e1514ac79 100644
> --- a/net/sunrpc/xprtrdma/verbs.c
> +++ b/net/sunrpc/xprtrdma/verbs.c
> @@ -436,6 +436,7 @@ static int rpcrdma_ep_create(struct rpcrdma_xprt *r_xprt)
> IB_POLL_WORKQUEUE);
> if (IS_ERR(ep->re_attr.send_cq)) {
> rc = PTR_ERR(ep->re_attr.send_cq);
> + ep->re_attr.send_cq = NULL;
> goto out_destroy;
> }
>
> @@ -444,6 +445,7 @@ static int rpcrdma_ep_create(struct rpcrdma_xprt *r_xprt)
> IB_POLL_WORKQUEUE);
> if (IS_ERR(ep->re_attr.recv_cq)) {
> rc = PTR_ERR(ep->re_attr.recv_cq);
> + ep->re_attr.recv_cq = NULL;
> goto out_destroy;
> }
> ep->re_receive_count = 0;
> @@ -482,6 +484,7 @@ static int rpcrdma_ep_create(struct rpcrdma_xprt *r_xprt)
> ep->re_pd = ib_alloc_pd(device, 0);
> if (IS_ERR(ep->re_pd)) {
> rc = PTR_ERR(ep->re_pd);
> + ep->re_pd = NULL;
> goto out_destroy;
> }
>
> --
> 2.23.0
>

--
Chuck Lever