diff mbox series

[v3,net-next,3/5] net: add skb_set_owner_edemux() helper

Message ID 20241010174817.1543642-4-edumazet@google.com (mailing list archive)
State Accepted
Commit 5ced52fa8f0dc23adb067f7b8a009a5ee051efb7
Delegated to: Netdev Maintainers
Headers show
Series tcp: add skb->sk to more control packets | expand

Checks

Context Check Description
netdev/series_format success Posting correctly formatted
netdev/tree_selection success Clearly marked for net-next, async
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 19 this patch: 19
netdev/build_tools success Errors and warnings before: 0 (+1) this patch: 0 (+1)
netdev/cc_maintainers warning 2 maintainers not CCed: dsahern@kernel.org willemb@google.com
netdev/build_clang success Errors and warnings before: 39 this patch: 39
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: 2620 this patch: 2620
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 40 lines checked
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 14 this patch: 14
netdev/source_inline success Was 0 now: 0
netdev/contest success net-next-2024-10-12--12-00 (tests: 777)

Commit Message

Eric Dumazet Oct. 10, 2024, 5:48 p.m. UTC
This can be used to attach a socket to an skb,
taking a reference on sk->sk_refcnt.

This helper might be a NOP if sk->sk_refcnt is zero.

Use it from tcp_make_synack().

Signed-off-by: Eric Dumazet <edumazet@google.com>
---
 include/net/sock.h    | 9 +++++++++
 net/core/sock.c       | 9 +++------
 net/ipv4/tcp_output.c | 2 +-
 3 files changed, 13 insertions(+), 7 deletions(-)

Comments

Kuniyuki Iwashima Oct. 11, 2024, 11:29 p.m. UTC | #1
From: Eric Dumazet <edumazet@google.com>
Date: Thu, 10 Oct 2024 17:48:15 +0000
> This can be used to attach a socket to an skb,
> taking a reference on sk->sk_refcnt.
> 
> This helper might be a NOP if sk->sk_refcnt is zero.
> 
> Use it from tcp_make_synack().
> 
> Signed-off-by: Eric Dumazet <edumazet@google.com>

