WARNING in svc_destroy

Status: moderation: reported on 2026/11/05 19:35
Subsystems: net nfs
Labels: prio:normal
[Documentation on labels]
Reported-by: syzbot+3c98edca676012db07cf@syzkaller.appspotmail.com
First crash: 2h33m, last: 2h33m
✨ AI-generated root cause summary:

In fs/nfs/callback.c, nfs4_callback_up_net() first initializes an IPv4 TCP listener transport via svc_xprt_create(..., PF_INET, ...), which links the transport onto serv->sv_permsocks. When a subsequent call to svc_xprt_create(..., PF_INET6, ...) fails with an error other than -EAFNOSUPPORT, nfs4_callback_up_net() returns the error immediately without tearing down the existing IPv4 transport. As a result, nfs_callback_up() unwinds on error and calls xprt_svc_destroy_nullify_bc() -> svc_destroy(), which triggers the WARN_ONCE(!list_empty(&serv->sv_permsocks)) warning because the IPv4 transport is still attached to the service, and subsequently frees the service while leaving the active listener with a dangling pointer.

▶ ▼ ✨ Full AI root cause analysis
Based on kernel commit 05441d697f7f:

Technical Root Cause Analysis

Involved Components

  • Source Files: fs/nfs/callback.c, net/sunrpc/svc.c, net/sunrpc/svc_xprt.c
  • Functions: nfs4_callback_up_net(), nfs_callback_up_net(), nfs_callback_up(), svc_destroy(), svc_xprt_create(), svc_add_new_perm_xprt()
  • Data Structures and Fields:
    • struct svc_serv: fields sv_permsocks, sv_pools
    • struct svc_xprt: fields xpt_list, xpt_server, xpt_flags

Root Cause and Trigger Mechanism

  1. Callback Service Initialization: During NFSv4.0 mount/client setup, nfs_callback_up() is invoked to bring up the callback service. It creates a server instance (struct svc_serv) via nfs_callback_create_svc(minorversion) and attempts to configure per-network-namespace callback transports by calling nfs_callback_up_net(minorversion, serv, net, xprt).

  2. Creation of Listeners in nfs4_callback_up_net(): For NFSv4.0 (minorversion == 0), nfs_callback_up_net() invokes nfs4_callback_up_net():

    ret = svc_xprt_create(serv, "tcp", net, PF_INET,
                          nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS, cred);
    if (ret <= 0)
        goto out_err;
    nn->nfs_callback_tcpport = ret;
    
    ret = svc_xprt_create(serv, "tcp", net, PF_INET6,
                          nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS, cred);
    if (ret > 0) {
        nn->nfs_callback_tcpport6 = ret;
    } else if (ret != -EAFNOSUPPORT)
        goto out_err;
    
    • The first call to svc_xprt_create() for PF_INET succeeds. The created struct svc_xprt is attached to serv->sv_permsocks via svc_add_new_perm_xprt(), and its xpt_server pointer is set to serv.
    • The second call to svc_xprt_create() for PF_INET6 fails with an error other than -EAFNOSUPPORT (for example, -EINVAL, -EADDRINUSE, -ENOBUFS, or other socket creation/bind errors).
    • nfs4_callback_up_net() takes the goto out_err; branch and returns the error code without cleaning up or closing the previously created PF_INET transport.
  3. Incomplete Error Unwind:

    • In nfs_callback_up_net(), on ret < 0, it prints "NFS: callback service start failed", decrements nn->cb_users[minorversion], and returns ret without destroying any transports associated with serv.
    • Control returns to nfs_callback_up(), which branches to err_net:. Because cb_info->users is 0, it calls:
      xprt_svc_shutdown_bc(xprt);
      svc_set_num_threads(cb_info->serv, 0, 0);
      xprt_svc_destroy_nullify_bc(xprt, &cb_info->serv);
      
    • xprt_svc_destroy_nullify_bc() forwards directly to svc_destroy(&cb_info->serv).
  4. Premature Destruction of svc_serv: In svc_destroy() (net/sunrpc/svc.c):

    WARN_ONCE(!list_empty(&serv->sv_permsocks),
              "SVC: permsocks remain for %s\n", serv->sv_programs->pg_name);
    WARN_ONCE(!list_empty(&serv->sv_tempsocks),
              "SVC: tempsocks remain for %s\n", serv->sv_programs->pg_name);
    ...
    kfree(serv->sv_pools);
    kfree(serv);
    

    Because the IPv4 transport was never torn down (unlike during graceful shutdown or in fs/lockd/svc.c:make_socks() where svc_xprt_destroy_all(serv, net, ...) is called on error), serv->sv_permsocks is not empty. This triggers the reported WARN_ONCE.

  5. Dangling Pointer and Use-After-Free: Following the warning, svc_destroy() proceeds to free serv->sv_pools and serv. The still-active IPv4 listener transport (struct svc_xprt) remains registered in the network stack with its xpt_server field holding a dangling pointer to the freed struct svc_serv.

▶ ▼ ✨ AI Jobs (1)
ID Workflow Result Correct Bug Created Started Finished Revision
1182a445 assessment-security DenialOfService: ✅ Exploitable: ✅ FilesystemTrigger: ❌ FuzzingArtifact: ❌ MemoryCorruption: ✅ NetworkNeedsSetup: ❌ NetworkTrigger: ❌ PeripheralTrigger: ❌ RemoteTrigger: ❌ Unprivileged: ❌ UserNamespace: ❌ VMGuestTrigger: ❌ VMHostTrigger: ❌ ❓ WARNING in svc_destroy 2026/11/05 18:23 2026/11/05 18:23 2026/11/05 19:23 5cecaf1f
▶ ▼ Similar bugs (1)
Kernel Title Rank 🛈 Repro Cause bisect Fix bisect Count Last Reported Patched Status
linux-6.6 WARNING in svc_destroy origin:lts-only -1 syz, C 452 1d10h 101d 0/2 upstream: reported C repro on 2026/07/27 20:31

Sample crash report:
NFS: callback service start failed
------------[ cut here ]------------
SVC: permsocks remain for NFSv4 callback
WARNING: net/sunrpc/svc.c:532 at svc_destroy+0x299/0x330 net/sunrpc/svc.c:532, CPU#1: syz.2.321/6994
Modules linked in:
CPU: 1 UID: 0 PID: 6994 Comm: syz.2.321 Not tainted syzkaller #0 PREEMPT(full) 
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/15/2026
RIP: 0010:svc_destroy+0x29d/0x330 net/sunrpc/svc.c:532
Code: 48 b8 00 00 00 00 00 fc ff df 49 8b 5d 00 48 8d 7b 18 48 89 fa 48 c1 ea 03 80 3c 02 00 75 67 48 8d 3d 17 5e 78 07 48 8b 73 18 <67> 48 0f b9 3a e9 d0 fd ff ff 48 8b 7c 24 08 e8 bf 13 86 f7 e9 a5
RSP: 0018:ffffc900042af860 EFLAGS: 00010246
RAX: dffffc0000000000 RBX: ffffffff9040ba80 RCX: ffffc900063d9000
RDX: 1ffffffff2081753 RSI: ffffffff8c37e800 RDI: ffffffff927aee30
RBP: 0000000000000000 R08: 00000000ffffffff R09: 0000000000000000
R10: 0000000000000001 R11: 0000000000000000 R12: ffff888035744000
R13: ffff888055f04c00 R14: ffff88802de30000 R15: ffffffff9cd5b540
FS:  00007ff81118f6c0(0000) GS:ffff88812257c000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 000000110c29af61 CR3: 0000000056a04000 CR4: 00000000003526f0
Call Trace:
 <TASK>
 nfs_callback_up+0x511/0xad0 fs/nfs/callback.c:236
 nfs4_init_callback fs/nfs/nfs4client.c:327 [inline]
 nfs4_init_client_minor_version fs/nfs/nfs4client.c:379 [inline]
 nfs4_init_client+0x236/0x420 fs/nfs/nfs4client.c:429
 nfs_get_client+0xf38/0x1230 fs/nfs/client.c:467
 nfs4_set_client+0x3f6/0x640 fs/nfs/nfs4client.c:763
 nfs4_init_server.isra.0+0x5be/0xf80 fs/nfs/nfs4client.c:1014
 nfs4_create_server+0x185/0x2b0 fs/nfs/nfs4client.c:1063
 nfs4_try_get_tree+0x93/0x140 fs/nfs/nfs4super.c:228
 nfs_get_tree+0xa61/0x1440 fs/nfs/fs_context.c:1621
 vfs_get_tree+0x92/0x320 fs/super.c:1881
 fc_mount fs/namespace.c:1282 [inline]
 do_new_mount_fc fs/namespace.c:3910 [inline]
 do_new_mount fs/namespace.c:3986 [inline]
 path_mount+0x7d0/0x2850 fs/namespace.c:4337
 do_mount fs/namespace.c:4350 [inline]
 __do_sys_mount fs/namespace.c:4565 [inline]
 __se_sys_mount fs/namespace.c:4542 [inline]
 __x64_sys_mount+0x293/0x310 fs/namespace.c:4542
 do_syscall_x64 arch/x86/entry/syscall_64.c:61 [inline]
 do_syscall_64+0x123/0x790 arch/x86/entry/syscall_64.c:84
 entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7ff81039fb19
Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 e8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007ff81118f028 EFLAGS: 00000246 ORIG_RAX: 00000000000000a5
RAX: ffffffffffffffda RBX: 00007ff810625fa0 RCX: 00007ff81039fb19
RDX: 0000200000000480 RSI: 0000200000000440 RDI: 0000200000000400
RBP: 00007ff810437b70 R08: 00002000000004c0 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007ff810626038 R14: 00007ff810625fa0 R15: 00007ffd2a563db8
 </TASK>
----------------
Code disassembly (best guess):
   0:	48 b8 00 00 00 00 00 	movabs $0xdffffc0000000000,%rax
   7:	fc ff df
   a:	49 8b 5d 00          	mov    0x0(%r13),%rbx
   e:	48 8d 7b 18          	lea    0x18(%rbx),%rdi
  12:	48 89 fa             	mov    %rdi,%rdx
  15:	48 c1 ea 03          	shr    $0x3,%rdx
  19:	80 3c 02 00          	cmpb   $0x0,(%rdx,%rax,1)
  1d:	75 67                	jne    0x86
  1f:	48 8d 3d 17 5e 78 07 	lea    0x7785e17(%rip),%rdi        # 0x7785e3d
  26:	48 8b 73 18          	mov    0x18(%rbx),%rsi
* 2a:	67 48 0f b9 3a       	ud1    (%edx),%rdi <-- trapping instruction
  2f:	e9 d0 fd ff ff       	jmp    0xfffffe04
  34:	48 8b 7c 24 08       	mov    0x8(%rsp),%rdi
  39:	e8 bf 13 86 f7       	call   0xf78613fd
  3e:	e9                   	.byte 0xe9
  3f:	a5                   	movsl  %ds:(%rsi),%es:(%rdi)

Crashes (1):
Time Kernel Commit Syzkaller Config Log Report Syz repro C repro VM info Assets (help?) Manager Title
2026/11/05 18:08 upstream 05441d697f7f 5cecaf1f .config console log report info [disk image] [vmlinux] [kernel image] ci-upstream-kasan-gce-selinux-root WARNING in svc_destroy
* Struck through repros no longer work on HEAD.