* [PATCH v3 1/1] xdp: avoid calling kfree twice @ 2020-12-11 4:26 Zhu Yanjun 2020-12-10 23:11 ` Daniel Borkmann 0 siblings, 1 reply; 3+ messages in thread From: Zhu Yanjun @ 2020-12-11 4:26 UTC (permalink / raw) To: zyjzyj2000, bjorn.topel, magnus.karlsson, netdev, jonathan.lemon Cc: Zhu Yanjun, Ye Dong In the function xdp_umem_pin_pages, if npgs != umem->npgs and npgs >= 0, the function xdp_umem_unpin_pages is called. In this function, kfree is called to handle umem->pgs, and then in the function xdp_umem_pin_pages, kfree is called again to handle umem->pgs. Eventually, to umem->pgs, kfree is called twice. Since umem->pgs is set to NULL after the first kfree, the second kfree would not trigger call trace. Fixes: c0c77d8fb787 ("xsk: add user memory registration support sockopt") CC: Ye Dong <dong.ye@intel.com> Acked-by: Björn Töpel <bjorn.topel@intel.com> Signed-off-by: Zhu Yanjun <yanjun.zhu@intel.com> --- net/xdp/xdp_umem.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/net/xdp/xdp_umem.c b/net/xdp/xdp_umem.c index 56a28a686988..01b31c56cead 100644 --- a/net/xdp/xdp_umem.c +++ b/net/xdp/xdp_umem.c @@ -97,7 +97,6 @@ static int xdp_umem_pin_pages(struct xdp_umem *umem, unsigned long address) { unsigned int gup_flags = FOLL_WRITE; long npgs; - int err; umem->pgs = kcalloc(umem->npgs, sizeof(*umem->pgs), GFP_KERNEL | __GFP_NOWARN); @@ -112,20 +111,14 @@ static int xdp_umem_pin_pages(struct xdp_umem *umem, unsigned long address) if (npgs != umem->npgs) { if (npgs >= 0) { umem->npgs = npgs; - err = -ENOMEM; - goto out_pin; + xdp_umem_unpin_pages(umem); + return -ENOMEM; } - err = npgs; - goto out_pgs; + kfree(umem->pgs); + umem->pgs = NULL; + return (int)npgs; } return 0; - -out_pin: - xdp_umem_unpin_pages(umem); -out_pgs: - kfree(umem->pgs); - umem->pgs = NULL; - return err; } static int xdp_umem_account_pages(struct xdp_umem *umem) -- 2.18.4 ^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH v3 1/1] xdp: avoid calling kfree twice 2020-12-11 4:26 [PATCH v3 1/1] xdp: avoid calling kfree twice Zhu Yanjun @ 2020-12-10 23:11 ` Daniel Borkmann 2020-12-12 5:36 ` Rain River 0 siblings, 1 reply; 3+ messages in thread From: Daniel Borkmann @ 2020-12-10 23:11 UTC (permalink / raw) To: Zhu Yanjun, zyjzyj2000, bjorn.topel, magnus.karlsson, netdev, jonathan.lemon Cc: Ye Dong On 12/11/20 5:26 AM, Zhu Yanjun wrote: > In the function xdp_umem_pin_pages, if npgs != umem->npgs and > npgs >= 0, the function xdp_umem_unpin_pages is called. In this > function, kfree is called to handle umem->pgs, and then in the > function xdp_umem_pin_pages, kfree is called again to handle > umem->pgs. Eventually, to umem->pgs, kfree is called twice. > > Since umem->pgs is set to NULL after the first kfree, the second > kfree would not trigger call trace. This can still be misinterpreted imho; maybe lets simplify, for example: [bpf-next] xdp: avoid unnecessary second call to kfree For the case when in xdp_umem_pin_pages() the call to pin_user_pages() wasn't able to pin all the requested number of pages in memory (but some) then we error out by cleaning up the ones that got pinned through a call to xdp_umem_unpin_pages() and later on we free kfree(umem->pgs) itself. This is unneeded since xdp_umem_unpin_pages() itself already does the kfree(umem->pgs) internally with subsequent setting umem->pgs to NULL, so that in xdp_umem_pin_pages() the second kfree(umem->pgs) becomes entirely unnecessary for this case. Therefore, clean the error handling up. > Fixes: c0c77d8fb787 ("xsk: add user memory registration support sockopt") Why do we need a Fixes tag here? It's a _cleanup_, not a bug/fix technically. > CC: Ye Dong <dong.ye@intel.com> > Acked-by: Björn Töpel <bjorn.topel@intel.com> > Signed-off-by: Zhu Yanjun <yanjun.zhu@intel.com> > --- > net/xdp/xdp_umem.c | 17 +++++------------ > 1 file changed, 5 insertions(+), 12 deletions(-) > > diff --git a/net/xdp/xdp_umem.c b/net/xdp/xdp_umem.c > index 56a28a686988..01b31c56cead 100644 > --- a/net/xdp/xdp_umem.c > +++ b/net/xdp/xdp_umem.c > @@ -97,7 +97,6 @@ static int xdp_umem_pin_pages(struct xdp_umem *umem, unsigned long address) > { > unsigned int gup_flags = FOLL_WRITE; > long npgs; > - int err; > > umem->pgs = kcalloc(umem->npgs, sizeof(*umem->pgs), > GFP_KERNEL | __GFP_NOWARN); > @@ -112,20 +111,14 @@ static int xdp_umem_pin_pages(struct xdp_umem *umem, unsigned long address) > if (npgs != umem->npgs) { > if (npgs >= 0) { > umem->npgs = npgs; > - err = -ENOMEM; > - goto out_pin; > + xdp_umem_unpin_pages(umem); > + return -ENOMEM; > } > - err = npgs; > - goto out_pgs; > + kfree(umem->pgs); > + umem->pgs = NULL; > + return (int)npgs; > } > return 0; > - > -out_pin: > - xdp_umem_unpin_pages(umem); > -out_pgs: > - kfree(umem->pgs); > - umem->pgs = NULL; > - return err; > } > > static int xdp_umem_account_pages(struct xdp_umem *umem) > While at it, maybe we could also simplify the if (npgs != umem->npgs) a bit to get rid of the indent, something like: diff --git a/net/xdp/xdp_umem.c b/net/xdp/xdp_umem.c index 56a28a686988..fa4dd16cced5 100644 --- a/net/xdp/xdp_umem.c +++ b/net/xdp/xdp_umem.c @@ -97,7 +97,6 @@ static int xdp_umem_pin_pages(struct xdp_umem *umem, unsigned long address) { unsigned int gup_flags = FOLL_WRITE; long npgs; - int err; umem->pgs = kcalloc(umem->npgs, sizeof(*umem->pgs), GFP_KERNEL | __GFP_NOWARN); @@ -108,24 +107,17 @@ static int xdp_umem_pin_pages(struct xdp_umem *umem, unsigned long address) npgs = pin_user_pages(address, umem->npgs, gup_flags | FOLL_LONGTERM, &umem->pgs[0], NULL); mmap_read_unlock(current->mm); - - if (npgs != umem->npgs) { - if (npgs >= 0) { - umem->npgs = npgs; - err = -ENOMEM; - goto out_pin; - } - err = npgs; - goto out_pgs; + if (npgs == umem->npgs) + return 0; + if (npgs >= 0) { + umem->npgs = npgs; + xdp_umem_unpin_pages(umem); + return -ENOMEM; } - return 0; -out_pin: - xdp_umem_unpin_pages(umem); -out_pgs: kfree(umem->pgs); umem->pgs = NULL; - return err; + return npgs; } static int xdp_umem_account_pages(struct xdp_umem *umem) ^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH v3 1/1] xdp: avoid calling kfree twice 2020-12-10 23:11 ` Daniel Borkmann @ 2020-12-12 5:36 ` Rain River 0 siblings, 0 replies; 3+ messages in thread From: Rain River @ 2020-12-12 5:36 UTC (permalink / raw) To: Daniel Borkmann Cc: Zhu Yanjun, zyjzyj2000, bjorn.topel, magnus.karlsson, netdev, jonathan.lemon, Ye Dong On Fri, Dec 11, 2020 at 11:53 PM Daniel Borkmann <daniel@iogearbox.net> wrote: > > On 12/11/20 5:26 AM, Zhu Yanjun wrote: > > In the function xdp_umem_pin_pages, if npgs != umem->npgs and > > npgs >= 0, the function xdp_umem_unpin_pages is called. In this > > function, kfree is called to handle umem->pgs, and then in the > > function xdp_umem_pin_pages, kfree is called again to handle > > umem->pgs. Eventually, to umem->pgs, kfree is called twice. > > > > Since umem->pgs is set to NULL after the first kfree, the second > > kfree would not trigger call trace. > > This can still be misinterpreted imho; maybe lets simplify, for example: > > [bpf-next] xdp: avoid unnecessary second call to kfree > > For the case when in xdp_umem_pin_pages() the call to pin_user_pages() > wasn't able to pin all the requested number of pages in memory (but some) > then we error out by cleaning up the ones that got pinned through a call > to xdp_umem_unpin_pages() and later on we free kfree(umem->pgs) itself. > > This is unneeded since xdp_umem_unpin_pages() itself already does the > kfree(umem->pgs) internally with subsequent setting umem->pgs to NULL, so > that in xdp_umem_pin_pages() the second kfree(umem->pgs) becomes entirely > unnecessary for this case. Therefore, clean the error handling up. > > > Fixes: c0c77d8fb787 ("xsk: add user memory registration support sockopt") > > Why do we need a Fixes tag here? It's a _cleanup_, not a bug/fix technically. > > > CC: Ye Dong <dong.ye@intel.com> > > Acked-by: Björn Töpel <bjorn.topel@intel.com> > > Signed-off-by: Zhu Yanjun <yanjun.zhu@intel.com> > > --- > > net/xdp/xdp_umem.c | 17 +++++------------ > > 1 file changed, 5 insertions(+), 12 deletions(-) > > > > diff --git a/net/xdp/xdp_umem.c b/net/xdp/xdp_umem.c > > index 56a28a686988..01b31c56cead 100644 > > --- a/net/xdp/xdp_umem.c > > +++ b/net/xdp/xdp_umem.c > > @@ -97,7 +97,6 @@ static int xdp_umem_pin_pages(struct xdp_umem *umem, unsigned long address) > > { > > unsigned int gup_flags = FOLL_WRITE; > > long npgs; > > - int err; > > > > umem->pgs = kcalloc(umem->npgs, sizeof(*umem->pgs), > > GFP_KERNEL | __GFP_NOWARN); > > @@ -112,20 +111,14 @@ static int xdp_umem_pin_pages(struct xdp_umem *umem, unsigned long address) > > if (npgs != umem->npgs) { > > if (npgs >= 0) { > > umem->npgs = npgs; > > - err = -ENOMEM; > > - goto out_pin; > > + xdp_umem_unpin_pages(umem); > > + return -ENOMEM; > > } > > - err = npgs; > > - goto out_pgs; > > + kfree(umem->pgs); > > + umem->pgs = NULL; > > + return (int)npgs; > > } > > return 0; > > - > > -out_pin: > > - xdp_umem_unpin_pages(umem); > > -out_pgs: > > - kfree(umem->pgs); > > - umem->pgs = NULL; > > - return err; > > } > > > > static int xdp_umem_account_pages(struct xdp_umem *umem) > > > > While at it, maybe we could also simplify the if (npgs != umem->npgs) a bit to > get rid of the indent, something like: The original patch is just to make some cleanups. Please do not make it so complicated. If you like it, please file an official patch for code review. > > diff --git a/net/xdp/xdp_umem.c b/net/xdp/xdp_umem.c > index 56a28a686988..fa4dd16cced5 100644 > --- a/net/xdp/xdp_umem.c > +++ b/net/xdp/xdp_umem.c > @@ -97,7 +97,6 @@ static int xdp_umem_pin_pages(struct xdp_umem *umem, unsigned long address) > { > unsigned int gup_flags = FOLL_WRITE; > long npgs; > - int err; > > umem->pgs = kcalloc(umem->npgs, sizeof(*umem->pgs), > GFP_KERNEL | __GFP_NOWARN); > @@ -108,24 +107,17 @@ static int xdp_umem_pin_pages(struct xdp_umem *umem, unsigned long address) > npgs = pin_user_pages(address, umem->npgs, > gup_flags | FOLL_LONGTERM, &umem->pgs[0], NULL); > mmap_read_unlock(current->mm); > - > - if (npgs != umem->npgs) { > - if (npgs >= 0) { > - umem->npgs = npgs; > - err = -ENOMEM; > - goto out_pin; > - } > - err = npgs; > - goto out_pgs; > + if (npgs == umem->npgs) > + return 0; > + if (npgs >= 0) { > + umem->npgs = npgs; > + xdp_umem_unpin_pages(umem); > + return -ENOMEM; > } > - return 0; > > -out_pin: > - xdp_umem_unpin_pages(umem); > -out_pgs: > kfree(umem->pgs); > umem->pgs = NULL; > - return err; > + return npgs; > } > > static int xdp_umem_account_pages(struct xdp_umem *umem) ^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2020-12-12 5:38 UTC | newest] Thread overview: 3+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2020-12-11 4:26 [PATCH v3 1/1] xdp: avoid calling kfree twice Zhu Yanjun 2020-12-10 23:11 ` Daniel Borkmann 2020-12-12 5:36 ` Rain River
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).