From: Greg Kroah-Hartman Date: Thu, 23 Jun 2022 10:49:28 +0000 (+0200) Subject: 4.14-stable patches X-Git-Tag: v4.9.320~27 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6b6f42ecf4d7c26a37f66d9310b1b2e759644b58;p=thirdparty%2Fkernel%2Fstable-queue.git 4.14-stable patches added patches: l2tp-don-t-use-inet_shutdown-on-ppp-session-destroy.patch l2tp-fix-race-in-pppol2tp_release-with-session-object-destroy.patch --- diff --git a/queue-4.14/l2tp-don-t-use-inet_shutdown-on-ppp-session-destroy.patch b/queue-4.14/l2tp-don-t-use-inet_shutdown-on-ppp-session-destroy.patch new file mode 100644 index 00000000000..078b06d8d3a --- /dev/null +++ b/queue-4.14/l2tp-don-t-use-inet_shutdown-on-ppp-session-destroy.patch @@ -0,0 +1,118 @@ +From 225eb26489d05c679a4c4197ffcb81c81e9dcaf4 Mon Sep 17 00:00:00 2001 +From: James Chapman +Date: Fri, 23 Feb 2018 17:45:44 +0000 +Subject: l2tp: don't use inet_shutdown on ppp session destroy + +From: James Chapman + +commit 225eb26489d05c679a4c4197ffcb81c81e9dcaf4 upstream. + +Previously, if a ppp session was closed, we called inet_shutdown to mark +the socket as unconnected such that userspace would get errors and +then close the socket. This could race with userspace closing the +socket. Instead, leave userspace to close the socket in its own time +(our session will be detached anyway). + +BUG: KASAN: use-after-free in inet_shutdown+0x5d/0x1c0 +Read of size 4 at addr ffff880010ea3ac0 by task syzbot_347bd5ac/8296 + +CPU: 3 PID: 8296 Comm: syzbot_347bd5ac Not tainted 4.16.0-rc1+ #91 +Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006 +Call Trace: + dump_stack+0x101/0x157 + ? inet_shutdown+0x5d/0x1c0 + print_address_description+0x78/0x260 + ? inet_shutdown+0x5d/0x1c0 + kasan_report+0x240/0x360 + __asan_load4+0x78/0x80 + inet_shutdown+0x5d/0x1c0 + ? pppol2tp_show+0x80/0x80 + pppol2tp_session_close+0x68/0xb0 + l2tp_tunnel_closeall+0x199/0x210 + ? udp_v6_flush_pending_frames+0x90/0x90 + l2tp_udp_encap_destroy+0x6b/0xc0 + ? l2tp_tunnel_del_work+0x2e0/0x2e0 + udpv6_destroy_sock+0x8c/0x90 + sk_common_release+0x47/0x190 + udp_lib_close+0x15/0x20 + inet_release+0x85/0xd0 + inet6_release+0x43/0x60 + sock_release+0x53/0x100 + ? sock_alloc_file+0x260/0x260 + sock_close+0x1b/0x20 + __fput+0x19f/0x380 + ____fput+0x1a/0x20 + task_work_run+0xd2/0x110 + exit_to_usermode_loop+0x18d/0x190 + do_syscall_64+0x389/0x3b0 + entry_SYSCALL_64_after_hwframe+0x26/0x9b +RIP: 0033:0x7fe240a45259 +RSP: 002b:00007fe241132df8 EFLAGS: 00000297 ORIG_RAX: 0000000000000003 +RAX: 0000000000000000 RBX: 0000000000000000 RCX: 00007fe240a45259 +RDX: 00007fe240a45259 RSI: 0000000000000000 RDI: 00000000000000a5 +RBP: 00007fe241132e20 R08: 00007fe241133700 R09: 0000000000000000 +R10: 00007fe241133700 R11: 0000000000000297 R12: 0000000000000000 +R13: 00007ffc49aff84f R14: 0000000000000000 R15: 00007fe241141040 + +Allocated by task 8331: + save_stack+0x43/0xd0 + kasan_kmalloc+0xad/0xe0 + kasan_slab_alloc+0x12/0x20 + kmem_cache_alloc+0x144/0x3e0 + sock_alloc_inode+0x22/0x130 + alloc_inode+0x3d/0xf0 + new_inode_pseudo+0x1c/0x90 + sock_alloc+0x30/0x110 + __sock_create+0xaa/0x4c0 + SyS_socket+0xbe/0x130 + do_syscall_64+0x128/0x3b0 + entry_SYSCALL_64_after_hwframe+0x26/0x9b + +Freed by task 8314: + save_stack+0x43/0xd0 + __kasan_slab_free+0x11a/0x170 + kasan_slab_free+0xe/0x10 + kmem_cache_free+0x88/0x2b0 + sock_destroy_inode+0x49/0x50 + destroy_inode+0x77/0xb0 + evict+0x285/0x340 + iput+0x429/0x530 + dentry_unlink_inode+0x28c/0x2c0 + __dentry_kill+0x1e3/0x2f0 + dput.part.21+0x500/0x560 + dput+0x24/0x30 + __fput+0x2aa/0x380 + ____fput+0x1a/0x20 + task_work_run+0xd2/0x110 + exit_to_usermode_loop+0x18d/0x190 + do_syscall_64+0x389/0x3b0 + entry_SYSCALL_64_after_hwframe+0x26/0x9b + +Fixes: fd558d186df2c ("l2tp: Split pppol2tp patch into separate l2tp and ppp parts") +Signed-off-by: James Chapman +Signed-off-by: David S. Miller +Cc: Lee Jones +Signed-off-by: Greg Kroah-Hartman +--- + net/l2tp/l2tp_ppp.c | 10 ---------- + 1 file changed, 10 deletions(-) + +--- a/net/l2tp/l2tp_ppp.c ++++ b/net/l2tp/l2tp_ppp.c +@@ -439,16 +439,6 @@ abort: + */ + static void pppol2tp_session_close(struct l2tp_session *session) + { +- struct sock *sk; +- +- BUG_ON(session->magic != L2TP_SESSION_MAGIC); +- +- sk = pppol2tp_session_get_sock(session); +- if (sk) { +- if (sk->sk_socket) +- inet_shutdown(sk->sk_socket, SEND_SHUTDOWN); +- sock_put(sk); +- } + } + + /* Really kill the session socket. (Called from sock_put() if diff --git a/queue-4.14/l2tp-fix-race-in-pppol2tp_release-with-session-object-destroy.patch b/queue-4.14/l2tp-fix-race-in-pppol2tp_release-with-session-object-destroy.patch new file mode 100644 index 00000000000..3d5733c9768 --- /dev/null +++ b/queue-4.14/l2tp-fix-race-in-pppol2tp_release-with-session-object-destroy.patch @@ -0,0 +1,172 @@ +From d02ba2a6110c530a32926af8ad441111774d2893 Mon Sep 17 00:00:00 2001 +From: James Chapman +Date: Fri, 23 Feb 2018 17:45:46 +0000 +Subject: l2tp: fix race in pppol2tp_release with session object destroy + +From: James Chapman + +commit d02ba2a6110c530a32926af8ad441111774d2893 upstream. + +pppol2tp_release uses call_rcu to put the final ref on its socket. But +the session object doesn't hold a ref on the session socket so may be +freed while the pppol2tp_put_sk RCU callback is scheduled. Fix this by +having the session hold a ref on its socket until the session is +destroyed. It is this ref that is dropped via call_rcu. + +Sessions are also deleted via l2tp_tunnel_closeall. This must now also put +the final ref via call_rcu. So move the call_rcu call site into +pppol2tp_session_close so that this happens in both destroy paths. A +common destroy path should really be implemented, perhaps with +l2tp_tunnel_closeall calling l2tp_session_delete like pppol2tp_release +does, but this will be looked at later. + +ODEBUG: activate active (active state 1) object type: rcu_head hint: (null) +WARNING: CPU: 3 PID: 13407 at lib/debugobjects.c:291 debug_print_object+0x166/0x220 +Modules linked in: +CPU: 3 PID: 13407 Comm: syzbot_19c09769 Not tainted 4.16.0-rc2+ #38 +Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006 +RIP: 0010:debug_print_object+0x166/0x220 +RSP: 0018:ffff880013647a00 EFLAGS: 00010082 +RAX: dffffc0000000008 RBX: 0000000000000003 RCX: ffffffff814d3333 +RDX: 0000000000000000 RSI: 0000000000000001 RDI: ffff88001a59f6d0 +RBP: ffff880013647a40 R08: 0000000000000000 R09: 0000000000000001 +R10: ffff8800136479a8 R11: 0000000000000000 R12: 0000000000000001 +R13: ffffffff86161420 R14: ffffffff85648b60 R15: 0000000000000000 +FS: 0000000000000000(0000) GS:ffff88001a580000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 0000000020e77000 CR3: 0000000006022000 CR4: 00000000000006e0 +Call Trace: + debug_object_activate+0x38b/0x530 + ? debug_object_assert_init+0x3b0/0x3b0 + ? __mutex_unlock_slowpath+0x85/0x8b0 + ? pppol2tp_session_destruct+0x110/0x110 + __call_rcu.constprop.66+0x39/0x890 + ? __call_rcu.constprop.66+0x39/0x890 + call_rcu_sched+0x17/0x20 + pppol2tp_release+0x2c7/0x440 + ? fcntl_setlk+0xca0/0xca0 + ? sock_alloc_file+0x340/0x340 + sock_release+0x92/0x1e0 + sock_close+0x1b/0x20 + __fput+0x296/0x6e0 + ____fput+0x1a/0x20 + task_work_run+0x127/0x1a0 + do_exit+0x7f9/0x2ce0 + ? SYSC_connect+0x212/0x310 + ? mm_update_next_owner+0x690/0x690 + ? up_read+0x1f/0x40 + ? __do_page_fault+0x3c8/0xca0 + do_group_exit+0x10d/0x330 + ? do_group_exit+0x330/0x330 + SyS_exit_group+0x22/0x30 + do_syscall_64+0x1e0/0x730 + ? trace_hardirqs_off_thunk+0x1a/0x1c + entry_SYSCALL_64_after_hwframe+0x42/0xb7 +RIP: 0033:0x7f362e471259 +RSP: 002b:00007ffe389abe08 EFLAGS: 00000202 ORIG_RAX: 00000000000000e7 +RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f362e471259 +RDX: 00007f362e471259 RSI: 000000000000002e RDI: 0000000000000000 +RBP: 00007ffe389abe30 R08: 0000000000000000 R09: 00007f362e944270 +R10: 0000000000000000 R11: 0000000000000202 R12: 0000000000400b60 +R13: 00007ffe389abf50 R14: 0000000000000000 R15: 0000000000000000 +Code: 8d 3c dd a0 8f 64 85 48 89 fa 48 c1 ea 03 80 3c 02 00 75 7b 48 8b 14 dd a0 8f 64 85 4c 89 f6 48 c7 c7 20 85 64 85 e +8 2a 55 14 ff <0f> 0b 83 05 ad 2a 68 04 01 48 83 c4 18 5b 41 5c 41 5d 41 5e 41 + +Fixes: ee40fb2e1eb5b ("l2tp: protect sock pointer of struct pppol2tp_session with RCU") +Signed-off-by: James Chapman +Signed-off-by: David S. Miller +Cc: Lee Jones +Signed-off-by: Greg Kroah-Hartman +--- + net/l2tp/l2tp_ppp.c | 52 +++++++++++++++++++++++++++------------------------- + 1 file changed, 27 insertions(+), 25 deletions(-) + +--- a/net/l2tp/l2tp_ppp.c ++++ b/net/l2tp/l2tp_ppp.c +@@ -435,10 +435,28 @@ abort: + * Session (and tunnel control) socket create/destroy. + *****************************************************************************/ + ++static void pppol2tp_put_sk(struct rcu_head *head) ++{ ++ struct pppol2tp_session *ps; ++ ++ ps = container_of(head, typeof(*ps), rcu); ++ sock_put(ps->__sk); ++} ++ + /* Called by l2tp_core when a session socket is being closed. + */ + static void pppol2tp_session_close(struct l2tp_session *session) + { ++ struct pppol2tp_session *ps; ++ ++ ps = l2tp_session_priv(session); ++ mutex_lock(&ps->sk_lock); ++ ps->__sk = rcu_dereference_protected(ps->sk, ++ lockdep_is_held(&ps->sk_lock)); ++ RCU_INIT_POINTER(ps->sk, NULL); ++ if (ps->__sk) ++ call_rcu(&ps->rcu, pppol2tp_put_sk); ++ mutex_unlock(&ps->sk_lock); + } + + /* Really kill the session socket. (Called from sock_put() if +@@ -458,14 +476,6 @@ static void pppol2tp_session_destruct(st + } + } + +-static void pppol2tp_put_sk(struct rcu_head *head) +-{ +- struct pppol2tp_session *ps; +- +- ps = container_of(head, typeof(*ps), rcu); +- sock_put(ps->__sk); +-} +- + /* Called when the PPPoX socket (session) is closed. + */ + static int pppol2tp_release(struct socket *sock) +@@ -489,26 +499,17 @@ static int pppol2tp_release(struct socke + sock_orphan(sk); + sock->sk = NULL; + ++ /* If the socket is associated with a session, ++ * l2tp_session_delete will call pppol2tp_session_close which ++ * will drop the session's ref on the socket. ++ */ + session = pppol2tp_sock_to_session(sk); +- +- if (session != NULL) { +- struct pppol2tp_session *ps; +- ++ if (session) { + l2tp_session_delete(session); +- +- ps = l2tp_session_priv(session); +- mutex_lock(&ps->sk_lock); +- ps->__sk = rcu_dereference_protected(ps->sk, +- lockdep_is_held(&ps->sk_lock)); +- RCU_INIT_POINTER(ps->sk, NULL); +- mutex_unlock(&ps->sk_lock); +- call_rcu(&ps->rcu, pppol2tp_put_sk); +- +- /* Rely on the sock_put() call at the end of the function for +- * dropping the reference held by pppol2tp_sock_to_session(). +- * The last reference will be dropped by pppol2tp_put_sk(). +- */ ++ /* drop the ref obtained by pppol2tp_sock_to_session */ ++ sock_put(sk); + } ++ + release_sock(sk); + + /* This will delete the session context via +@@ -820,6 +821,7 @@ static int pppol2tp_connect(struct socke + + out_no_ppp: + /* This is how we get the session context from the socket. */ ++ sock_hold(sk); + sk->sk_user_data = session; + rcu_assign_pointer(ps->sk, sk); + mutex_unlock(&ps->sk_lock); diff --git a/queue-4.14/series b/queue-4.14/series index 7181ad155b9..b66008cfe6f 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -225,3 +225,5 @@ ext4-fix-bug_on-ext4_mb_use_inode_pa.patch ext4-make-variable-count-signed.patch ext4-add-reserved-gdt-blocks-check.patch virtio-pci-remove-wrong-address-verification-in-vp_del_vqs.patch +l2tp-don-t-use-inet_shutdown-on-ppp-session-destroy.patch +l2tp-fix-race-in-pppol2tp_release-with-session-object-destroy.patch