diff mbox series

[net,v3] net: allow skb_datagram_iter to be called from any context

Message ID 20240626070037.758538-1-sagi@grimberg.me (mailing list archive)
State Superseded
Delegated to: Netdev Maintainers
Headers show
Series [net,v3] net: allow skb_datagram_iter to be called from any context | expand

Checks

Context Check Description
netdev/series_format success Single patches do not need cover letters
netdev/tree_selection success Clearly marked for net
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present fail Series targets non-next tree, but doesn't contain any Fixes tags
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 859 this patch: 859
netdev/build_tools success No tools touched, skip
netdev/cc_maintainers warning 2 maintainers not CCed: pabeni@redhat.com brauner@kernel.org
netdev/build_clang success Errors and warnings before: 863 this patch: 863
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 863 this patch: 863
netdev/checkpatch warning CHECK: Alignment should match open parenthesis WARNING: line length of 82 exceeds 80 columns
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 8 this patch: 8
netdev/source_inline success Was 0 now: 0

Commit Message

Sagi Grimberg June 26, 2024, 7 a.m. UTC
We only use the mapping in a single context, so kmap_local is sufficient
and cheaper. Make sure to use skb_frag_foreach_page as skb frags may
contain highmem compound pages and we need to map page by page.

Reported-by: kernel test robot <oliver.sang@intel.com>
Closes: https://lore.kernel.org/oe-lkp/202406161539.b5ff7b20-oliver.sang@intel.com
Signed-off-by: Sagi Grimberg <sagi@grimberg.me>
---
Changes from v2:
- added a target tree in subject prefix
- added reported credits and closes annotation

Changes from v1:
- Fix usercopy BUG() due to copy from highmem pages across page boundary
  by using skb_frag_foreach_page

 net/core/datagram.c | 19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)

Comments

Eric Dumazet June 26, 2024, 7:40 a.m. UTC | #1
On Wed, Jun 26, 2024 at 9:00 AM Sagi Grimberg <sagi@grimberg.me> wrote:
>
> We only use the mapping in a single context, so kmap_local is sufficient
> and cheaper. Make sure to use skb_frag_foreach_page as skb frags may
> contain highmem compound pages and we need to map page by page.
>
> Reported-by: kernel test robot <oliver.sang@intel.com>
> Closes: https://lore.kernel.org/oe-lkp/202406161539.b5ff7b20-oliver.sang@intel.com
> Signed-off-by: Sagi Grimberg <sagi@grimberg.me>

Thanks for working on this !

A patch targeting net tree would need a Fixes: tag, so that stable
teams do not have
to do archeological digging to find which trees need this fix.

If the bug is too old, then maybe this patch should use kmap() instead
of  kmap_local_page() ?

Then in net-next, (after this fix is merged), perform the conversion
to kmap_local_page()

Fact that the bug never showed up is a bit strange, are 32bit systems
still used today ? (apart from bots)...

Do we have a reproducer to test this?

