From: Greg Kroah-Hartman Date: Mon, 4 Jul 2022 11:33:20 +0000 (+0200) Subject: 4.14-stable patches X-Git-Tag: v4.9.322~69 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=34eeec41eee022cf79b8470446a6d6b3549756c2;p=thirdparty%2Fkernel%2Fstable-queue.git 4.14-stable patches added patches: net-rose-fix-uaf-bugs-caused-by-timer-handler.patch sunrpc-fix-read_plus-crasher.patch --- diff --git a/queue-4.14/net-rose-fix-uaf-bugs-caused-by-timer-handler.patch b/queue-4.14/net-rose-fix-uaf-bugs-caused-by-timer-handler.patch new file mode 100644 index 00000000000..061b9148ffc --- /dev/null +++ b/queue-4.14/net-rose-fix-uaf-bugs-caused-by-timer-handler.patch @@ -0,0 +1,252 @@ +From 9cc02ede696272c5271a401e4f27c262359bc2f6 Mon Sep 17 00:00:00 2001 +From: Duoming Zhou +Date: Wed, 29 Jun 2022 08:26:40 +0800 +Subject: net: rose: fix UAF bugs caused by timer handler + +From: Duoming Zhou + +commit 9cc02ede696272c5271a401e4f27c262359bc2f6 upstream. + +There are UAF bugs in rose_heartbeat_expiry(), rose_timer_expiry() +and rose_idletimer_expiry(). The root cause is that del_timer() +could not stop the timer handler that is running and the refcount +of sock is not managed properly. + +One of the UAF bugs is shown below: + + (thread 1) | (thread 2) + | rose_bind + | rose_connect + | rose_start_heartbeat +rose_release | (wait a time) + case ROSE_STATE_0 | + rose_destroy_socket | rose_heartbeat_expiry + rose_stop_heartbeat | + sock_put(sk) | ... + sock_put(sk) // FREE | + | bh_lock_sock(sk) // USE + +The sock is deallocated by sock_put() in rose_release() and +then used by bh_lock_sock() in rose_heartbeat_expiry(). + +Although rose_destroy_socket() calls rose_stop_heartbeat(), +it could not stop the timer that is running. + +The KASAN report triggered by POC is shown below: + +BUG: KASAN: use-after-free in _raw_spin_lock+0x5a/0x110 +Write of size 4 at addr ffff88800ae59098 by task swapper/3/0 +... +Call Trace: + + dump_stack_lvl+0xbf/0xee + print_address_description+0x7b/0x440 + print_report+0x101/0x230 + ? irq_work_single+0xbb/0x140 + ? _raw_spin_lock+0x5a/0x110 + kasan_report+0xed/0x120 + ? _raw_spin_lock+0x5a/0x110 + kasan_check_range+0x2bd/0x2e0 + _raw_spin_lock+0x5a/0x110 + rose_heartbeat_expiry+0x39/0x370 + ? rose_start_heartbeat+0xb0/0xb0 + call_timer_fn+0x2d/0x1c0 + ? rose_start_heartbeat+0xb0/0xb0 + expire_timers+0x1f3/0x320 + __run_timers+0x3ff/0x4d0 + run_timer_softirq+0x41/0x80 + __do_softirq+0x233/0x544 + irq_exit_rcu+0x41/0xa0 + sysvec_apic_timer_interrupt+0x8c/0xb0 + + + asm_sysvec_apic_timer_interrupt+0x1b/0x20 +RIP: 0010:default_idle+0xb/0x10 +RSP: 0018:ffffc9000012fea0 EFLAGS: 00000202 +RAX: 000000000000bcae RBX: ffff888006660f00 RCX: 000000000000bcae +RDX: 0000000000000001 RSI: ffffffff843a11c0 RDI: ffffffff843a1180 +RBP: dffffc0000000000 R08: dffffc0000000000 R09: ffffed100da36d46 +R10: dfffe9100da36d47 R11: ffffffff83cf0950 R12: 0000000000000000 +R13: 1ffff11000ccc1e0 R14: ffffffff8542af28 R15: dffffc0000000000 +... +Allocated by task 146: + __kasan_kmalloc+0xc4/0xf0 + sk_prot_alloc+0xdd/0x1a0 + sk_alloc+0x2d/0x4e0 + rose_create+0x7b/0x330 + __sock_create+0x2dd/0x640 + __sys_socket+0xc7/0x270 + __x64_sys_socket+0x71/0x80 + do_syscall_64+0x43/0x90 + entry_SYSCALL_64_after_hwframe+0x46/0xb0 + +Freed by task 152: + kasan_set_track+0x4c/0x70 + kasan_set_free_info+0x1f/0x40 + ____kasan_slab_free+0x124/0x190 + kfree+0xd3/0x270 + __sk_destruct+0x314/0x460 + rose_release+0x2fa/0x3b0 + sock_close+0xcb/0x230 + __fput+0x2d9/0x650 + task_work_run+0xd6/0x160 + exit_to_user_mode_loop+0xc7/0xd0 + exit_to_user_mode_prepare+0x4e/0x80 + syscall_exit_to_user_mode+0x20/0x40 + do_syscall_64+0x4f/0x90 + entry_SYSCALL_64_after_hwframe+0x46/0xb0 + +This patch adds refcount of sock when we use functions +such as rose_start_heartbeat() and so on to start timer, +and decreases the refcount of sock when timer is finished +or deleted by functions such as rose_stop_heartbeat() +and so on. As a result, the UAF bugs could be mitigated. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Duoming Zhou +Tested-by: Duoming Zhou +Link: https://lore.kernel.org/r/20220629002640.5693-1-duoming@zju.edu.cn +Signed-off-by: Paolo Abeni +Signed-off-by: Greg Kroah-Hartman +--- + net/rose/rose_timer.c | 34 +++++++++++++++++++--------------- + 1 file changed, 19 insertions(+), 15 deletions(-) + +--- a/net/rose/rose_timer.c ++++ b/net/rose/rose_timer.c +@@ -34,90 +34,90 @@ static void rose_idletimer_expiry(struct + + void rose_start_heartbeat(struct sock *sk) + { +- del_timer(&sk->sk_timer); ++ sk_stop_timer(sk, &sk->sk_timer); + + sk->sk_timer.data = (unsigned long)sk; + sk->sk_timer.function = &rose_heartbeat_expiry; + sk->sk_timer.expires = jiffies + 5 * HZ; + +- add_timer(&sk->sk_timer); ++ sk_reset_timer(sk, &sk->sk_timer, sk->sk_timer.expires); + } + + void rose_start_t1timer(struct sock *sk) + { + struct rose_sock *rose = rose_sk(sk); + +- del_timer(&rose->timer); ++ sk_stop_timer(sk, &rose->timer); + + rose->timer.function = (TIMER_FUNC_TYPE)rose_timer_expiry; + rose->timer.expires = jiffies + rose->t1; + +- add_timer(&rose->timer); ++ sk_reset_timer(sk, &rose->timer, rose->timer.expires); + } + + void rose_start_t2timer(struct sock *sk) + { + struct rose_sock *rose = rose_sk(sk); + +- del_timer(&rose->timer); ++ sk_stop_timer(sk, &rose->timer); + + rose->timer.function = (TIMER_FUNC_TYPE)rose_timer_expiry; + rose->timer.expires = jiffies + rose->t2; + +- add_timer(&rose->timer); ++ sk_reset_timer(sk, &rose->timer, rose->timer.expires); + } + + void rose_start_t3timer(struct sock *sk) + { + struct rose_sock *rose = rose_sk(sk); + +- del_timer(&rose->timer); ++ sk_stop_timer(sk, &rose->timer); + + rose->timer.function = (TIMER_FUNC_TYPE)rose_timer_expiry; + rose->timer.expires = jiffies + rose->t3; + +- add_timer(&rose->timer); ++ sk_reset_timer(sk, &rose->timer, rose->timer.expires); + } + + void rose_start_hbtimer(struct sock *sk) + { + struct rose_sock *rose = rose_sk(sk); + +- del_timer(&rose->timer); ++ sk_stop_timer(sk, &rose->timer); + + rose->timer.function = (TIMER_FUNC_TYPE)rose_timer_expiry; + rose->timer.expires = jiffies + rose->hb; + +- add_timer(&rose->timer); ++ sk_reset_timer(sk, &rose->timer, rose->timer.expires); + } + + void rose_start_idletimer(struct sock *sk) + { + struct rose_sock *rose = rose_sk(sk); + +- del_timer(&rose->idletimer); ++ sk_stop_timer(sk, &rose->timer); + + if (rose->idle > 0) { + rose->idletimer.function = (TIMER_FUNC_TYPE)rose_idletimer_expiry; + rose->idletimer.expires = jiffies + rose->idle; + +- add_timer(&rose->idletimer); ++ sk_reset_timer(sk, &rose->idletimer, rose->idletimer.expires); + } + } + + void rose_stop_heartbeat(struct sock *sk) + { +- del_timer(&sk->sk_timer); ++ sk_stop_timer(sk, &sk->sk_timer); + } + + void rose_stop_timer(struct sock *sk) + { +- del_timer(&rose_sk(sk)->timer); ++ sk_stop_timer(sk, &rose_sk(sk)->timer); + } + + void rose_stop_idletimer(struct sock *sk) + { +- del_timer(&rose_sk(sk)->idletimer); ++ sk_stop_timer(sk, &rose_sk(sk)->idletimer); + } + + static void rose_heartbeat_expiry(unsigned long param) +@@ -134,6 +134,7 @@ static void rose_heartbeat_expiry(unsign + (sk->sk_state == TCP_LISTEN && sock_flag(sk, SOCK_DEAD))) { + bh_unlock_sock(sk); + rose_destroy_socket(sk); ++ sock_put(sk); + return; + } + break; +@@ -156,6 +157,7 @@ static void rose_heartbeat_expiry(unsign + + rose_start_heartbeat(sk); + bh_unlock_sock(sk); ++ sock_put(sk); + } + + static void rose_timer_expiry(struct timer_list *t) +@@ -185,6 +187,7 @@ static void rose_timer_expiry(struct tim + break; + } + bh_unlock_sock(sk); ++ sock_put(sk); + } + + static void rose_idletimer_expiry(struct timer_list *t) +@@ -209,4 +212,5 @@ static void rose_idletimer_expiry(struct + sock_set_flag(sk, SOCK_DEAD); + } + bh_unlock_sock(sk); ++ sock_put(sk); + } diff --git a/queue-4.14/series b/queue-4.14/series index 5848dacc03c..10d697ba77c 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -2,3 +2,5 @@ nvdimm-fix-badblocks-clear-off-by-one-error.patch dm-raid-fix-accesses-beyond-end-of-raid-member-array.patch dm-raid-fix-kasan-warning-in-raid5_add_disks.patch s390-archrandom-simplify-back-to-earlier-design-and-initialize-earlier.patch +sunrpc-fix-read_plus-crasher.patch +net-rose-fix-uaf-bugs-caused-by-timer-handler.patch diff --git a/queue-4.14/sunrpc-fix-read_plus-crasher.patch b/queue-4.14/sunrpc-fix-read_plus-crasher.patch new file mode 100644 index 00000000000..ff2338cf38c --- /dev/null +++ b/queue-4.14/sunrpc-fix-read_plus-crasher.patch @@ -0,0 +1,34 @@ +From a23dd544debcda4ee4a549ec7de59e85c3c8345c Mon Sep 17 00:00:00 2001 +From: Chuck Lever +Date: Thu, 30 Jun 2022 16:48:18 -0400 +Subject: SUNRPC: Fix READ_PLUS crasher + +From: Chuck Lever + +commit a23dd544debcda4ee4a549ec7de59e85c3c8345c upstream. + +Looks like there are still cases when "space_left - frag1bytes" can +legitimately exceed PAGE_SIZE. Ensure that xdr->end always remains +within the current encode buffer. + +Reported-by: Bruce Fields +Reported-by: Zorro Lang +Link: https://bugzilla.kernel.org/show_bug.cgi?id=216151 +Fixes: 6c254bf3b637 ("SUNRPC: Fix the calculation of xdr->end in xdr_get_next_encode_buffer()") +Signed-off-by: Chuck Lever +Signed-off-by: Greg Kroah-Hartman +--- + net/sunrpc/xdr.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/sunrpc/xdr.c ++++ b/net/sunrpc/xdr.c +@@ -544,7 +544,7 @@ static __be32 *xdr_get_next_encode_buffe + */ + xdr->p = (void *)p + frag2bytes; + space_left = xdr->buf->buflen - xdr->buf->len; +- if (space_left - nbytes >= PAGE_SIZE) ++ if (space_left - frag1bytes >= PAGE_SIZE) + xdr->end = (void *)p + PAGE_SIZE; + else + xdr->end = (void *)p + space_left - frag1bytes;