Reviewed-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Brian Vazquez Oct. 14, 2024, 2:20 p.m. UTC | #2
On Thu, Oct 10, 2024 at 1:48 PM Eric Dumazet <edumazet@google.com> wrote:
>
> This can be used to attach a socket to an skb,
> taking a reference on sk->sk_refcnt.
>
> This helper might be a NOP if sk->sk_refcnt is zero.
>
> Use it from tcp_make_synack().
>
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> ---
>  include/net/sock.h    | 9 +++++++++
>  net/core/sock.c       | 9 +++------
>  net/ipv4/tcp_output.c | 2 +-
>  3 files changed, 13 insertions(+), 7 deletions(-)
>
> diff --git a/include/net/sock.h b/include/net/sock.h
> index 703ec6aef927337f7ca6798ff3c3970529af53f9..e5bb64ad92c769f3edb8c2dc72cafb336837cabb 100644
> --- a/include/net/sock.h
> +++ b/include/net/sock.h
> @@ -1758,6 +1758,15 @@ void sock_efree(struct sk_buff *skb);
>  #ifdef CONFIG_INET
>  void sock_edemux(struct sk_buff *skb);
>  void sock_pfree(struct sk_buff *skb);
> +
> +static inline void skb_set_owner_edemux(struct sk_buff *skb, struct sock *sk)
> +{
> +       skb_orphan(skb);

Is this skb_orphan(skb) needed? IIUC skb_set_owner_w is doing
skb_orphan too? and then calling this helper, but we do need the
skb_orphan is needed when called from the synack.

Can skb_set_owner_w try to orphan an skb twice?


> +       if (refcount_inc_not_zero(&sk->sk_refcnt)) {
> +               skb->sk = sk;
> +               skb->destructor = sock_edemux;
> +       }
> +}
>  #else
>  #define sock_edemux sock_efree
>  #endif
> diff --git a/net/core/sock.c b/net/core/sock.c
> index 083d438d8b6faff60e2e3cf1f982eb306a923cf7..f8c0d4eda888cf190b87fb42e94eef4fb950bf1f 100644
> --- a/net/core/sock.c
> +++ b/net/core/sock.c
> @@ -2592,14 +2592,11 @@ void __sock_wfree(struct sk_buff *skb)
>  void skb_set_owner_w(struct sk_buff *skb, struct sock *sk)
>  {
>         skb_orphan(skb);
> -       skb->sk = sk;
>  #ifdef CONFIG_INET
> -       if (unlikely(!sk_fullsock(sk))) {
> -               skb->destructor = sock_edemux;
> -               sock_hold(sk);
> -               return;
> -       }
> +       if (unlikely(!sk_fullsock(sk)))
> +               return skb_set_owner_edemux(skb, sk);
>  #endif
> +       skb->sk = sk;
>         skb->destructor = sock_wfree;
>         skb_set_hash_from_sk(skb, sk);
>         /*
> diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
> index 1251510f0e58da6b6403d2097b498f3e4cb6d255..4cf64ed13609fdcb72b3858ca9e20a1e65bd3d94 100644
> --- a/net/ipv4/tcp_output.c
> +++ b/net/ipv4/tcp_output.c
> @@ -3731,7 +3731,7 @@ struct sk_buff *tcp_make_synack(const struct sock *sk, struct dst_entry *dst,
>
>         switch (synack_type) {
>         case TCP_SYNACK_NORMAL:
> -               skb_set_owner_w(skb, req_to_sk(req));
> +               skb_set_owner_edemux(skb, req_to_sk(req));
>                 break;
>         case TCP_SYNACK_COOKIE:
>                 /* Under synflood, we do not attach skb to a socket,
> --
> 2.47.0.rc1.288.g06298d1525-goog
>
Eric Dumazet Oct. 14, 2024, 2:23 p.m. UTC | #3
On Mon, Oct 14, 2024 at 4:20 PM Brian Vazquez <brianvv@google.com> wrote:
>
> On Thu, Oct 10, 2024 at 1:48 PM Eric Dumazet <edumazet@google.com> wrote:
> >
> > This can be used to attach a socket to an skb,
> > taking a reference on sk->sk_refcnt.
> >
> > This helper might be a NOP if sk->sk_refcnt is zero.
> >
> > Use it from tcp_make_synack().
> >
> > Signed-off-by: Eric Dumazet <edumazet@google.com>
> > ---
> >  include/net/sock.h    | 9 +++++++++
> >  net/core/sock.c       | 9 +++------
> >  net/ipv4/tcp_output.c | 2 +-
> >  3 files changed, 13 insertions(+), 7 deletions(-)
> >
> > diff --git a/include/net/sock.h b/include/net/sock.h
> > index 703ec6aef927337f7ca6798ff3c3970529af53f9..e5bb64ad92c769f3edb8c2dc72cafb336837cabb 100644
> > --- a/include/net/sock.h
> > +++ b/include/net/sock.h
> > @@ -1758,6 +1758,15 @@ void sock_efree(struct sk_buff *skb);
> >  #ifdef CONFIG_INET
> >  void sock_edemux(struct sk_buff *skb);
> >  void sock_pfree(struct sk_buff *skb);
> > +
> > +static inline void skb_set_owner_edemux(struct sk_buff *skb, struct sock *sk)
> > +{
> > +       skb_orphan(skb);
>
> Is this skb_orphan(skb) needed? IIUC skb_set_owner_w is doing
> skb_orphan too? and then calling this helper, but we do need the
> skb_orphan is needed when called from the synack.
>
> Can skb_set_owner_w try to orphan an skb twice?
>

skb_orphan(skb) does nothing if there is nothing to do.

It is common practice to include it every time we are about to change
skb->destructor.

Otherwise we would have to add a WARN() or something to prevent future leaks.

Better safe than sorry :)
Brian Vazquez Oct. 14, 2024, 2:34 p.m. UTC | #4
Thanks a lot for the explanation, it makes sense.

Reviewed-by: Brian Vazquez <brianvv@google.com>

On Mon, Oct 14, 2024 at 10:23 AM Eric Dumazet <edumazet@google.com> wrote:
>
> On Mon, Oct 14, 2024 at 4:20 PM Brian Vazquez <brianvv@google.com> wrote:
> >
> > On Thu, Oct 10, 2024 at 1:48 PM Eric Dumazet <edumazet@google.com> wrote:
> > >
> > > This can be used to attach a socket to an skb,
> > > taking a reference on sk->sk_refcnt.
> > >
> > > This helper might be a NOP if sk->sk_refcnt is zero.
> > >
> > > Use it from tcp_make_synack().
> > >
> > > Signed-off-by: Eric Dumazet <edumazet@google.com>
> > > ---
> > >  include/net/sock.h    | 9 +++++++++
> > >  net/core/sock.c       | 9 +++------
> > >  net/ipv4/tcp_output.c | 2 +-
> > >  3 files changed, 13 insertions(+), 7 deletions(-)
> > >
> > > diff --git a/include/net/sock.h b/include/net/sock.h
> > > index 703ec6aef927337f7ca6798ff3c3970529af53f9..e5bb64ad92c769f3edb8c2dc72cafb336837cabb 100644
> > > --- a/include/net/sock.h
> > > +++ b/include/net/sock.h
> > > @@ -1758,6 +1758,15 @@ void sock_efree(struct sk_buff *skb);
> > >  #ifdef CONFIG_INET
> > >  void sock_edemux(struct sk_buff *skb);
> > >  void sock_pfree(struct sk_buff *skb);
> > > +
> > > +static inline void skb_set_owner_edemux(struct sk_buff *skb, struct sock *sk)
> > > +{
> > > +       skb_orphan(skb);
> >
> > Is this skb_orphan(skb) needed? IIUC skb_set_owner_w is doing
> > skb_orphan too? and then calling this helper, but we do need the
> > skb_orphan is needed when called from the synack.
> >
> > Can skb_set_owner_w try to orphan an skb twice?
> >
>
> skb_orphan(skb) does nothing if there is nothing to do.
>
> It is common practice to include it every time we are about to change
> skb->destructor.
>
> Otherwise we would have to add a WARN() or something to prevent future leaks.
>
> Better safe than sorry :)
diff mbox series

Patch

diff --git a/include/net/sock.h b/include/net/sock.h
index 703ec6aef927337f7ca6798ff3c3970529af53f9..e5bb64ad92c769f3edb8c2dc72cafb336837cabb 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -1758,6 +1758,15 @@  void sock_efree(struct sk_buff *skb);
 #ifdef CONFIG_INET
 void sock_edemux(struct sk_buff *skb);
 void sock_pfree(struct sk_buff *skb);
+
+static inline void skb_set_owner_edemux(struct sk_buff *skb, struct sock *sk)
+{
+	skb_orphan(skb);
+	if (refcount_inc_not_zero(&sk->sk_refcnt)) {
+		skb->sk = sk;
+		skb->destructor = sock_edemux;
+	}
+}
 #else
 #define sock_edemux sock_efree
 #endif
diff --git a/net/core/sock.c b/net/core/sock.c
index 083d438d8b6faff60e2e3cf1f982eb306a923cf7..f8c0d4eda888cf190b87fb42e94eef4fb950bf1f 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -2592,14 +2592,11 @@  void __sock_wfree(struct sk_buff *skb)
 void skb_set_owner_w(struct sk_buff *skb, struct sock *sk)
 {
 	skb_orphan(skb);
-	skb->sk = sk;
 #ifdef CONFIG_INET
-	if (unlikely(!sk_fullsock(sk))) {
-		skb->destructor = sock_edemux;
-		sock_hold(sk);
-		return;
-	}
+	if (unlikely(!sk_fullsock(sk)))
+		return skb_set_owner_edemux(skb, sk);
 #endif
+	skb->sk = sk;
 	skb->destructor = sock_wfree;
 	skb_set_hash_from_sk(skb, sk);
 	/*
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 1251510f0e58da6b6403d2097b498f3e4cb6d255..4cf64ed13609fdcb72b3858ca9e20a1e65bd3d94 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -3731,7 +3731,7 @@  struct sk_buff *tcp_make_synack(const struct sock *sk, struct dst_entry *dst,
 
 	switch (synack_type) {
 	case TCP_SYNACK_NORMAL:
-		skb_set_owner_w(skb, req_to_sk(req));
+		skb_set_owner_edemux(skb, req_to_sk(req));
 		break;
 	case TCP_SYNACK_COOKIE:
 		/* Under synflood, we do not attach skb to a socket,