diff mbox series

[PATCHv2,net] ipv6: sr: fix invalid unregister error path

Message ID 20240508025502.3928296-1-liuhangbin@gmail.com (mailing list archive)
State Changes Requested
Delegated to: Netdev Maintainers
Headers show
Series [PATCHv2,net] ipv6: sr: fix invalid unregister error path | 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 success Fixes tag present in non-next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 928 this patch: 928
netdev/build_tools success No tools touched, skip
netdev/cc_maintainers success CCed 6 of 6 maintainers
netdev/build_clang success Errors and warnings before: 937 this patch: 937
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 Fixes tag looks correct
netdev/build_allmodconfig_warn success Errors and warnings before: 939 this patch: 939
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 19 lines checked
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0
netdev/contest success net-next-2024-05-08--09-00 (tests: 1003)

Commit Message

Hangbin Liu May 8, 2024, 2:55 a.m. UTC
The error path of seg6_init() is wrong in case CONFIG_IPV6_SEG6_LWTUNNEL
is not defined. In that case if seg6_hmac_init() fails, the
genl_unregister_family() isn't called.

At the same time, add seg6_local_exit() and fix the genl unregister order
in seg6_exit().

Fixes: 5559cea2d5aa ("ipv6: sr: fix possible use-after-free and null-ptr-deref")
Reported-by: Guillaume Nault <gnault@redhat.com>
Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
---
v2: define label out_unregister_genl in CONFIG_IPV6_SEG6_LWTUNNEL(Sabrina Dubroca)
---
 net/ipv6/seg6.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

Comments

Sabrina Dubroca May 8, 2024, 9:33 a.m. UTC | #1
2024-05-08, 10:55:02 +0800, Hangbin Liu wrote:
> The error path of seg6_init() is wrong in case CONFIG_IPV6_SEG6_LWTUNNEL
> is not defined. In that case if seg6_hmac_init() fails, the
> genl_unregister_family() isn't called.
> 
> At the same time, add seg6_local_exit() and fix the genl unregister order
> in seg6_exit().
> 
> Fixes: 5559cea2d5aa ("ipv6: sr: fix possible use-after-free and null-ptr-deref")
> Reported-by: Guillaume Nault <gnault@redhat.com>
> Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
> ---
> v2: define label out_unregister_genl in CONFIG_IPV6_SEG6_LWTUNNEL(Sabrina Dubroca)
> ---
>  net/ipv6/seg6.c | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/net/ipv6/seg6.c b/net/ipv6/seg6.c
> index 35508abd76f4..6a80d93399ce 100644
> --- a/net/ipv6/seg6.c
> +++ b/net/ipv6/seg6.c
> @@ -551,8 +551,8 @@ int __init seg6_init(void)
>  #endif
>  #ifdef CONFIG_IPV6_SEG6_LWTUNNEL
>  out_unregister_genl:
> -	genl_unregister_family(&seg6_genl_family);
>  #endif
> +	genl_unregister_family(&seg6_genl_family);

Sorry, I didn't notice when you answered my comment yesterday, but
this will create unreachable code after return when
CONFIG_IPV6_SEG6_LWTUNNEL=n and CONFIG_IPV6_SEG6_HMAC=n:

out:
	return err;
	genl_unregister_family(&seg6_genl_family);
out_unregister_pernet:
	unregister_pernet_subsys(&ip6_segments_ops);
	goto out;


