diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2019-09-02 22:26:09 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2019-09-02 22:26:09 +0200 |
commit | f7a9241155211c41fc84b293c8cd0a52c95b2108 (patch) | |
tree | 33921b16b3643dbeb7e274c0a6f66067240fdee9 | |
parent | 195d05e43a203147cb2f094ce2b4122dec0a5907 (diff) | |
download | queue-3.18-f7a9241155211c41fc84b293c8cd0a52c95b2108.tar.gz |
more patches
7 files changed, 363 insertions, 155 deletions
diff --git a/alsa-seq-fix-potential-concurrent-access-to-the-deleted-pool.patch b/alsa-seq-fix-potential-concurrent-access-to-the-deleted-pool.patch new file mode 100644 index 0000000..0092e62 --- /dev/null +++ b/alsa-seq-fix-potential-concurrent-access-to-the-deleted-pool.patch @@ -0,0 +1,70 @@ +From 75545304eba6a3d282f923b96a466dc25a81e359 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai <tiwai@suse.de> +Date: Sun, 25 Aug 2019 09:21:44 +0200 +Subject: ALSA: seq: Fix potential concurrent access to the deleted pool + +From: Takashi Iwai <tiwai@suse.de> + +commit 75545304eba6a3d282f923b96a466dc25a81e359 upstream. + +The input pool of a client might be deleted via the resize ioctl, the +the access to it should be covered by the proper locks. Currently the +only missing place is the call in snd_seq_ioctl_get_client_pool(), and +this patch papers over it. + +Reported-by: syzbot+4a75454b9ca2777f35c7@syzkaller.appspotmail.com +Cc: <stable@vger.kernel.org> +Signed-off-by: Takashi Iwai <tiwai@suse.de> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> + +--- + sound/core/seq/seq_clientmgr.c | 3 +-- + sound/core/seq/seq_fifo.c | 17 +++++++++++++++++ + sound/core/seq/seq_fifo.h | 2 ++ + 3 files changed, 20 insertions(+), 2 deletions(-) + +--- a/sound/core/seq/seq_clientmgr.c ++++ b/sound/core/seq/seq_clientmgr.c +@@ -1911,8 +1911,7 @@ static int snd_seq_ioctl_get_client_pool + if (cptr->type == USER_CLIENT) { + info.input_pool = cptr->data.user.fifo_pool_size; + info.input_free = info.input_pool; +- if (cptr->data.user.fifo) +- info.input_free = snd_seq_unused_cells(cptr->data.user.fifo->pool); ++ info.input_free = snd_seq_fifo_unused_cells(cptr->data.user.fifo); + } else { + info.input_pool = 0; + info.input_free = 0; +--- a/sound/core/seq/seq_fifo.c ++++ b/sound/core/seq/seq_fifo.c +@@ -275,3 +275,20 @@ int snd_seq_fifo_resize(struct snd_seq_f + + return 0; + } ++ ++/* get the number of unused cells safely */ ++int snd_seq_fifo_unused_cells(struct snd_seq_fifo *f) ++{ ++ unsigned long flags; ++ int cells; ++ ++ if (!f) ++ return 0; ++ ++ snd_use_lock_use(&f->use_lock); ++ spin_lock_irqsave(&f->lock, flags); ++ cells = snd_seq_unused_cells(f->pool); ++ spin_unlock_irqrestore(&f->lock, flags); ++ snd_use_lock_free(&f->use_lock); ++ return cells; ++} +--- a/sound/core/seq/seq_fifo.h ++++ b/sound/core/seq/seq_fifo.h +@@ -68,5 +68,7 @@ int snd_seq_fifo_poll_wait(struct snd_se + /* resize pool in fifo */ + int snd_seq_fifo_resize(struct snd_seq_fifo *f, int poolsize); + ++/* get the number of unused cells safely */ ++int snd_seq_fifo_unused_cells(struct snd_seq_fifo *f); + + #endif diff --git a/alsa-usb-audio-fix-a-stack-buffer-overflow-bug-in-check_input_term.patch b/alsa-usb-audio-fix-a-stack-buffer-overflow-bug-in-check_input_term.patch new file mode 100644 index 0000000..eb8d971 --- /dev/null +++ b/alsa-usb-audio-fix-a-stack-buffer-overflow-bug-in-check_input_term.patch @@ -0,0 +1,104 @@ +From 19bce474c45be69a284ecee660aa12d8f1e88f18 Mon Sep 17 00:00:00 2001 +From: Hui Peng <benquike@gmail.com> +Date: Thu, 15 Aug 2019 00:31:34 -0400 +Subject: ALSA: usb-audio: Fix a stack buffer overflow bug in check_input_term + +From: Hui Peng <benquike@gmail.com> + +commit 19bce474c45be69a284ecee660aa12d8f1e88f18 upstream. + +`check_input_term` recursively calls itself with input from +device side (e.g., uac_input_terminal_descriptor.bCSourceID) +as argument (id). In `check_input_term`, if `check_input_term` +is called with the same `id` argument as the caller, it triggers +endless recursive call, resulting kernel space stack overflow. + +This patch fixes the bug by adding a bitmap to `struct mixer_build` +to keep track of the checked ids and stop the execution if some id +has been checked (similar to how parse_audio_unit handles unitid +argument). + +Reported-by: Hui Peng <benquike@gmail.com> +Reported-by: Mathias Payer <mathias.payer@nebelwelt.net> +Signed-off-by: Hui Peng <benquike@gmail.com> +Cc: <stable@vger.kernel.org> +Signed-off-by: Takashi Iwai <tiwai@suse.de> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> + + +--- + sound/usb/mixer.c | 29 ++++++++++++++++++++++++----- + 1 file changed, 24 insertions(+), 5 deletions(-) + +--- a/sound/usb/mixer.c ++++ b/sound/usb/mixer.c +@@ -81,6 +81,7 @@ struct mixer_build { + unsigned char *buffer; + unsigned int buflen; + DECLARE_BITMAP(unitbitmap, MAX_ID_ELEMS); ++ DECLARE_BITMAP(termbitmap, MAX_ID_ELEMS); + struct usb_audio_term oterm; + const struct usbmix_name_map *map; + const struct usbmix_selector_map *selector_map; +@@ -695,15 +696,24 @@ static int get_term_name(struct mixer_bu + * parse the source unit recursively until it reaches to a terminal + * or a branched unit. + */ +-static int check_input_term(struct mixer_build *state, int id, ++static int __check_input_term(struct mixer_build *state, int id, + struct usb_audio_term *term) + { + int err; + void *p1; ++ unsigned char *hdr; + + memset(term, 0, sizeof(*term)); +- while ((p1 = find_audio_control_unit(state, id)) != NULL) { +- unsigned char *hdr = p1; ++ for (;;) { ++ /* a loop in the terminal chain? */ ++ if (test_and_set_bit(id, state->termbitmap)) ++ return -EINVAL; ++ ++ p1 = find_audio_control_unit(state, id); ++ if (!p1) ++ break; ++ ++ hdr = p1; + term->id = id; + switch (hdr[2]) { + case UAC_INPUT_TERMINAL: +@@ -721,7 +731,7 @@ static int check_input_term(struct mixer + term->name = d->iTerminal; + + /* call recursively to get the clock selectors */ +- err = check_input_term(state, d->bCSourceID, term); ++ err = __check_input_term(state, d->bCSourceID, term); + if (err < 0) + return err; + } +@@ -744,7 +754,7 @@ static int check_input_term(struct mixer + case UAC2_CLOCK_SELECTOR: { + struct uac_selector_unit_descriptor *d = p1; + /* call recursively to retrieve the channel info */ +- err = check_input_term(state, d->baSourceID[0], term); ++ err = __check_input_term(state, d->baSourceID[0], term); + if (err < 0) + return err; + term->type = d->bDescriptorSubtype << 16; /* virtual type */ +@@ -791,6 +801,15 @@ static int check_input_term(struct mixer + return -ENODEV; + } + ++ ++static int check_input_term(struct mixer_build *state, int id, ++ struct usb_audio_term *term) ++{ ++ memset(term, 0, sizeof(*term)); ++ memset(state->termbitmap, 0, sizeof(state->termbitmap)); ++ return __check_input_term(state, id, term); ++} ++ + /* + * Feature Unit + */ diff --git a/alsa-usb-audio-fix-an-oob-bug-in-parse_audio_mixer_unit.patch b/alsa-usb-audio-fix-an-oob-bug-in-parse_audio_mixer_unit.patch new file mode 100644 index 0000000..ba0ec06 --- /dev/null +++ b/alsa-usb-audio-fix-an-oob-bug-in-parse_audio_mixer_unit.patch @@ -0,0 +1,52 @@ +From daac07156b330b18eb5071aec4b3ddca1c377f2c Mon Sep 17 00:00:00 2001 +From: Hui Peng <benquike@gmail.com> +Date: Tue, 13 Aug 2019 22:34:04 -0400 +Subject: ALSA: usb-audio: Fix an OOB bug in parse_audio_mixer_unit + +From: Hui Peng <benquike@gmail.com> + +commit daac07156b330b18eb5071aec4b3ddca1c377f2c upstream. + +The `uac_mixer_unit_descriptor` shown as below is read from the +device side. In `parse_audio_mixer_unit`, `baSourceID` field is +accessed from index 0 to `bNrInPins` - 1, the current implementation +assumes that descriptor is always valid (the length of descriptor +is no shorter than 5 + `bNrInPins`). If a descriptor read from +the device side is invalid, it may trigger out-of-bound memory +access. + +``` +struct uac_mixer_unit_descriptor { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubtype; + __u8 bUnitID; + __u8 bNrInPins; + __u8 baSourceID[]; +} +``` + +This patch fixes the bug by add a sanity check on the length of +the descriptor. + +Reported-by: Hui Peng <benquike@gmail.com> +Reported-by: Mathias Payer <mathias.payer@nebelwelt.net> +Cc: <stable@vger.kernel.org> +Signed-off-by: Hui Peng <benquike@gmail.com> +Signed-off-by: Takashi Iwai <tiwai@suse.de> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> + +--- + sound/usb/mixer.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/sound/usb/mixer.c ++++ b/sound/usb/mixer.c +@@ -1622,6 +1622,7 @@ static int parse_audio_mixer_unit(struct + int pin, ich, err; + + if (desc->bLength < 11 || !(input_pins = desc->bNrInPins) || ++ desc->bLength < sizeof(*desc) + desc->bNrInPins || + !(num_outs = uac_mixer_unit_bNrChannels(desc))) { + usb_audio_err(state->chip, + "invalid MIXER UNIT descriptor %d\n", @@ -1,5 +1,9 @@ revert-dm-bufio-fix-deadlock-with-loop-device.patch -x86-apic-handle-missing-global-clockevent-gracefully.patch dm-btree-fix-order-of-block-initialization-in-btree_split_beneath.patch dm-space-map-metadata-fix-missing-store-of-apply_bops-return-value.patch dm-table-fix-invalid-memory-accesses-with-too-high-sector-number.patch +alsa-usb-audio-fix-a-stack-buffer-overflow-bug-in-check_input_term.patch +alsa-usb-audio-fix-an-oob-bug-in-parse_audio_mixer_unit.patch +alsa-seq-fix-potential-concurrent-access-to-the-deleted-pool.patch +x86-apic-do-not-initialize-ldr-and-dfr-for-bigsmp.patch +x86-apic-include-the-ldr-when-clearing-out-apic-registers.patch diff --git a/x86-apic-do-not-initialize-ldr-and-dfr-for-bigsmp.patch b/x86-apic-do-not-initialize-ldr-and-dfr-for-bigsmp.patch new file mode 100644 index 0000000..14615a3 --- /dev/null +++ b/x86-apic-do-not-initialize-ldr-and-dfr-for-bigsmp.patch @@ -0,0 +1,83 @@ +From bae3a8d3308ee69a7dbdf145911b18dfda8ade0d Mon Sep 17 00:00:00 2001 +From: Bandan Das <bsd@redhat.com> +Date: Mon, 26 Aug 2019 06:15:12 -0400 +Subject: x86/apic: Do not initialize LDR and DFR for bigsmp + +From: Bandan Das <bsd@redhat.com> + +commit bae3a8d3308ee69a7dbdf145911b18dfda8ade0d upstream. + +Legacy apic init uses bigsmp for smp systems with 8 and more CPUs. The +bigsmp APIC implementation uses physical destination mode, but it +nevertheless initializes LDR and DFR. The LDR even ends up incorrectly with +multiple bit being set. + +This does not cause a functional problem because LDR and DFR are ignored +when physical destination mode is active, but it triggered a problem on a +32-bit KVM guest which jumps into a kdump kernel. + +The multiple bits set unearthed a bug in the KVM APIC implementation. The +code which creates the logical destination map for VCPUs ignores the +disabled state of the APIC and ends up overwriting an existing valid entry +and as a result, APIC calibration hangs in the guest during kdump +initialization. + +Remove the bogus LDR/DFR initialization. + +This is not intended to work around the KVM APIC bug. The LDR/DFR +ininitalization is wrong on its own. + +The issue goes back into the pre git history. The fixes tag is the commit +in the bitkeeper import which introduced bigsmp support in 2003. + + git://git.kernel.org/pub/scm/linux/kernel/git/tglx/history.git + +Fixes: db7b9e9f26b8 ("[PATCH] Clustered APIC setup for >8 CPU systems") +Suggested-by: Thomas Gleixner <tglx@linutronix.de> +Signed-off-by: Bandan Das <bsd@redhat.com> +Signed-off-by: Thomas Gleixner <tglx@linutronix.de> +Cc: stable@vger.kernel.org +Link: https://lkml.kernel.org/r/20190826101513.5080-2-bsd@redhat.com +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> + +--- + arch/x86/kernel/apic/bigsmp_32.c | 24 ++---------------------- + 1 file changed, 2 insertions(+), 22 deletions(-) + +--- a/arch/x86/kernel/apic/bigsmp_32.c ++++ b/arch/x86/kernel/apic/bigsmp_32.c +@@ -37,32 +37,12 @@ static int bigsmp_early_logical_apicid(i + return early_per_cpu(x86_cpu_to_apicid, cpu); + } + +-static inline unsigned long calculate_ldr(int cpu) +-{ +- unsigned long val, id; +- +- val = apic_read(APIC_LDR) & ~APIC_LDR_MASK; +- id = per_cpu(x86_bios_cpu_apicid, cpu); +- val |= SET_APIC_LOGICAL_ID(id); +- +- return val; +-} +- + /* +- * Set up the logical destination ID. +- * +- * Intel recommends to set DFR, LDR and TPR before enabling +- * an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel +- * document number 292116). So here it goes... ++ * bigsmp enables physical destination mode ++ * and doesn't use LDR and DFR + */ + static void bigsmp_init_apic_ldr(void) + { +- unsigned long val; +- int cpu = smp_processor_id(); +- +- apic_write(APIC_DFR, APIC_DFR_FLAT); +- val = calculate_ldr(cpu); +- apic_write(APIC_LDR, val); + } + + static void bigsmp_setup_apic_routing(void) diff --git a/x86-apic-handle-missing-global-clockevent-gracefully.patch b/x86-apic-handle-missing-global-clockevent-gracefully.patch deleted file mode 100644 index 890f15c..0000000 --- a/x86-apic-handle-missing-global-clockevent-gracefully.patch +++ /dev/null @@ -1,154 +0,0 @@ -From f897e60a12f0b9146357780d317879bce2a877dc Mon Sep 17 00:00:00 2001 -From: Thomas Gleixner <tglx@linutronix.de> -Date: Fri, 9 Aug 2019 14:54:07 +0200 -Subject: x86/apic: Handle missing global clockevent gracefully - -From: Thomas Gleixner <tglx@linutronix.de> - -commit f897e60a12f0b9146357780d317879bce2a877dc upstream. - -Some newer machines do not advertise legacy timers. The kernel can handle -that situation if the TSC and the CPU frequency are enumerated by CPUID or -MSRs and the CPU supports TSC deadline timer. If the CPU does not support -TSC deadline timer the local APIC timer frequency has to be known as well. - -Some Ryzens machines do not advertize legacy timers, but there is no -reliable way to determine the bus frequency which feeds the local APIC -timer when the machine allows overclocking of that frequency. - -As there is no legacy timer the local APIC timer calibration crashes due to -a NULL pointer dereference when accessing the not installed global clock -event device. - -Switch the calibration loop to a non interrupt based one, which polls -either TSC (if frequency is known) or jiffies. The latter requires a global -clockevent. As the machines which do not have a global clockevent installed -have a known TSC frequency this is a non issue. For older machines where -TSC frequency is not known, there is no known case where the legacy timers -do not exist as that would have been reported long ago. - -Reported-by: Daniel Drake <drake@endlessm.com> -Reported-by: Jiri Slaby <jslaby@suse.cz> -Signed-off-by: Thomas Gleixner <tglx@linutronix.de> -Tested-by: Daniel Drake <drake@endlessm.com> -Cc: stable@vger.kernel.org -Link: https://lkml.kernel.org/r/alpine.DEB.2.21.1908091443030.21433@nanos.tec.linutronix.de -Link: http://bugzilla.opensuse.org/show_bug.cgi?id=1142926#c12 -Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> - ---- - arch/x86/kernel/apic/apic.c | 68 ++++++++++++++++++++++++++++++++++---------- - 1 file changed, 53 insertions(+), 15 deletions(-) - ---- a/arch/x86/kernel/apic/apic.c -+++ b/arch/x86/kernel/apic/apic.c -@@ -620,7 +620,7 @@ static __initdata unsigned long lapic_ca - static __initdata unsigned long lapic_cal_j1, lapic_cal_j2; - - /* -- * Temporary interrupt handler. -+ * Temporary interrupt handler and polled calibration function. - */ - static void __init lapic_cal_handler(struct clock_event_device *dev) - { -@@ -704,7 +704,8 @@ calibrate_by_pmtimer(long deltapm, long - static int __init calibrate_APIC_clock(void) - { - struct clock_event_device *levt = this_cpu_ptr(&lapic_events); -- void (*real_handler)(struct clock_event_device *dev); -+ u64 tsc_perj = 0, tsc_start = 0; -+ unsigned long jif_start; - unsigned long deltaj; - long delta, deltatsc; - int pm_referenced = 0; -@@ -733,29 +734,65 @@ static int __init calibrate_APIC_clock(v - apic_printk(APIC_VERBOSE, "Using local APIC timer interrupts.\n" - "calibrating APIC timer ...\n"); - -+ /* -+ * There are platforms w/o global clockevent devices. Instead of -+ * making the calibration conditional on that, use a polling based -+ * approach everywhere. -+ */ - local_irq_disable(); - -- /* Replace the global interrupt handler */ -- real_handler = global_clock_event->event_handler; -- global_clock_event->event_handler = lapic_cal_handler; -- - /* - * Setup the APIC counter to maximum. There is no way the lapic - * can underflow in the 100ms detection time frame - */ - __setup_APIC_LVTT(0xffffffff, 0, 0); - -- /* Let the interrupts run */ -+ /* -+ * Methods to terminate the calibration loop: -+ * 1) Global clockevent if available (jiffies) -+ * 2) TSC if available and frequency is known -+ */ -+ jif_start = READ_ONCE(jiffies); -+ -+ if (tsc_khz) { -+ tsc_start = rdtsc(); -+ tsc_perj = div_u64((u64)tsc_khz * 1000, HZ); -+ } -+ -+ /* -+ * Enable interrupts so the tick can fire, if a global -+ * clockevent device is available -+ */ - local_irq_enable(); - -- while (lapic_cal_loops <= LAPIC_CAL_LOOPS) -- cpu_relax(); -+ while (lapic_cal_loops <= LAPIC_CAL_LOOPS) { -+ /* Wait for a tick to elapse */ -+ while (1) { -+ if (tsc_khz) { -+ u64 tsc_now = rdtsc(); -+ if ((tsc_now - tsc_start) >= tsc_perj) { -+ tsc_start += tsc_perj; -+ break; -+ } -+ } else { -+ unsigned long jif_now = READ_ONCE(jiffies); -+ -+ if (time_after(jif_now, jif_start)) { -+ jif_start = jif_now; -+ break; -+ } -+ } -+ cpu_relax(); -+ } -+ -+ /* Invoke the calibration routine */ -+ local_irq_disable(); -+ lapic_cal_handler(NULL); -+ local_irq_enable(); -+ } - - local_irq_disable(); - -- /* Restore the real event handler */ -- global_clock_event->event_handler = real_handler; -- - /* Build delta t1-t2 as apic timer counts down */ - delta = lapic_cal_t1 - lapic_cal_t2; - apic_printk(APIC_VERBOSE, "... lapic delta = %ld\n", delta); -@@ -805,10 +842,11 @@ static int __init calibrate_APIC_clock(v - levt->features &= ~CLOCK_EVT_FEAT_DUMMY; - - /* -- * PM timer calibration failed or not turned on -- * so lets try APIC timer based calibration -+ * PM timer calibration failed or not turned on so lets try APIC -+ * timer based calibration, if a global clockevent device is -+ * available. - */ -- if (!pm_referenced) { -+ if (!pm_referenced && global_clock_event) { - apic_printk(APIC_VERBOSE, "... verify APIC timer\n"); - - /* diff --git a/x86-apic-include-the-ldr-when-clearing-out-apic-registers.patch b/x86-apic-include-the-ldr-when-clearing-out-apic-registers.patch new file mode 100644 index 0000000..ad40135 --- /dev/null +++ b/x86-apic-include-the-ldr-when-clearing-out-apic-registers.patch @@ -0,0 +1,49 @@ +From 558682b5291937a70748d36fd9ba757fb25b99ae Mon Sep 17 00:00:00 2001 +From: Bandan Das <bsd@redhat.com> +Date: Mon, 26 Aug 2019 06:15:13 -0400 +Subject: x86/apic: Include the LDR when clearing out APIC registers + +From: Bandan Das <bsd@redhat.com> + +commit 558682b5291937a70748d36fd9ba757fb25b99ae upstream. + +Although APIC initialization will typically clear out the LDR before +setting it, the APIC cleanup code should reset the LDR. + +This was discovered with a 32-bit KVM guest jumping into a kdump +kernel. The stale bits in the LDR triggered a bug in the KVM APIC +implementation which caused the destination mapping for VCPUs to be +corrupted. + +Note that this isn't intended to paper over the KVM APIC bug. The kernel +has to clear the LDR when resetting the APIC registers except when X2APIC +is enabled. + +This lacks a Fixes tag because missing to clear LDR goes way back into pre +git history. + +[ tglx: Made x2apic_enabled a function call as required ] + +Signed-off-by: Bandan Das <bsd@redhat.com> +Signed-off-by: Thomas Gleixner <tglx@linutronix.de> +Cc: stable@vger.kernel.org +Link: https://lkml.kernel.org/r/20190826101513.5080-3-bsd@redhat.com +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> + +--- + arch/x86/kernel/apic/apic.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/arch/x86/kernel/apic/apic.c ++++ b/arch/x86/kernel/apic/apic.c +@@ -1019,6 +1019,10 @@ void clear_local_APIC(void) + apic_write(APIC_LVT0, v | APIC_LVT_MASKED); + v = apic_read(APIC_LVT1); + apic_write(APIC_LVT1, v | APIC_LVT_MASKED); ++ if (!x2apic_enabled()) { ++ v = apic_read(APIC_LDR) & ~APIC_LDR_MASK; ++ apic_write(APIC_LDR, v); ++ } + if (maxlvt >= 4) { + v = apic_read(APIC_LVTPC); + apic_write(APIC_LVTPC, v | APIC_LVT_MASKED); |