> ---
> Changes from v2:
> - added a target tree in subject prefix
> - added reported credits and closes annotation
>
> Changes from v1:
> - Fix usercopy BUG() due to copy from highmem pages across page boundary
>   by using skb_frag_foreach_page
>
>  net/core/datagram.c | 19 +++++++++++++------
>  1 file changed, 13 insertions(+), 6 deletions(-)
>
> diff --git a/net/core/datagram.c b/net/core/datagram.c
> index e614cfd8e14a..e9ba4c7b449d 100644
> --- a/net/core/datagram.c
> +++ b/net/core/datagram.c
> @@ -416,15 +416,22 @@ static int __skb_datagram_iter(const struct sk_buff *skb, int offset,
>
>                 end = start + skb_frag_size(frag);
>                 if ((copy = end - offset) > 0) {
> -                       struct page *page = skb_frag_page(frag);
> -                       u8 *vaddr = kmap(page);
> +                       u32 p_off, p_len, copied;
> +                       struct page *p;
> +                       u8 *vaddr;
>
>                         if (copy > len)
>                                 copy = len;
> -                       n = INDIRECT_CALL_1(cb, simple_copy_to_iter,
> -                                       vaddr + skb_frag_off(frag) + offset - start,
> -                                       copy, data, to);
> -                       kunmap(page);
> +
> +                       skb_frag_foreach_page(frag,
> +                                             skb_frag_off(frag) + offset - start,
> +                                             copy, p, p_off, p_len, copied) {
> +                               vaddr = kmap_local_page(p);
> +                               n = INDIRECT_CALL_1(cb, simple_copy_to_iter,
> +                                       vaddr + p_off, p_len, data, to);
> +                               kunmap_local(vaddr);
> +                       }
> +
>                         offset += n;
>                         if (n != copy)
>                                 goto short_copy;
> --
> 2.43.0
>
Sagi Grimberg June 26, 2024, 8:23 a.m. UTC | #2
On 26/06/2024 10:40, Eric Dumazet wrote:
> On Wed, Jun 26, 2024 at 9:00 AM Sagi Grimberg <sagi@grimberg.me> wrote:
>> We only use the mapping in a single context, so kmap_local is sufficient
>> and cheaper. Make sure to use skb_frag_foreach_page as skb frags may
>> contain highmem compound pages and we need to map page by page.
>>
>> Reported-by: kernel test robot <oliver.sang@intel.com>
>> Closes: https://lore.kernel.org/oe-lkp/202406161539.b5ff7b20-oliver.sang@intel.com
>> Signed-off-by: Sagi Grimberg <sagi@grimberg.me>
> Thanks for working on this !
>
> A patch targeting net tree would need a Fixes: tag, so that stable
> teams do not have
> to do archeological digging to find which trees need this fix.

The BUG complaint was exposed by the reverted patch in net-next.

TBH, its hard to tell when this actually was introduced, could skb_frags 
always
have contained high-order pages? or was this introduced with the 
introduction
of skb_copy_datagram_iter? or did it originate in the base implementation it
was copied from skb_copy_datagram_const_iovec?

Its hard for me to tell, and I don't have enough knowledge of the stack.
could use some help here.

>
> If the bug is too old, then maybe this patch should use kmap() instead
> of  kmap_local_page() ?

I honestly don't know.

>
> Then in net-next, (after this fix is merged), perform the conversion
> to kmap_local_page()
>
> Fact that the bug never showed up is a bit strange, are 32bit systems
> still used today ? (apart from bots)...

Not sure.

>
> Do we have a reproducer to test this?

Aside from the robot not that I know of...
Eric Dumazet June 26, 2024, 8:43 a.m. UTC | #3
On Wed, Jun 26, 2024 at 10:23 AM Sagi Grimberg <sagi@grimberg.me> wrote:
>
>
>
> On 26/06/2024 10:40, Eric Dumazet wrote:
> > On Wed, Jun 26, 2024 at 9:00 AM Sagi Grimberg <sagi@grimberg.me> wrote:
> >> We only use the mapping in a single context, so kmap_local is sufficient
> >> and cheaper. Make sure to use skb_frag_foreach_page as skb frags may
> >> contain highmem compound pages and we need to map page by page.
> >>
> >> Reported-by: kernel test robot <oliver.sang@intel.com>
> >> Closes: https://lore.kernel.org/oe-lkp/202406161539.b5ff7b20-oliver.sang@intel.com
> >> Signed-off-by: Sagi Grimberg <sagi@grimberg.me>
> > Thanks for working on this !
> >
> > A patch targeting net tree would need a Fixes: tag, so that stable
> > teams do not have
> > to do archeological digging to find which trees need this fix.
>
> The BUG complaint was exposed by the reverted patch in net-next.
>
> TBH, its hard to tell when this actually was introduced, could skb_frags
> always
> have contained high-order pages? or was this introduced with the
> introduction
> of skb_copy_datagram_iter? or did it originate in the base implementation it
> was copied from skb_copy_datagram_const_iovec?

OK, I will therefore suggest something like this (even if the older
bug might be exposed
by a more recent patch), to cover all kernels after 5.0

This was the commit adding __skb_datagram_iter(), not the bug.

Fixes: 950fcaecd5cc ("datagram: consolidate datagram copy to iter helpers")

I suspect high-order highmem pages were not used in older kernels anyway.
Matthew Wilcox June 27, 2024, 3:01 p.m. UTC | #4
On Wed, Jun 26, 2024 at 10:43:38AM +0200, Eric Dumazet wrote:
> On Wed, Jun 26, 2024 at 10:23 AM Sagi Grimberg <sagi@grimberg.me> wrote:
> >
> >
> >
> > On 26/06/2024 10:40, Eric Dumazet wrote:
> > > On Wed, Jun 26, 2024 at 9:00 AM Sagi Grimberg <sagi@grimberg.me> wrote:
> > >> We only use the mapping in a single context, so kmap_local is sufficient
> > >> and cheaper. Make sure to use skb_frag_foreach_page as skb frags may
> > >> contain highmem compound pages and we need to map page by page.
> > >>
> > >> Reported-by: kernel test robot <oliver.sang@intel.com>
> > >> Closes: https://lore.kernel.org/oe-lkp/202406161539.b5ff7b20-oliver.sang@intel.com
> > >> Signed-off-by: Sagi Grimberg <sagi@grimberg.me>
> > > Thanks for working on this !
> > >
> > > A patch targeting net tree would need a Fixes: tag, so that stable
> > > teams do not have
> > > to do archeological digging to find which trees need this fix.
> >
> > The BUG complaint was exposed by the reverted patch in net-next.
> >
> > TBH, its hard to tell when this actually was introduced, could skb_frags
> > always
> > have contained high-order pages? or was this introduced with the
> > introduction
> > of skb_copy_datagram_iter? or did it originate in the base implementation it
> > was copied from skb_copy_datagram_const_iovec?
> 
> OK, I will therefore suggest something like this (even if the older
> bug might be exposed
> by a more recent patch), to cover all kernels after 5.0
> 
> This was the commit adding __skb_datagram_iter(), not the bug.
> 
> Fixes: 950fcaecd5cc ("datagram: consolidate datagram copy to iter helpers")
> 
> I suspect high-order highmem pages were not used in older kernels anyway.

This explanation is slightly garbled.

High-order lowmem pages _also_ get caught by this check.  See my earlier
email explaining this.
diff mbox series

Patch

diff --git a/net/core/datagram.c b/net/core/datagram.c
index e614cfd8e14a..e9ba4c7b449d 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -416,15 +416,22 @@  static int __skb_datagram_iter(const struct sk_buff *skb, int offset,
 
 		end = start + skb_frag_size(frag);
 		if ((copy = end - offset) > 0) {
-			struct page *page = skb_frag_page(frag);
-			u8 *vaddr = kmap(page);
+			u32 p_off, p_len, copied;
+			struct page *p;
+			u8 *vaddr;
 
 			if (copy > len)
 				copy = len;
-			n = INDIRECT_CALL_1(cb, simple_copy_to_iter,
-					vaddr + skb_frag_off(frag) + offset - start,
-					copy, data, to);
-			kunmap(page);
+
+			skb_frag_foreach_page(frag,
+					      skb_frag_off(frag) + offset - start,
+					      copy, p, p_off, p_len, copied) {
+				vaddr = kmap_local_page(p);
+				n = INDIRECT_CALL_1(cb, simple_copy_to_iter,
+					vaddr + p_off, p_len, data, to);
+				kunmap_local(vaddr);
+			}
+
 			offset += n;
 			if (n != copy)
 				goto short_copy;