On Thu, Jan 31, 2019 at 01:05:49PM -0800, Cong Wang wrote:
> xfrm_state_put() moves struct xfrm_state to the GC list
> and schedules the GC work to clean it up. On net exit call
> path, xfrm_state_flush() is called to clean up and
> xfrm_flush_gc() is called to wait for the GC work to complete
> before exit.
> 
> However, this doesn't work because one of the ->destructor(),
> ipcomp_destroy(), schedules the same GC work again inside
> the GC work. It is hard to wait for such a nested async
> callback. This is also why syzbot still reports the following
> warning:
> 
>  WARNING: CPU: 1 PID: 33 at net/ipv6/xfrm6_tunnel.c:351 
> xfrm6_tunnel_net_exit+0x2cb/0x500 net/ipv6/xfrm6_tunnel.c:351
>  ...
>   ops_exit_list.isra.0+0xb0/0x160 net/core/net_namespace.c:153
>   cleanup_net+0x51d/0xb10 net/core/net_namespace.c:551
>   process_one_work+0xd0c/0x1ce0 kernel/workqueue.c:2153
>   worker_thread+0x143/0x14a0 kernel/workqueue.c:2296
>   kthread+0x357/0x430 kernel/kthread.c:246
>   ret_from_fork+0x3a/0x50 arch/x86/entry/entry_64.S:352
> 
> In fact, it is perfectly fine to bypass GC and destroy xfrm_state
> synchronously on net exit call path, because it is in process context
> and doesn't need a work struct to do any blocking work.
> 
> This patch introduces xfrm_state_put_sync() which simply bypasses
> GC, and lets its callers to decide whether to use this synchronous
> version. On net exit path, xfrm_state_fini() and
> xfrm6_tunnel_net_exit() use it. And, as ipcomp_destroy() itself is
> blocking, it can use xfrm_state_put_sync() directly too.
> 
> Also rename xfrm_state_gc_destroy() to ___xfrm_state_destroy() to
> reflect this change.
> 
> Fixes: b48c05ab5d32 ("xfrm: Fix warning in xfrm6_tunnel_net_exit.")
> Reported-and-tested-by: syzbot+e9aebef558e3ed673...@syzkaller.appspotmail.com
> Cc: Steffen Klassert <steffen.klass...@secunet.com>
> Signed-off-by: Cong Wang <xiyou.wangc...@gmail.com>

Applied, thanks a lot!

Reply via email to