[<prev] [next>] [day] [month] [year] [list]
Message-ID: <68889a3f.050a0220.f0410.0000.GAE@google.com>
Date: Tue, 29 Jul 2025 02:54:07 -0700
From: syzbot <syzbot+6641a61fe0e2e89ae8c5@...kaller.appspotmail.com>
To: steffen.klassert@...unet.com
Cc: steffen.klassert@...unet.com, linux-kernel@...r.kernel.org,
syzkaller-bugs@...glegroups.com
Subject: Re: [syzbot] [net?] WARNING in xfrm_state_fini (3)
> On Tue, Jul 29, 2025 at 12:08:31AM -0700, syzbot wrote:
>> Hello,
>>
>> syzbot found the following issue on:
>>
>> HEAD commit: 038d61fd6422 Linux 6.16
>> git tree: upstream
>> console+strace: https://syzkaller.appspot.com/x/log.txt?x=11b88cf0580000
>> kernel config: https://syzkaller.appspot.com/x/.config?x=4066f1c76cfbc4fe
>> dashboard link: https://syzkaller.appspot.com/bug?extid=6641a61fe0e2e89ae8c5
>> compiler: Debian clang version 20.1.7 (++20250616065708+6146a88f6049-1~exp1~20250616065826.132), Debian LLD 20.1.7
>> syz repro: https://syzkaller.appspot.com/x/repro.syz?x=16ca1782580000
>> C reproducer: https://syzkaller.appspot.com/x/repro.c?x=140194a2580000
>>
>> Downloadable assets:
>> disk image: https://storage.googleapis.com/syzbot-assets/6505c612be11/disk-038d61fd.raw.xz
>> vmlinux: https://storage.googleapis.com/syzbot-assets/e466ef29c1ca/vmlinux-038d61fd.xz
>> kernel image: https://storage.googleapis.com/syzbot-assets/b6d3d8fc5cbb/bzImage-038d61fd.xz
>>
>> IMPORTANT: if you fix the issue, please add the following tag to the commit:
>> Reported-by: syzbot+6641a61fe0e2e89ae8c5@...kaller.appspotmail.com
>
> #syz test:
want either no args or 2 args (repo, branch), got 4
>
> diff --git a/include/net/xfrm.h b/include/net/xfrm.h
> index f3014e4f54fc..91d52a380e37 100644
> --- a/include/net/xfrm.h
> +++ b/include/net/xfrm.h
> @@ -915,7 +915,7 @@ static inline void xfrm_pols_put(struct xfrm_policy **pols, int npols)
> xfrm_pol_put(pols[i]);
> }
>
> -void __xfrm_state_destroy(struct xfrm_state *);
> +void __xfrm_state_destroy(struct xfrm_state *, bool);
>
> static inline void __xfrm_state_put(struct xfrm_state *x)
> {
> @@ -925,7 +925,13 @@ static inline void __xfrm_state_put(struct xfrm_state *x)
> static inline void xfrm_state_put(struct xfrm_state *x)
> {
> if (refcount_dec_and_test(&x->refcnt))
> - __xfrm_state_destroy(x);
> + __xfrm_state_destroy(x, false);
> +}
> +
> +static inline void xfrm_state_put_sync(struct xfrm_state *x)
> +{
> + if (refcount_dec_and_test(&x->refcnt))
> + __xfrm_state_destroy(x, true);
> }
>
> static inline void xfrm_state_hold(struct xfrm_state *x)
> @@ -1763,7 +1769,7 @@ struct xfrmk_spdinfo {
>
> struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 mark, u32 seq, u32 pcpu_num);
> int xfrm_state_delete(struct xfrm_state *x);
> -int xfrm_state_flush(struct net *net, u8 proto, bool task_valid);
> +int xfrm_state_flush(struct net *net, u8 proto, bool task_valid, bool sync);
> int xfrm_dev_state_flush(struct net *net, struct net_device *dev, bool task_valid);
> int xfrm_dev_policy_flush(struct net *net, struct net_device *dev,
> bool task_valid);
> diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
> index 5120a763da0d..7fd8bc08e6eb 100644
> --- a/net/ipv6/xfrm6_tunnel.c
> +++ b/net/ipv6/xfrm6_tunnel.c
> @@ -334,7 +334,7 @@ static void __net_exit xfrm6_tunnel_net_exit(struct net *net)
> struct xfrm6_tunnel_net *xfrm6_tn = xfrm6_tunnel_pernet(net);
> unsigned int i;
>
> - xfrm_state_flush(net, IPSEC_PROTO_ANY, false);
> + xfrm_state_flush(net, 0, false, true);
> xfrm_flush_gc();
>
> for (i = 0; i < XFRM6_TUNNEL_SPI_BYADDR_HSIZE; i++)
> diff --git a/net/key/af_key.c b/net/key/af_key.c
> index b5d761700776..efc2a91f4c48 100644
> --- a/net/key/af_key.c
> +++ b/net/key/af_key.c
> @@ -1766,7 +1766,7 @@ static int pfkey_flush(struct sock *sk, struct sk_buff *skb, const struct sadb_m
> if (proto == 0)
> return -EINVAL;
>
> - err = xfrm_state_flush(net, proto, true);
> + err = xfrm_state_flush(net, proto, true, false);
> err2 = unicast_flush_resp(sk, hdr);
> if (err || err2) {
> if (err == -ESRCH) /* empty table - go quietly */
> diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
> index 97ff756191ba..0ec7d22aaff3 100644
> --- a/net/xfrm/xfrm_state.c
> +++ b/net/xfrm/xfrm_state.c
> @@ -592,7 +592,7 @@ void xfrm_state_free(struct xfrm_state *x)
> }
> EXPORT_SYMBOL(xfrm_state_free);
>
> -static void xfrm_state_gc_destroy(struct xfrm_state *x)
> +static void ___xfrm_state_destroy(struct xfrm_state *x)
> {
> if (x->mode_cbs && x->mode_cbs->destroy_state)
> x->mode_cbs->destroy_state(x);
> @@ -631,7 +631,7 @@ static void xfrm_state_gc_task(struct work_struct *work)
> synchronize_rcu();
>
> hlist_for_each_entry_safe(x, tmp, &gc_list, gclist)
> - xfrm_state_gc_destroy(x);
> + ___xfrm_state_destroy(x);
> }
>
> static enum hrtimer_restart xfrm_timer_handler(struct hrtimer *me)
> @@ -795,14 +795,19 @@ void xfrm_dev_state_free(struct xfrm_state *x)
> }
> #endif
>
> -void __xfrm_state_destroy(struct xfrm_state *x)
> +void __xfrm_state_destroy(struct xfrm_state *x, bool sync)
> {
> WARN_ON(x->km.state != XFRM_STATE_DEAD);
>
> - spin_lock_bh(&xfrm_state_gc_lock);
> - hlist_add_head(&x->gclist, &xfrm_state_gc_list);
> - spin_unlock_bh(&xfrm_state_gc_lock);
> - schedule_work(&xfrm_state_gc_work);
> + if (sync) {
> + synchronize_rcu();
> + ___xfrm_state_destroy(x);
> + } else {
> + spin_lock_bh(&xfrm_state_gc_lock);
> + hlist_add_head(&x->gclist, &xfrm_state_gc_list);
> + spin_unlock_bh(&xfrm_state_gc_lock);
> + schedule_work(&xfrm_state_gc_work);
> + }
> }
> EXPORT_SYMBOL(__xfrm_state_destroy);
>
> @@ -917,7 +922,7 @@ xfrm_dev_state_flush_secctx_check(struct net *net, struct net_device *dev, bool
> }
> #endif
>
> -int xfrm_state_flush(struct net *net, u8 proto, bool task_valid)
> +int xfrm_state_flush(struct net *net, u8 proto, bool task_valid, bool sync)
> {
> int i, err = 0, cnt = 0;
>
> @@ -3278,7 +3283,7 @@ void xfrm_state_fini(struct net *net)
> unsigned int sz;
>
> flush_work(&net->xfrm.state_hash_work);
> - xfrm_state_flush(net, IPSEC_PROTO_ANY, false);
> + xfrm_state_flush(net, 0, false, true);
> flush_work(&xfrm_state_gc_work);
>
> WARN_ON(!list_empty(&net->xfrm.state_all));
> diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
> index 684239018bec..1db18f470f42 100644
> --- a/net/xfrm/xfrm_user.c
> +++ b/net/xfrm/xfrm_user.c
> @@ -2635,7 +2635,7 @@ static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
> struct xfrm_usersa_flush *p = nlmsg_data(nlh);
> int err;
>
> - err = xfrm_state_flush(net, p->proto, true);
> + err = xfrm_state_flush(net, p->proto, true, false);
> if (err) {
> if (err == -ESRCH) /* empty table */
> return 0;
> --
> 2.43.0
>
Powered by blists - more mailing lists