Re: [PATCH for-next] RDMA/rxe: Fix coding error in rxe_rcv_mcast_pkt

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

 



On Wed, Jan 27, 2021 at 10:23:53PM -0600, Bob Pearson wrote:
> On 1/27/21 9:53 PM, Bob Pearson wrote:
> > On 1/27/21 9:50 PM, Zhu Yanjun wrote:
> >> On Thu, Jan 28, 2021 at 9:12 AM Bob Pearson <rpearsonhpe@xxxxxxxxx> wrote:
> >>>
> >>> rxe_rcv_mcast_pkt() in rxe_recv.c can leak SKBs in error path
> >>> code. The loop over the QPs attached to a multicast group
> >>> creates new cloned SKBs for all but the last QP in the list
> >>> and passes the SKB and its clones to rxe_rcv_pkt() for further
> >>> processing. Any QPs that do not pass some checks are skipped.
> >>> If the last QP in the list fails the tests the SKB is leaked.
> >>> This patch checks if the SKB for the last QP was used and if
> >>> not frees it. Also removes a redundant loop invariant assignment.
> >>>
> >>> Fixes: 8700e3e7c4857 ("Soft RoCE driver")
> >>> Fixes: 71abf20b28ff8 ("RDMA/rxe: Handle skb_clone() failure in rxe_recv.c")
> >>> Signed-off-by: Bob Pearson <rpearson@xxxxxxx>
> >>> ---
> >>>  drivers/infiniband/sw/rxe/rxe_recv.c | 18 +++++++++++-------
> >>>  1 file changed, 11 insertions(+), 7 deletions(-)
> >>>
> >>> diff --git a/drivers/infiniband/sw/rxe/rxe_recv.c b/drivers/infiniband/sw/rxe/rxe_recv.c
> >>> index c9984a28eecc..57cc25e3b4ad 100644
> >>> --- a/drivers/infiniband/sw/rxe/rxe_recv.c
> >>> +++ b/drivers/infiniband/sw/rxe/rxe_recv.c
> >>> @@ -252,7 +252,6 @@ static void rxe_rcv_mcast_pkt(struct rxe_dev *rxe, struct sk_buff *skb)
> >>>
> >>>         list_for_each_entry(mce, &mcg->qp_list, qp_list) {
> >>>                 qp = mce->qp;
> >>> -               pkt = SKB_TO_PKT(skb);
> >>>
> >>>                 /* validate qp for incoming packet */
> >>>                 err = check_type_state(rxe, pkt, qp);
> >>> @@ -264,12 +263,18 @@ static void rxe_rcv_mcast_pkt(struct rxe_dev *rxe, struct sk_buff *skb)
> >>>                         continue;
> >>>
> >>>                 /* for all but the last qp create a new clone of the
> >>> -                * skb and pass to the qp.
> >>> +                * skb and pass to the qp. If an error occurs in the
> >>> +                * checks for the last qp in the list we need to
> >>> +                * free the skb since it hasn't been passed on to
> >>> +                * rxe_rcv_pkt() which would free it later.
> >>>                  */
> >>> -               if (mce->qp_list.next != &mcg->qp_list)
> >>> +               if (mce->qp_list.next != &mcg->qp_list) {
> >>>                         per_qp_skb = skb_clone(skb, GFP_ATOMIC);
> >>> -               else
> >>> +               } else {
> >>>                         per_qp_skb = skb;
> >>> +                       /* show we have consumed the skb */
> >>> +                       skb = NULL;
> >>> +               }
> >>>
> >>>                 if (unlikely(!per_qp_skb))
> >>>                         continue;
> >>> @@ -284,10 +289,9 @@ static void rxe_rcv_mcast_pkt(struct rxe_dev *rxe, struct sk_buff *skb)
> >>>
> >>>         rxe_drop_ref(mcg);      /* drop ref from rxe_pool_get_key. */
> >>>
> >>> -       return;
> >>> -
> >>>  err1:
> >>> -       kfree_skb(skb);
> >>> +       if (skb)
> >>> +               kfree_skb(skb);
> >>
> >> "if (skb)" is not needed here.
> >>
> >> The implemetation of kfree_skb:
> >>
> >> void kfree_skb(struct sk_buff *skb)
> >> {
> >> if (unlikely(!skb))
> >> return;
> >> if (likely(atomic_read(&skb->users) == 1))
> >> smp_rmb();
> >> else if (likely(!atomic_dec_and_test(&skb->users)))
> >> return;
> >> trace_kfree_skb(skb, __builtin_return_address(0));
> >> __kfree_skb(skb);
> >> }
> >>
> >> Zhu Yanjun
> >>>  }
> >>>
> >>>  /**
> >>> --
> >>> 2.27.0
> >>>
> > Agreed but the reason I wrote that was to make it obvious why I set skb to NULL above. But as long as it is clear without it I can remove the test.
> >
> Actually I should have written
>
> if (unlikely(skb))
> 	kfree_skb(skb);

Please don't put "if (a) kfree(a);" constructions unless you want to
deal with daily flux of patches with attempt to remove "if".

Thanks

>
>



[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Photo]     [Yosemite News]     [Yosemite Photos]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux