Netdev List
 help / color / mirror / Atom feed
From: David Laight <david.laight.linux@gmail.com>
To: Cen Zhang <zzzccc427@gmail.com>
Cc: davem@davemloft.net, edumazet@kernel.org, kuba@kernel.org,
	pabeni@redhat.com, horms@kernel.org, kuniyu@google.com,
	fmancera@suse.de, willemb@google.com, kees@kernel.org,
	netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
	baijiaju1990@gmail.com, jjzuming@gmail.com
Subject: Re: [PATCH net] ipv6: Keep the SCTP provider alive through socket allocation
Date: Wed, 14 Oct 2026 13:23:19 +0100	[thread overview]
Message-ID: <20261014132319.734ca449@pumpkin> (raw)
In-Reply-To: <pm-ip-core-objects-candidate-0001-v2-efc0e8a00d4f22c36ab8@gmail.com>

On Mon, 12 Oct 2026 12:42:15 +0800
Cen Zhang <zzzccc427@gmail.com> wrote:

> The sctpv6_prot slab must remain alive through socket allocation.
> inet6_create() selects that proto under RCU, but drops RCU before
> sk_alloc(). sk_prot_alloc() obtains the owner reference only after
> allocating from the slab.
> 
> SCTP publishes its IPv6 stream and seqpacket entries while its module
> is still COMING. A concurrent user socket can select an entry before
> register_pernet_subsys(&sctp_ctrlsock_ops), sctp_v4_add_protocol() or
> sctp_v6_add_protocol() fails. The subsequent initialization unwind
> removes both entries and destroys the cache without waiting for owner
> references.
> 
> After the constructor captures the cache pointer, initialization can
> fail and destroy the cache before the allocator consumes that pointer:
> 
>   User socket creation              SCTP module initialization
>   --------------------              --------------------------
>                                     publish IPv6 protosw entries
>   select sctpv6_prot under RCU
>   drop RCU
>   capture prot->slab
>                                     fail a later setup step
>                                     sctp_v6_protosw_exit()
>                                       unlink both entries
>                                       synchronize_net()
>                                       proto_unregister()
>                                         destroy slab cache
>   kmem_cache_alloc(saved slab)
> 
> The allocator can then read retired cache metadata and fault. The grace
> period drains lookup readers, but the constructor has already left RCU.
> An early owner reference alone cannot prevent initialization failure
> from destroying the cache, since try_module_get() accepts COMING.
> 
> The initialization-failure path follows from source inspection. The
> Oops below came from an unload experiment using a modified kernel with
> allocator bootstrap changes, scheduling instrumentation and SCTP's
> internal control socket omitted. With that socket present, its owner
> reference blocks ordinary unload. The experiment selected and captured
> the same cache that teardown destroyed; the seqpacket constructor then
> faulted before the allocator returned.
> 
> Reject user SCTP sockets while the owner is COMING and take a temporary
> owner reference under the lookup's RCU protection before dropping RCU.
> User allocation then requires completed initialization, and the
> reference prevents normal module exit until sk_alloc() takes the
> socket's own reference or fails. Release the temporary reference in
> either case. Keep kernel control socket creation allowed during init,
> where SCTP's per-net registration orders construction and cleanup.

Isn't this the same basic problem than lets a second sock_create() call
enter the protocol code before initialisation is complete and then hit
all sorts of invalid pointers.
That is a real problem that doesn't require module load to fail (it doesn't)
or module unload to happen at an unexpected time (I doubt anyone really
unloads sctp - it could even be marked not-unloadable?)

David

> 
> KASAN report as below:
> 
>     Oops: general protection fault, probably for non-canonical address
>     0xffff11036c3d1430: 0000 [#1] SMP KASAN NOPTI
>     KASAN: maybe wild-memory-access in range
>     [0xfff8a81b61e8a180-0xfff8a81b61e8a187]
>     CPU: 2 UID: 0 PID: 532 Comm: sctp-race-fixtu Not tainted
>     7.2.0-rc5-pmb-ipcore-functional-v2+ #1 PREEMPT(lazy)
>     Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix,
>     1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
>     RIP: 0010:kmem_cache_alloc_noprof+0xd6/0x600
>     Code: 85 c0 0f 8e 93 04 00 00 44 8b 74 24 18 0f 1f 44 00 00 41 bf ff ff
>     ff ff 65 ff 05 b5 e6 0d 09 65 4c 8b 2d a5 e6 0d 09 4c 03 2b <41> 0f b6
>     45 30 84 c0 0f 85 11 04 00 00 41 c6 45 30 01 45 31 c9 41
>     RSP: 0018:ffff8881135dfcc0 EFLAGS: 00010287
>     RAX: 0000000000000001 RBX: ffff88810891ec80 RCX: dffffc0000000000
>     RDX: 0000000000000cc0 RSI: 0000000000000890 RDI: ffff88810891ec80
>     RBP: 0000000000000c00 R08: 0000000000000001 R09: 00000000000000bd
>     R10: 0000000000000028 R11: ffff888113e5ba00 R12: 0000000000000cc0
>     R13: ffff11036c3d1400 R14: 0000000000000000 R15: 00000000ffffffff
>     FS:  00007ff3c2206780(0000) GS:ffff88826b86a000(0000)
>     knlGS:0000000000000000
>     CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
>     CR2: 000055b973e7b10c CR3: 00000001158b5005 CR4: 0000000000770ef0
>     PKRU: 55555554
>     Call Trace:
>      <TASK>
>      ? srso_alias_return_thunk+0x5/0xfbef5
>      ? sk_prot_alloc+0x6f/0x2c0
>      sk_prot_alloc+0x6f/0x2c0
>      sk_alloc+0x37/0xb40
>      inet6_create+0x31b/0x1230
>      ? inet6_create+0x5a/0x1230
>      __sock_create+0x2c4/0x730
>      __sys_socket+0x141/0x210
>      ? __pfx___sys_socket+0x10/0x10
>      ? srso_alias_return_thunk+0x5/0xfbef5
>      ? handle_mm_fault+0x12e/0x580
>      __x64_sys_socket+0x77/0xc0
>      do_syscall_64+0x115/0x6a0
>      entry_SYSCALL_64_after_hwframe+0x77/0x7f
>     RIP: 0033:0x7ff3c231b437
>     Code: 8b 54 24 08 64 48 2b 14 25 28 00 00 00 75 05 48 83 c4 18 c3 e8 ba
>     a7 00 00 66 2e 0f 1f 84 00 00 00 00 00 b8 29 00 00 00 0f 05 <48> 3d 01
>     f0 ff ff 73 01 c3 48 8b 0d a9 29 0d 00 f7 d8 64 89 01 48
>     RSP: 002b:00007ffed24e4ab8 EFLAGS: 00000246 ORIG_RAX: 0000000000000029
>     RAX: ffffffffffffffda RBX: 00007ffed24e4bd8 RCX: 00007ff3c231b437
>     RDX: 0000000000000084 RSI: 0000000000000005 RDI: 000000000000000a
>     RBP: 0000000000000002 R08: 0000000000000000 R09: 00007ff3c2413aa0
>     R10: 00007ffed24e4800 R11: 0000000000000246 R12: 0000000000000000
>     R13: 00007ffed24e4bf0 R14: 00007ff3c2444000 R15: 000055b973e7cd48
>      </TASK>
>     Modules linked in: [last unloaded: sctp]
>     ---[ end trace 0000000000000000 ]---
>     RIP: 0010:kmem_cache_alloc_noprof+0xd6/0x600
>     Code: 85 c0 0f 8e 93 04 00 00 44 8b 74 24 18 0f 1f 44 00 00 41 bf ff ff
>     ff ff 65 ff 05 b5 e6 0d 09 65 4c 8b 2d a5 e6 0d 09 4c 03 2b <41> 0f b6
>     45 30 84 c0 0f 85 11 04 00 00 41 c6 45 30 01 45 31 c9 41
>     RSP: 0018:ffff8881135dfcc0 EFLAGS: 00010287
>     RAX: 0000000000000001 RBX: ffff88810891ec80 RCX: dffffc0000000000
>     RDX: 0000000000000cc0 RSI: 0000000000000890 RDI: ffff88810891ec80
>     RBP: 0000000000000c00 R08: 0000000000000001 R09: 00000000000000bd
>     R10: 0000000000000028 R11: ffff888113e5ba00 R12: 0000000000000cc0
>     R13: ffff11036c3d1400 R14: 0000000000000000 R15: 00000000ffffffff
>     FS:  00007ff3c2206780(0000) GS:ffff88826b86a000(0000)
>     knlGS:0000000000000000
>     CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
>     CR2: 000055b973e7b10c CR3: 00000001158b5005 CR4: 0000000000770ef0
>     PKRU: 55555554
>     Kernel panic - not syncing: Fatal exception
>     Kernel Offset: disabled
>     ---[ end Kernel panic - not syncing: Fatal exception ]---
> 
> Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
> Assisted-by: LLM
> 
> ---
> 
> diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
> index a9b8b4b42a1af72f09fb9544b0e13aade00a1e3d..fb7f84baeeb66f5d3926169df790cc439f98224f 100644
> --- a/net/ipv6/af_inet6.c
> +++ b/net/ipv6/af_inet6.c
> @@ -110,6 +110,7 @@ static int inet6_create(struct net *net, struct socket *sock, int protocol,
>  	struct sock *sk;
>  	struct inet_protosw *answer;
>  	struct proto *answer_prot;
> +	struct module *owner = NULL;
>  	unsigned char answer_flags;
>  	int try_loading_module = 0;
>  	int err;
> @@ -169,6 +170,17 @@ static int inet6_create(struct net *net, struct socket *sock, int protocol,
>  
>  	sock->ops = answer->ops;
>  	answer_prot = answer->prot;
> +	if (answer->protocol == IPPROTO_SCTP) {
> +		owner = answer_prot->owner;
> +		err = -EPROTONOSUPPORT;
> +		/* SCTP init can unwind despite an owner reference.
> +		 * Allow the kernel control socket during initialization.
> +		 */
> +		if (!kern && owner && module_is_coming(owner))
> +			goto out_rcu_unlock;
> +		if (!try_module_get(owner))
> +			goto out_rcu_unlock;
> +	}
>  	answer_flags = answer->flags;
>  	rcu_read_unlock();
>  
> @@ -176,6 +188,7 @@ static int inet6_create(struct net *net, struct socket *sock, int protocol,
>  
>  	err = -ENOBUFS;
>  	sk = sk_alloc(net, PF_INET6, GFP_KERNEL, answer_prot, kern);
> +	module_put(owner);
>  	if (!sk)
>  		goto out;
>  
> 


      parent reply	other threads:[~2026-10-14 12:23 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-12  4:42 [PATCH net] ipv6: Keep the SCTP provider alive through socket allocation Cen Zhang
2026-10-12 19:56 ` Kuniyuki Iwashima
2026-10-13  2:39   ` Cen Zhang
2026-10-13  5:44 ` netdev-bot+sashiko
2026-10-14 12:23 ` David Laight [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261014132319.734ca449@pumpkin \
    --to=david.laight.linux@gmail.com \
    --cc=baijiaju1990@gmail.com \
    --cc=davem@davemloft.net \
    --cc=edumazet@kernel.org \
    --cc=fmancera@suse.de \
    --cc=horms@kernel.org \
    --cc=jjzuming@gmail.com \
    --cc=kees@kernel.org \
    --cc=kuba@kernel.org \
    --cc=kuniyu@google.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=willemb@google.com \
    --cc=zzzccc427@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox