From 480866065d359fd8d00aae8e6fb975dbb4bd6c98 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 20 Feb 2023 12:21:02 +0100 Subject: [PATCH] 5.15-stable patches added patches: alarmtimer-prevent-starvation-by-small-intervals-and-sig_ign.patch kvm-initialize-all-of-the-kvm_debugregs-structure-before-sending-it-to-userspace.patch --- ...ation-by-small-intervals-and-sig_ign.patch | 132 ++++++++++++++++++ ...cture-before-sending-it-to-userspace.patch | 53 +++++++ queue-5.15/series | 2 + 3 files changed, 187 insertions(+) create mode 100644 queue-5.15/alarmtimer-prevent-starvation-by-small-intervals-and-sig_ign.patch create mode 100644 queue-5.15/kvm-initialize-all-of-the-kvm_debugregs-structure-before-sending-it-to-userspace.patch diff --git a/queue-5.15/alarmtimer-prevent-starvation-by-small-intervals-and-sig_ign.patch b/queue-5.15/alarmtimer-prevent-starvation-by-small-intervals-and-sig_ign.patch new file mode 100644 index 00000000000..bc89e500310 --- /dev/null +++ b/queue-5.15/alarmtimer-prevent-starvation-by-small-intervals-and-sig_ign.patch @@ -0,0 +1,132 @@ +From d125d1349abeb46945dc5e98f7824bf688266f13 Mon Sep 17 00:00:00 2001 +From: Thomas Gleixner +Date: Thu, 9 Feb 2023 23:25:49 +0100 +Subject: alarmtimer: Prevent starvation by small intervals and SIG_IGN + +From: Thomas Gleixner + +commit d125d1349abeb46945dc5e98f7824bf688266f13 upstream. + +syzbot reported a RCU stall which is caused by setting up an alarmtimer +with a very small interval and ignoring the signal. The reproducer arms the +alarm timer with a relative expiry of 8ns and an interval of 9ns. Not a +problem per se, but that's an issue when the signal is ignored because then +the timer is immediately rearmed because there is no way to delay that +rearming to the signal delivery path. See posix_timer_fn() and commit +58229a189942 ("posix-timers: Prevent softirq starvation by small intervals +and SIG_IGN") for details. + +The reproducer does not set SIG_IGN explicitely, but it sets up the timers +signal with SIGCONT. That has the same effect as explicitely setting +SIG_IGN for a signal as SIGCONT is ignored if there is no handler set and +the task is not ptraced. + +The log clearly shows that: + + [pid 5102] --- SIGCONT {si_signo=SIGCONT, si_code=SI_TIMER, si_timerid=0, si_overrun=316014, si_int=0, si_ptr=NULL} --- + +It works because the tasks are traced and therefore the signal is queued so +the tracer can see it, which delays the restart of the timer to the signal +delivery path. But then the tracer is killed: + + [pid 5087] kill(-5102, SIGKILL + ... + ./strace-static-x86_64: Process 5107 detached + +and after it's gone the stall can be observed: + + syzkaller login: [ 79.439102][ C0] hrtimer: interrupt took 68471 ns + [ 184.460538][ C1] rcu: INFO: rcu_preempt detected stalls on CPUs/tasks: + ... + [ 184.658237][ C1] rcu: Stack dump where RCU GP kthread last ran: + [ 184.664574][ C1] Sending NMI from CPU 1 to CPUs 0: + [ 184.669821][ C0] NMI backtrace for cpu 0 + [ 184.669831][ C0] CPU: 0 PID: 5108 Comm: syz-executor192 Not tainted 6.2.0-rc6-next-20230203-syzkaller #0 + ... + [ 184.670036][ C0] Call Trace: + [ 184.670041][ C0] + [ 184.670045][ C0] alarmtimer_fired+0x327/0x670 + +posix_timer_fn() prevents that by checking whether the interval for +timers which have the signal ignored is smaller than a jiffie and +artifically delay it by shifting the next expiry out by a jiffie. That's +accurate vs. the overrun accounting, but slightly inaccurate +vs. timer_gettimer(2). + +The comment in that function says what needs to be done and there was a fix +available for the regular userspace induced SIG_IGN mechanism, but that did +not work due to the implicit ignore for SIGCONT and similar signals. This +needs to be worked on, but for now the only available workaround is to do +exactly what posix_timer_fn() does: + +Increase the interval of self-rearming timers, which have their signal +ignored, to at least a jiffie. + +Interestingly this has been fixed before via commit ff86bf0c65f1 +("alarmtimer: Rate limit periodic intervals") already, but that fix got +lost in a later rework. + +Reported-by: syzbot+b9564ba6e8e00694511b@syzkaller.appspotmail.com +Fixes: f2c45807d399 ("alarmtimer: Switch over to generic set/get/rearm routine") +Signed-off-by: Thomas Gleixner +Acked-by: John Stultz +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/87k00q1no2.ffs@tglx +Signed-off-by: Greg Kroah-Hartman +--- + kernel/time/alarmtimer.c | 33 +++++++++++++++++++++++++++++---- + 1 file changed, 29 insertions(+), 4 deletions(-) + +--- a/kernel/time/alarmtimer.c ++++ b/kernel/time/alarmtimer.c +@@ -470,11 +470,35 @@ u64 alarm_forward(struct alarm *alarm, k + } + EXPORT_SYMBOL_GPL(alarm_forward); + +-u64 alarm_forward_now(struct alarm *alarm, ktime_t interval) ++static u64 __alarm_forward_now(struct alarm *alarm, ktime_t interval, bool throttle) + { + struct alarm_base *base = &alarm_bases[alarm->type]; ++ ktime_t now = base->get_ktime(); ++ ++ if (IS_ENABLED(CONFIG_HIGH_RES_TIMERS) && throttle) { ++ /* ++ * Same issue as with posix_timer_fn(). Timers which are ++ * periodic but the signal is ignored can starve the system ++ * with a very small interval. The real fix which was ++ * promised in the context of posix_timer_fn() never ++ * materialized, but someone should really work on it. ++ * ++ * To prevent DOS fake @now to be 1 jiffie out which keeps ++ * the overrun accounting correct but creates an ++ * inconsistency vs. timer_gettime(2). ++ */ ++ ktime_t kj = NSEC_PER_SEC / HZ; ++ ++ if (interval < kj) ++ now = ktime_add(now, kj); ++ } ++ ++ return alarm_forward(alarm, now, interval); ++} + +- return alarm_forward(alarm, base->get_ktime(), interval); ++u64 alarm_forward_now(struct alarm *alarm, ktime_t interval) ++{ ++ return __alarm_forward_now(alarm, interval, false); + } + EXPORT_SYMBOL_GPL(alarm_forward_now); + +@@ -551,9 +575,10 @@ static enum alarmtimer_restart alarm_han + if (posix_timer_event(ptr, si_private) && ptr->it_interval) { + /* + * Handle ignored signals and rearm the timer. This will go +- * away once we handle ignored signals proper. ++ * away once we handle ignored signals proper. Ensure that ++ * small intervals cannot starve the system. + */ +- ptr->it_overrun += alarm_forward_now(alarm, ptr->it_interval); ++ ptr->it_overrun += __alarm_forward_now(alarm, ptr->it_interval, true); + ++ptr->it_requeue_pending; + ptr->it_active = 1; + result = ALARMTIMER_RESTART; diff --git a/queue-5.15/kvm-initialize-all-of-the-kvm_debugregs-structure-before-sending-it-to-userspace.patch b/queue-5.15/kvm-initialize-all-of-the-kvm_debugregs-structure-before-sending-it-to-userspace.patch new file mode 100644 index 00000000000..9cb0e77de51 --- /dev/null +++ b/queue-5.15/kvm-initialize-all-of-the-kvm_debugregs-structure-before-sending-it-to-userspace.patch @@ -0,0 +1,53 @@ +From 2c10b61421a28e95a46ab489fd56c0f442ff6952 Mon Sep 17 00:00:00 2001 +From: Greg Kroah-Hartman +Date: Tue, 14 Feb 2023 11:33:04 +0100 +Subject: kvm: initialize all of the kvm_debugregs structure before sending it to userspace + +From: Greg Kroah-Hartman + +commit 2c10b61421a28e95a46ab489fd56c0f442ff6952 upstream. + +When calling the KVM_GET_DEBUGREGS ioctl, on some configurations, there +might be some unitialized portions of the kvm_debugregs structure that +could be copied to userspace. Prevent this as is done in the other kvm +ioctls, by setting the whole structure to 0 before copying anything into +it. + +Bonus is that this reduces the lines of code as the explicit flag +setting and reserved space zeroing out can be removed. + +Cc: Sean Christopherson +Cc: Paolo Bonzini +Cc: Thomas Gleixner +Cc: Ingo Molnar +Cc: Borislav Petkov +Cc: Dave Hansen +Cc: +Cc: "H. Peter Anvin" +Cc: stable +Reported-by: Xingyuan Mo +Signed-off-by: Greg Kroah-Hartman +Message-Id: <20230214103304.3689213-1-gregkh@linuxfoundation.org> +Tested-by: Xingyuan Mo +Signed-off-by: Paolo Bonzini +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kvm/x86.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -4821,12 +4821,11 @@ static void kvm_vcpu_ioctl_x86_get_debug + { + unsigned long val; + ++ memset(dbgregs, 0, sizeof(*dbgregs)); + memcpy(dbgregs->db, vcpu->arch.db, sizeof(vcpu->arch.db)); + kvm_get_dr(vcpu, 6, &val); + dbgregs->dr6 = val; + dbgregs->dr7 = vcpu->arch.dr7; +- dbgregs->flags = 0; +- memset(&dbgregs->reserved, 0, sizeof(dbgregs->reserved)); + } + + static int kvm_vcpu_ioctl_x86_set_debugregs(struct kvm_vcpu *vcpu, diff --git a/queue-5.15/series b/queue-5.15/series index 25ba9f448db..577484b3431 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -76,3 +76,5 @@ flow_offload-fill-flags-to-action-structure.patch net-sched-act_ctinfo-use-percpu-stats.patch i40e-add-checking-for-null-for-nlmsg_find_attr.patch net-sched-tcindex-search-key-must-be-16-bits.patch +kvm-initialize-all-of-the-kvm_debugregs-structure-before-sending-it-to-userspace.patch +alarmtimer-prevent-starvation-by-small-intervals-and-sig_ign.patch -- 2.47.2