(stragely, gcc doesn't complain about it, I thought it would)


The only solution I can think of if we want to avoid it is ugly:

 #ifdef CONFIG_IPV6_SEG6_LWTUNNEL
 out_unregister_genl:
 #endif
+#if IS_ENABLED(CONFIG_IPV6_SEG6_LWTUNNEL) || IS_ENABLED(CONFIG_IPV6_SEG6_HMAC)
 	genl_unregister_family(&seg6_genl_family);
+#endif
 out_unregister_pernet:
 	unregister_pernet_subsys(&ip6_segments_ops);
 	goto out;

(on top of v2)

For all other cases your patch looks correct.
Simon Horman May 8, 2024, 9:40 a.m. UTC | #2
On Wed, May 08, 2024 at 10:55:02AM +0800, Hangbin Liu wrote:
> The error path of seg6_init() is wrong in case CONFIG_IPV6_SEG6_LWTUNNEL
> is not defined. In that case if seg6_hmac_init() fails, the
> genl_unregister_family() isn't called.
> 
> At the same time, add seg6_local_exit() and fix the genl unregister order
> in seg6_exit().

It seems that this fixes two, or perhaps three different problems.
Perhaps we should consider two or three patches?

Also, could you explain the implications of changing the unregister order
in the patch description: it should describe why a change is made.

> Fixes: 5559cea2d5aa ("ipv6: sr: fix possible use-after-free and null-ptr-deref")

I agree that the current manifestation of the first problem
was introduced. But didn't a very similar problem exist before then?
I suspect the fixes tag should refer to an earlier commit.

> Reported-by: Guillaume Nault <gnault@redhat.com>
> Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>

I think these bugs are pretty good examples of why not
to sprinkle #ifdef inside of functions - it makes the
logic hard to reason with.

So while I agree that a minimal fix, along the lines of this patch, is
suitable for 'net'. Could we consider, as a follow-up, refactoring the code
to remove this #ifdef spaghetti? F.e. by providing dummy implementations
of seg6_iptunnel_init()/seg6_iptunnel_exit() and so on.
Vasiliy Kovalev May 8, 2024, 12:04 p.m. UTC | #3
Hi,

08.05.2024 12:40, Simon Horman wrote:
> On Wed, May 08, 2024 at 10:55:02AM +0800, Hangbin Liu wrote:

>> Fixes: 5559cea2d5aa ("ipv6: sr: fix possible use-after-free and null-ptr-deref")
> 
> I agree that the current manifestation of the first problem
> was introduced. But didn't a very similar problem exist before then?
> I suspect the fixes tag should refer to an earlier commit.
> 
Indeed, the invalid unregister error path was introduced by commit 
46738b1317e1 ("ipv6: sr: add option to control lwtunnel support"),
and the mentioned 5559cea2d5aa commit replaced one function with another 
in this error path.
Hangbin Liu May 8, 2024, 2:23 p.m. UTC | #4
On Wed, May 08, 2024 at 11:33:18AM +0200, Sabrina Dubroca wrote:
> > ---
> > v2: define label out_unregister_genl in CONFIG_IPV6_SEG6_LWTUNNEL(Sabrina Dubroca)
> > ---
> >  net/ipv6/seg6.c | 5 +++--
> >  1 file changed, 3 insertions(+), 2 deletions(-)
> > 
> > diff --git a/net/ipv6/seg6.c b/net/ipv6/seg6.c
> > index 35508abd76f4..6a80d93399ce 100644
> > --- a/net/ipv6/seg6.c
> > +++ b/net/ipv6/seg6.c
> > @@ -551,8 +551,8 @@ int __init seg6_init(void)
> >  #endif
> >  #ifdef CONFIG_IPV6_SEG6_LWTUNNEL
> >  out_unregister_genl:
> > -	genl_unregister_family(&seg6_genl_family);
> >  #endif
> > +	genl_unregister_family(&seg6_genl_family);
> 
> Sorry, I didn't notice when you answered my comment yesterday, but
> this will create unreachable code after return when
> CONFIG_IPV6_SEG6_LWTUNNEL=n and CONFIG_IPV6_SEG6_HMAC=n:

Oh.. Didn't notice this...

> 
> out:
> 	return err;
> 	genl_unregister_family(&seg6_genl_family);
> out_unregister_pernet:
> 	unregister_pernet_subsys(&ip6_segments_ops);
> 	goto out;
> 
> 
> (stragely, gcc doesn't complain about it, I thought it would)

Yes, I also complied the patch with not complain, so I just posted it.

> 
> 
> The only solution I can think of if we want to avoid it is ugly:
> 
>  #ifdef CONFIG_IPV6_SEG6_LWTUNNEL
>  out_unregister_genl:
>  #endif
> +#if IS_ENABLED(CONFIG_IPV6_SEG6_LWTUNNEL) || IS_ENABLED(CONFIG_IPV6_SEG6_HMAC)
>  	genl_unregister_family(&seg6_genl_family);
> +#endif
>  out_unregister_pernet:
>  	unregister_pernet_subsys(&ip6_segments_ops);
>  	goto out;
> 
> (on top of v2)
> 
> For all other cases your patch looks correct.

Thanks, I will check if there are any other workaround. If not, I will do
like what you said.

Hangbin
Hangbin Liu May 8, 2024, 2:26 p.m. UTC | #5
On Wed, May 08, 2024 at 10:40:53AM +0100, Simon Horman wrote:
> On Wed, May 08, 2024 at 10:55:02AM +0800, Hangbin Liu wrote:
> > The error path of seg6_init() is wrong in case CONFIG_IPV6_SEG6_LWTUNNEL
> > is not defined. In that case if seg6_hmac_init() fails, the
> > genl_unregister_family() isn't called.
> > 
> > At the same time, add seg6_local_exit() and fix the genl unregister order
> > in seg6_exit().
> 
> It seems that this fixes two, or perhaps three different problems.
> Perhaps we should consider two or three patches?

Yeah..
> 
> Also, could you explain the implications of changing the unregister order
> in the patch description: it should describe why a change is made.

Sure, I will.

> 
> > Fixes: 5559cea2d5aa ("ipv6: sr: fix possible use-after-free and null-ptr-deref")
> 
> I agree that the current manifestation of the first problem
> was introduced. But didn't a very similar problem exist before then?
> I suspect the fixes tag should refer to an earlier commit.

Yes, I will check previous commits.

> 
> > Reported-by: Guillaume Nault <gnault@redhat.com>
> > Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
> 
> I think these bugs are pretty good examples of why not
> to sprinkle #ifdef inside of functions - it makes the
> logic hard to reason with.
> 
> So while I agree that a minimal fix, along the lines of this patch, is
> suitable for 'net'. Could we consider, as a follow-up, refactoring the code
> to remove this #ifdef spaghetti? F.e. by providing dummy implementations
> of seg6_iptunnel_init()/seg6_iptunnel_exit() and so on.

Makes sense.

Thanks
Hangbin
Hangbin Liu May 8, 2024, 2:28 p.m. UTC | #6
On Wed, May 08, 2024 at 03:04:36PM +0300, kovalev@altlinux.org wrote:
> Hi,
> 
> 08.05.2024 12:40, Simon Horman wrote:
> > On Wed, May 08, 2024 at 10:55:02AM +0800, Hangbin Liu wrote:
> 
> > > Fixes: 5559cea2d5aa ("ipv6: sr: fix possible use-after-free and null-ptr-deref")
> > 
> > I agree that the current manifestation of the first problem
> > was introduced. But didn't a very similar problem exist before then?
> > I suspect the fixes tag should refer to an earlier commit.
> > 
> Indeed, the invalid unregister error path was introduced by commit
> 46738b1317e1 ("ipv6: sr: add option to control lwtunnel support"),
> and the mentioned 5559cea2d5aa commit replaced one function with another in
> this error path.

Thanks for your checking :)

Hangbin
diff mbox series

Patch

diff --git a/net/ipv6/seg6.c b/net/ipv6/seg6.c
index 35508abd76f4..6a80d93399ce 100644
--- a/net/ipv6/seg6.c
+++ b/net/ipv6/seg6.c
@@ -551,8 +551,8 @@  int __init seg6_init(void)
 #endif
 #ifdef CONFIG_IPV6_SEG6_LWTUNNEL
 out_unregister_genl:
-	genl_unregister_family(&seg6_genl_family);
 #endif
+	genl_unregister_family(&seg6_genl_family);
 out_unregister_pernet:
 	unregister_pernet_subsys(&ip6_segments_ops);
 	goto out;
@@ -564,8 +564,9 @@  void seg6_exit(void)
 	seg6_hmac_exit();
 #endif
 #ifdef CONFIG_IPV6_SEG6_LWTUNNEL
+	seg6_local_exit();
 	seg6_iptunnel_exit();
 #endif
-	unregister_pernet_subsys(&ip6_segments_ops);
 	genl_unregister_family(&seg6_genl_family);
+	unregister_pernet_subsys(&ip6_segments_ops);
 }