Re: [PATCH 5.4 185/658] xprtrdma: Fix regbuf data not freed in rpcrdma_req_create()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Jan 19, 2023 at 11:39:35AM +0530, Harshit Mogalapalli wrote:
> Hi,
> 
> On 16/01/23 9:14 pm, Greg Kroah-Hartman wrote:
> > From: Zhang Xiaoxu <zhangxiaoxu5@xxxxxxxxxx>
> > 
> > [ Upstream commit 9181f40fb2952fd59ecb75e7158620c9c669eee3 ]
> > 
> > If rdma receive buffer allocate failed, should call rpcrdma_regbuf_free()
> > to free the send buffer, otherwise, the buffer data will be leaked.
> > 
> > Fixes: bb93a1ae2bf4 ("xprtrdma: Allocate req's regbufs at xprt create time")
> > Signed-off-by: Zhang Xiaoxu <zhangxiaoxu5@xxxxxxxxxx>
> > Signed-off-by: Trond Myklebust <trond.myklebust@xxxxxxxxxxxxxxx>
> > Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>
> > ---
> >   net/sunrpc/xprtrdma/verbs.c | 1 +
> >   1 file changed, 1 insertion(+)
> > 
> > diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c
> > index 0f4d39fdb48f..e13115bbe719 100644
> > --- a/net/sunrpc/xprtrdma/verbs.c
> > +++ b/net/sunrpc/xprtrdma/verbs.c
> > @@ -1037,6 +1037,7 @@ struct rpcrdma_req *rpcrdma_req_create(struct rpcrdma_xprt *r_xprt, size_t size,
> >   	kfree(req->rl_sendbuf);
> >   out3:
> >   	kfree(req->rl_rdmabuf);
> > +	rpcrdma_regbuf_free(req->rl_sendbuf);
> 
> I think this introduces a double free in rpcrdma_req_create() [5.4.y]
> 
> Copying the function from 5.4.229 post the above patch here.
> 
> Comments added with //// marker.
> 
> struct rpcrdma_req *rpcrdma_req_create(struct rpcrdma_xprt *r_xprt, size_t
> size,
>                                        gfp_t flags)
> {
>         struct rpcrdma_buffer *buffer = &r_xprt->rx_buf;
>         struct rpcrdma_regbuf *rb;
>         struct rpcrdma_req *req;
>         size_t maxhdrsize;
> 
>         req = kzalloc(sizeof(*req), flags);
>         if (req == NULL)
>                 goto out1;
> 
>         /* Compute maximum header buffer size in bytes */
>         maxhdrsize = rpcrdma_fixed_maxsz + 3 +
>                      r_xprt->rx_ia.ri_max_segs * rpcrdma_readchunk_maxsz;
>         maxhdrsize *= sizeof(__be32);
>         rb = rpcrdma_regbuf_alloc(__roundup_pow_of_two(maxhdrsize),
>                                   DMA_TO_DEVICE, flags);
>         if (!rb)
>                 goto out2;
>         req->rl_rdmabuf = rb;
>         xdr_buf_init(&req->rl_hdrbuf, rdmab_data(rb), rdmab_length(rb));
> 
>         req->rl_sendbuf = rpcrdma_regbuf_alloc(size, DMA_TO_DEVICE, flags);
>         if (!req->rl_sendbuf)
>                 goto out3;
> 
>         req->rl_recvbuf = rpcrdma_regbuf_alloc(size, DMA_NONE, flags);
>         if (!req->rl_recvbuf)
>                 goto out4; ///// let us say we hit this.
> 
>         INIT_LIST_HEAD(&req->rl_free_mrs);
>         INIT_LIST_HEAD(&req->rl_registered);
>         spin_lock(&buffer->rb_lock);
>         list_add(&req->rl_all, &buffer->rb_allreqs);
>         spin_unlock(&buffer->rb_lock);
>         return req;
> 
> out4:
>         kfree(req->rl_sendbuf);
> //// free of (req->rl_sendbuf)
> out3:
>         kfree(req->rl_rdmabuf);
>         rpcrdma_regbuf_free(req->rl_sendbuf);
> //// double free of req->rl_sendbuf, we have a kfree in rpcrdma_regbuf_free.
> 
> out2:
>         kfree(req);
> out1:
>         return NULL;
> }
> 
> Found using smatch.
> 
> I looked at the history of the function, the reason is that we don't have
> commit b78de1dca00376aaba7a58bb5fe21c1606524abe in 5.4.y
> 
> This problem is only in 5.4.y not seen in newer LTS.
> 
> Please correct me if I am missing something here.
> 

I think you are correct.  I'll look into fixing it on Monday, thanks for
the review!

greg k-h



[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux