From 84a2495f800f2c473b6c9073965f95d88527b08a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 20 Aug 2017 11:33:21 -0700 Subject: [PATCH] 4.9-stable patches added patches: alsa-seq-2nd-attempt-at-fixing-race-creating-a-queue.patch alsa-usb-audio-add-mute-tlv-for-playback-volumes-on-c-media-devices.patch alsa-usb-audio-apply-sample-rate-quirk-to-sennheiser-headset.patch mm-discard-memblock-data-later.patch --- ...empt-at-fixing-race-creating-a-queue.patch | 127 +++++++++++++ ...-playback-volumes-on-c-media-devices.patch | 65 +++++++ ...ple-rate-quirk-to-sennheiser-headset.patch | 35 ++++ .../mm-discard-memblock-data-later.patch | 176 ++++++++++++++++++ queue-4.9/series | 4 + 5 files changed, 407 insertions(+) create mode 100644 queue-4.9/alsa-seq-2nd-attempt-at-fixing-race-creating-a-queue.patch create mode 100644 queue-4.9/alsa-usb-audio-add-mute-tlv-for-playback-volumes-on-c-media-devices.patch create mode 100644 queue-4.9/alsa-usb-audio-apply-sample-rate-quirk-to-sennheiser-headset.patch create mode 100644 queue-4.9/mm-discard-memblock-data-later.patch diff --git a/queue-4.9/alsa-seq-2nd-attempt-at-fixing-race-creating-a-queue.patch b/queue-4.9/alsa-seq-2nd-attempt-at-fixing-race-creating-a-queue.patch new file mode 100644 index 00000000000..8482ed3ea22 --- /dev/null +++ b/queue-4.9/alsa-seq-2nd-attempt-at-fixing-race-creating-a-queue.patch @@ -0,0 +1,127 @@ +From 7e1d90f60a0d501c8503e636942ca704a454d910 Mon Sep 17 00:00:00 2001 +From: Daniel Mentz +Date: Mon, 14 Aug 2017 14:46:01 -0700 +Subject: ALSA: seq: 2nd attempt at fixing race creating a queue + +From: Daniel Mentz + +commit 7e1d90f60a0d501c8503e636942ca704a454d910 upstream. + +commit 4842e98f26dd80be3623c4714a244ba52ea096a8 ("ALSA: seq: Fix race at +creating a queue") attempted to fix a race reported by syzkaller. That +fix has been described as follows: + +" +When a sequencer queue is created in snd_seq_queue_alloc(),it adds the +new queue element to the public list before referencing it. Thus the +queue might be deleted before the call of snd_seq_queue_use(), and it +results in the use-after-free error, as spotted by syzkaller. + +The fix is to reference the queue object at the right time. +" + +Even with that fix in place, syzkaller reported a use-after-free error. +It specifically pointed to the last instruction "return q->queue" in +snd_seq_queue_alloc(). The pointer q is being used after kfree() has +been called on it. + +It turned out that there is still a small window where a race can +happen. The window opens at +snd_seq_ioctl_create_queue()->snd_seq_queue_alloc()->queue_list_add() +and closes at +snd_seq_ioctl_create_queue()->queueptr()->snd_use_lock_use(). Between +these two calls, a different thread could delete the queue and possibly +re-create a different queue in the same location in queue_list. + +This change prevents this situation by calling snd_use_lock_use() from +snd_seq_queue_alloc() prior to calling queue_list_add(). It is then the +caller's responsibility to call snd_use_lock_free(&q->use_lock). + +Fixes: 4842e98f26dd ("ALSA: seq: Fix race at creating a queue") +Reported-by: Dmitry Vyukov +Signed-off-by: Daniel Mentz +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/core/seq/seq_clientmgr.c | 13 ++++--------- + sound/core/seq/seq_queue.c | 14 +++++++++----- + sound/core/seq/seq_queue.h | 2 +- + 3 files changed, 14 insertions(+), 15 deletions(-) + +--- a/sound/core/seq/seq_clientmgr.c ++++ b/sound/core/seq/seq_clientmgr.c +@@ -1502,16 +1502,11 @@ static int snd_seq_ioctl_unsubscribe_por + static int snd_seq_ioctl_create_queue(struct snd_seq_client *client, void *arg) + { + struct snd_seq_queue_info *info = arg; +- int result; + struct snd_seq_queue *q; + +- result = snd_seq_queue_alloc(client->number, info->locked, info->flags); +- if (result < 0) +- return result; +- +- q = queueptr(result); +- if (q == NULL) +- return -EINVAL; ++ q = snd_seq_queue_alloc(client->number, info->locked, info->flags); ++ if (IS_ERR(q)) ++ return PTR_ERR(q); + + info->queue = q->queue; + info->locked = q->locked; +@@ -1521,7 +1516,7 @@ static int snd_seq_ioctl_create_queue(st + if (!info->name[0]) + snprintf(info->name, sizeof(info->name), "Queue-%d", q->queue); + strlcpy(q->name, info->name, sizeof(q->name)); +- queuefree(q); ++ snd_use_lock_free(&q->use_lock); + + return 0; + } +--- a/sound/core/seq/seq_queue.c ++++ b/sound/core/seq/seq_queue.c +@@ -184,22 +184,26 @@ void __exit snd_seq_queues_delete(void) + static void queue_use(struct snd_seq_queue *queue, int client, int use); + + /* allocate a new queue - +- * return queue index value or negative value for error ++ * return pointer to new queue or ERR_PTR(-errno) for error ++ * The new queue's use_lock is set to 1. It is the caller's responsibility to ++ * call snd_use_lock_free(&q->use_lock). + */ +-int snd_seq_queue_alloc(int client, int locked, unsigned int info_flags) ++struct snd_seq_queue *snd_seq_queue_alloc(int client, int locked, unsigned int info_flags) + { + struct snd_seq_queue *q; + + q = queue_new(client, locked); + if (q == NULL) +- return -ENOMEM; ++ return ERR_PTR(-ENOMEM); + q->info_flags = info_flags; + queue_use(q, client, 1); ++ snd_use_lock_use(&q->use_lock); + if (queue_list_add(q) < 0) { ++ snd_use_lock_free(&q->use_lock); + queue_delete(q); +- return -ENOMEM; ++ return ERR_PTR(-ENOMEM); + } +- return q->queue; ++ return q; + } + + /* delete a queue - queue must be owned by the client */ +--- a/sound/core/seq/seq_queue.h ++++ b/sound/core/seq/seq_queue.h +@@ -71,7 +71,7 @@ void snd_seq_queues_delete(void); + + + /* create new queue (constructor) */ +-int snd_seq_queue_alloc(int client, int locked, unsigned int flags); ++struct snd_seq_queue *snd_seq_queue_alloc(int client, int locked, unsigned int flags); + + /* delete queue (destructor) */ + int snd_seq_queue_delete(int client, int queueid); diff --git a/queue-4.9/alsa-usb-audio-add-mute-tlv-for-playback-volumes-on-c-media-devices.patch b/queue-4.9/alsa-usb-audio-add-mute-tlv-for-playback-volumes-on-c-media-devices.patch new file mode 100644 index 00000000000..904b8ecddb4 --- /dev/null +++ b/queue-4.9/alsa-usb-audio-add-mute-tlv-for-playback-volumes-on-c-media-devices.patch @@ -0,0 +1,65 @@ +From 0f174b3525a43bd51f9397394763925e0ebe7bc7 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Wed, 16 Aug 2017 14:18:37 +0200 +Subject: ALSA: usb-audio: Add mute TLV for playback volumes on C-Media devices + +From: Takashi Iwai + +commit 0f174b3525a43bd51f9397394763925e0ebe7bc7 upstream. + +C-Media devices (at least some models) mute the playback stream when +volumes are set to the minimum value. But this isn't informed via TLV +and the user-space, typically PulseAudio, gets confused as if it's +still played in a low volume. + +This patch adds the new flag, min_mute, to struct usb_mixer_elem_info +for indicating that the mixer element is with the minimum-mute volume. +This flag is set for known C-Media devices in +snd_usb_mixer_fu_apply_quirk() in turn. + +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=196669 +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/usb/mixer.c | 2 ++ + sound/usb/mixer.h | 1 + + sound/usb/mixer_quirks.c | 6 ++++++ + 3 files changed, 9 insertions(+) + +--- a/sound/usb/mixer.c ++++ b/sound/usb/mixer.c +@@ -542,6 +542,8 @@ int snd_usb_mixer_vol_tlv(struct snd_kco + + if (size < sizeof(scale)) + return -ENOMEM; ++ if (cval->min_mute) ++ scale[0] = SNDRV_CTL_TLVT_DB_MINMAX_MUTE; + scale[2] = cval->dBmin; + scale[3] = cval->dBmax; + if (copy_to_user(_tlv, scale, sizeof(scale))) +--- a/sound/usb/mixer.h ++++ b/sound/usb/mixer.h +@@ -64,6 +64,7 @@ struct usb_mixer_elem_info { + int cached; + int cache_val[MAX_CHANNELS]; + u8 initialized; ++ u8 min_mute; + void *private_data; + }; + +--- a/sound/usb/mixer_quirks.c ++++ b/sound/usb/mixer_quirks.c +@@ -1873,6 +1873,12 @@ void snd_usb_mixer_fu_apply_quirk(struct + if (unitid == 7 && cval->control == UAC_FU_VOLUME) + snd_dragonfly_quirk_db_scale(mixer, cval, kctl); + break; ++ /* lowest playback value is muted on C-Media devices */ ++ case USB_ID(0x0d8c, 0x000c): ++ case USB_ID(0x0d8c, 0x0014): ++ if (strstr(kctl->id.name, "Playback")) ++ cval->min_mute = 1; ++ break; + } + } + diff --git a/queue-4.9/alsa-usb-audio-apply-sample-rate-quirk-to-sennheiser-headset.patch b/queue-4.9/alsa-usb-audio-apply-sample-rate-quirk-to-sennheiser-headset.patch new file mode 100644 index 00000000000..54a150dfa83 --- /dev/null +++ b/queue-4.9/alsa-usb-audio-apply-sample-rate-quirk-to-sennheiser-headset.patch @@ -0,0 +1,35 @@ +From a8e800fe0f68bc28ce309914f47e432742b865ed Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Mon, 14 Aug 2017 14:35:50 +0200 +Subject: ALSA: usb-audio: Apply sample rate quirk to Sennheiser headset + +From: Takashi Iwai + +commit a8e800fe0f68bc28ce309914f47e432742b865ed upstream. + +A Senheisser headset requires the typical sample-rate quirk for +avoiding spurious errors from inquiring the current sample rate like: + usb 1-1: 2:1: cannot get freq at ep 0x4 + usb 1-1: 3:1: cannot get freq at ep 0x83 + +The USB ID 1395:740a has to be added to the entries in +snd_usb_get_sample_rate_quirk(). + +Bugzilla: https://bugzilla.suse.com/show_bug.cgi?id=1052580 +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/usb/quirks.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/sound/usb/quirks.c ++++ b/sound/usb/quirks.c +@@ -1142,6 +1142,7 @@ bool snd_usb_get_sample_rate_quirk(struc + case USB_ID(0x0556, 0x0014): /* Phoenix Audio TMX320VC */ + case USB_ID(0x05A3, 0x9420): /* ELP HD USB Camera */ + case USB_ID(0x074D, 0x3553): /* Outlaw RR2150 (Micronas UAC3553B) */ ++ case USB_ID(0x1395, 0x740a): /* Sennheiser DECT */ + case USB_ID(0x1901, 0x0191): /* GE B850V3 CP2114 audio interface */ + case USB_ID(0x1de7, 0x0013): /* Phoenix Audio MT202exe */ + case USB_ID(0x1de7, 0x0014): /* Phoenix Audio TMX320 */ diff --git a/queue-4.9/mm-discard-memblock-data-later.patch b/queue-4.9/mm-discard-memblock-data-later.patch new file mode 100644 index 00000000000..0f112c1f39a --- /dev/null +++ b/queue-4.9/mm-discard-memblock-data-later.patch @@ -0,0 +1,176 @@ +From 3010f876500f9ba921afaeccec30c45ca6584dc8 Mon Sep 17 00:00:00 2001 +From: Pavel Tatashin +Date: Fri, 18 Aug 2017 15:16:05 -0700 +Subject: mm: discard memblock data later + +From: Pavel Tatashin + +commit 3010f876500f9ba921afaeccec30c45ca6584dc8 upstream. + +There is existing use after free bug when deferred struct pages are +enabled: + +The memblock_add() allocates memory for the memory array if more than +128 entries are needed. See comment in e820__memblock_setup(): + + * The bootstrap memblock region count maximum is 128 entries + * (INIT_MEMBLOCK_REGIONS), but EFI might pass us more E820 entries + * than that - so allow memblock resizing. + +This memblock memory is freed here: + free_low_memory_core_early() + +We access the freed memblock.memory later in boot when deferred pages +are initialized in this path: + + deferred_init_memmap() + for_each_mem_pfn_range() + __next_mem_pfn_range() + type = &memblock.memory; + +One possible explanation for why this use-after-free hasn't been hit +before is that the limit of INIT_MEMBLOCK_REGIONS has never been +exceeded at least on systems where deferred struct pages were enabled. + +Tested by reducing INIT_MEMBLOCK_REGIONS down to 4 from the current 128, +and verifying in qemu that this code is getting excuted and that the +freed pages are sane. + +Link: http://lkml.kernel.org/r/1502485554-318703-2-git-send-email-pasha.tatashin@oracle.com +Fixes: 7e18adb4f80b ("mm: meminit: initialise remaining struct pages in parallel with kswapd") +Signed-off-by: Pavel Tatashin +Reviewed-by: Steven Sistare +Reviewed-by: Daniel Jordan +Reviewed-by: Bob Picco +Acked-by: Michal Hocko +Cc: Mel Gorman +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + include/linux/memblock.h | 6 ++++-- + mm/memblock.c | 40 ++++++++++++++++++---------------------- + mm/nobootmem.c | 16 ---------------- + mm/page_alloc.c | 4 ++++ + 4 files changed, 26 insertions(+), 40 deletions(-) + +--- a/include/linux/memblock.h ++++ b/include/linux/memblock.h +@@ -64,6 +64,7 @@ extern bool movable_node_enabled; + #ifdef CONFIG_ARCH_DISCARD_MEMBLOCK + #define __init_memblock __meminit + #define __initdata_memblock __meminitdata ++void memblock_discard(void); + #else + #define __init_memblock + #define __initdata_memblock +@@ -77,8 +78,6 @@ phys_addr_t memblock_find_in_range_node( + int nid, ulong flags); + phys_addr_t memblock_find_in_range(phys_addr_t start, phys_addr_t end, + phys_addr_t size, phys_addr_t align); +-phys_addr_t get_allocated_memblock_reserved_regions_info(phys_addr_t *addr); +-phys_addr_t get_allocated_memblock_memory_regions_info(phys_addr_t *addr); + void memblock_allow_resize(void); + int memblock_add_node(phys_addr_t base, phys_addr_t size, int nid); + int memblock_add(phys_addr_t base, phys_addr_t size); +@@ -112,6 +111,9 @@ void __next_mem_range_rev(u64 *idx, int + void __next_reserved_mem_region(u64 *idx, phys_addr_t *out_start, + phys_addr_t *out_end); + ++void __memblock_free_early(phys_addr_t base, phys_addr_t size); ++void __memblock_free_late(phys_addr_t base, phys_addr_t size); ++ + /** + * for_each_mem_range - iterate through memblock areas from type_a and not + * included in type_b. Or just type_a if type_b is NULL. +--- a/mm/memblock.c ++++ b/mm/memblock.c +@@ -297,31 +297,27 @@ static void __init_memblock memblock_rem + } + + #ifdef CONFIG_ARCH_DISCARD_MEMBLOCK +- +-phys_addr_t __init_memblock get_allocated_memblock_reserved_regions_info( +- phys_addr_t *addr) +-{ +- if (memblock.reserved.regions == memblock_reserved_init_regions) +- return 0; +- +- *addr = __pa(memblock.reserved.regions); +- +- return PAGE_ALIGN(sizeof(struct memblock_region) * +- memblock.reserved.max); +-} +- +-phys_addr_t __init_memblock get_allocated_memblock_memory_regions_info( +- phys_addr_t *addr) ++/** ++ * Discard memory and reserved arrays if they were allocated ++ */ ++void __init memblock_discard(void) + { +- if (memblock.memory.regions == memblock_memory_init_regions) +- return 0; ++ phys_addr_t addr, size; + +- *addr = __pa(memblock.memory.regions); +- +- return PAGE_ALIGN(sizeof(struct memblock_region) * +- memblock.memory.max); ++ if (memblock.reserved.regions != memblock_reserved_init_regions) { ++ addr = __pa(memblock.reserved.regions); ++ size = PAGE_ALIGN(sizeof(struct memblock_region) * ++ memblock.reserved.max); ++ __memblock_free_late(addr, size); ++ } ++ ++ if (memblock.memory.regions == memblock_memory_init_regions) { ++ addr = __pa(memblock.memory.regions); ++ size = PAGE_ALIGN(sizeof(struct memblock_region) * ++ memblock.memory.max); ++ __memblock_free_late(addr, size); ++ } + } +- + #endif + + /** +--- a/mm/nobootmem.c ++++ b/mm/nobootmem.c +@@ -146,22 +146,6 @@ static unsigned long __init free_low_mem + NULL) + count += __free_memory_core(start, end); + +-#ifdef CONFIG_ARCH_DISCARD_MEMBLOCK +- { +- phys_addr_t size; +- +- /* Free memblock.reserved array if it was allocated */ +- size = get_allocated_memblock_reserved_regions_info(&start); +- if (size) +- count += __free_memory_core(start, start + size); +- +- /* Free memblock.memory array if it was allocated */ +- size = get_allocated_memblock_memory_regions_info(&start); +- if (size) +- count += __free_memory_core(start, start + size); +- } +-#endif +- + return count; + } + +--- a/mm/page_alloc.c ++++ b/mm/page_alloc.c +@@ -1587,6 +1587,10 @@ void __init page_alloc_init_late(void) + /* Reinit limits that are based on free pages after the kernel is up */ + files_maxfiles_init(); + #endif ++#ifdef CONFIG_ARCH_DISCARD_MEMBLOCK ++ /* Discard memblock private memory */ ++ memblock_discard(); ++#endif + + for_each_populated_zone(zone) + set_zone_contiguous(zone); diff --git a/queue-4.9/series b/queue-4.9/series index 6def2a4ba34..2053697f4c2 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -5,3 +5,7 @@ crypto-ixp4xx-fix-error-handling-path-in-aead_perform.patch crypto-x86-sha1-fix-reads-beyond-the-number-of-blocks-passed.patch input-elan_i2c-add-elan0608-to-the-acpi-table.patch input-elan_i2c-add-antoher-lenovo-acpi-id-for-upcoming-lenovo-nb.patch +alsa-seq-2nd-attempt-at-fixing-race-creating-a-queue.patch +alsa-usb-audio-apply-sample-rate-quirk-to-sennheiser-headset.patch +alsa-usb-audio-add-mute-tlv-for-playback-volumes-on-c-media-devices.patch +mm-discard-memblock-data-later.patch -- 2.47.3