From 671ceda44a0efbd11d984d3168019dfac1804ce4 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 19 May 2018 15:11:01 +0200 Subject: [PATCH] 3.18-stable patches added patches: alsa-control-fix-a-redundant-copy-issue.patch alsa-usb-mixer-volume-quirk-for-cm102-a-102s.patch powerpc-don-t-preempt_disable-in-show_cpuinfo.patch tracing-x86-xen-remove-zero-data-size-trace-events-trace_xen_mmu_flush_tlb-_all.patch usbip-fix-error-handling-in-stub_probe.patch usbip-usbip_host-delete-device-from-busid_table-after-rebind.patch usbip-usbip_host-fix-bad-unlock-balance-during-stub_probe.patch usbip-usbip_host-fix-null-ptr-deref-and-use-after-free-errors.patch usbip-usbip_host-refine-probe-and-disconnect-debug-msgs-to-be-useful.patch usbip-usbip_host-run-rebind-from-exit-when-module-is-removed.patch --- ...a-control-fix-a-redundant-copy-issue.patch | 45 +++ ...-mixer-volume-quirk-for-cm102-a-102s.patch | 44 +++ ...on-t-preempt_disable-in-show_cpuinfo.patch | 51 +++ queue-3.18/series | 10 + ...-events-trace_xen_mmu_flush_tlb-_all.patch | 84 +++++ ...bip-fix-error-handling-in-stub_probe.patch | 73 +++++ ...device-from-busid_table-after-rebind.patch | 46 +++ ...bad-unlock-balance-during-stub_probe.patch | 54 ++++ ...-ptr-deref-and-use-after-free-errors.patch | 298 ++++++++++++++++++ ...d-disconnect-debug-msgs-to-be-useful.patch | 40 +++ ...ind-from-exit-when-module-is-removed.patch | 135 ++++++++ 11 files changed, 880 insertions(+) create mode 100644 queue-3.18/alsa-control-fix-a-redundant-copy-issue.patch create mode 100644 queue-3.18/alsa-usb-mixer-volume-quirk-for-cm102-a-102s.patch create mode 100644 queue-3.18/powerpc-don-t-preempt_disable-in-show_cpuinfo.patch create mode 100644 queue-3.18/tracing-x86-xen-remove-zero-data-size-trace-events-trace_xen_mmu_flush_tlb-_all.patch create mode 100644 queue-3.18/usbip-fix-error-handling-in-stub_probe.patch create mode 100644 queue-3.18/usbip-usbip_host-delete-device-from-busid_table-after-rebind.patch create mode 100644 queue-3.18/usbip-usbip_host-fix-bad-unlock-balance-during-stub_probe.patch create mode 100644 queue-3.18/usbip-usbip_host-fix-null-ptr-deref-and-use-after-free-errors.patch create mode 100644 queue-3.18/usbip-usbip_host-refine-probe-and-disconnect-debug-msgs-to-be-useful.patch create mode 100644 queue-3.18/usbip-usbip_host-run-rebind-from-exit-when-module-is-removed.patch diff --git a/queue-3.18/alsa-control-fix-a-redundant-copy-issue.patch b/queue-3.18/alsa-control-fix-a-redundant-copy-issue.patch new file mode 100644 index 00000000000..d64851192e0 --- /dev/null +++ b/queue-3.18/alsa-control-fix-a-redundant-copy-issue.patch @@ -0,0 +1,45 @@ +From 3f12888dfae2a48741c4caa9214885b3aaf350f9 Mon Sep 17 00:00:00 2001 +From: Wenwen Wang +Date: Sat, 5 May 2018 13:38:03 -0500 +Subject: ALSA: control: fix a redundant-copy issue + +From: Wenwen Wang + +commit 3f12888dfae2a48741c4caa9214885b3aaf350f9 upstream. + +In snd_ctl_elem_add_compat(), the fields of the struct 'data' need to be +copied from the corresponding fields of the struct 'data32' in userspace. +This is achieved by invoking copy_from_user() and get_user() functions. The +problem here is that the 'type' field is copied twice. One is by +copy_from_user() and one is by get_user(). Given that the 'type' field is +not used between the two copies, the second copy is *completely* redundant +and should be removed for better performance and cleanup. Also, these two +copies can cause inconsistent data: as the struct 'data32' resides in +userspace and a malicious userspace process can race to change the 'type' +field between the two copies to cause inconsistent data. Depending on how +the data is used in the future, such an inconsistency may cause potential +security risks. + +For above reasons, we should take out the second copy. + +Signed-off-by: Wenwen Wang +Cc: +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/core/control_compat.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/sound/core/control_compat.c ++++ b/sound/core/control_compat.c +@@ -400,8 +400,7 @@ static int snd_ctl_elem_add_compat(struc + if (copy_from_user(&data->id, &data32->id, sizeof(data->id)) || + copy_from_user(&data->type, &data32->type, 3 * sizeof(u32))) + goto error; +- if (get_user(data->owner, &data32->owner) || +- get_user(data->type, &data32->type)) ++ if (get_user(data->owner, &data32->owner)) + goto error; + switch (data->type) { + case SNDRV_CTL_ELEM_TYPE_BOOLEAN: diff --git a/queue-3.18/alsa-usb-mixer-volume-quirk-for-cm102-a-102s.patch b/queue-3.18/alsa-usb-mixer-volume-quirk-for-cm102-a-102s.patch new file mode 100644 index 00000000000..c9a56b41d67 --- /dev/null +++ b/queue-3.18/alsa-usb-mixer-volume-quirk-for-cm102-a-102s.patch @@ -0,0 +1,44 @@ +From 21493316a3c4598f308d5a9fa31cc74639c4caff Mon Sep 17 00:00:00 2001 +From: Federico Cuello +Date: Wed, 9 May 2018 00:13:38 +0200 +Subject: ALSA: usb: mixer: volume quirk for CM102-A+/102S+ + +From: Federico Cuello + +commit 21493316a3c4598f308d5a9fa31cc74639c4caff upstream. + +Currently it's not possible to set volume lower than 26% (it just mutes). + +Also fixes this warning: + + Warning! Unlikely big volume range (=9472), cval->res is probably wrong. + [13] FU [PCM Playback Volume] ch = 2, val = -9473/-1/1 + +, and volume works fine for full range. + +Signed-off-by: Federico Cuello +Cc: +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/usb/mixer.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/sound/usb/mixer.c ++++ b/sound/usb/mixer.c +@@ -883,6 +883,14 @@ static void volume_control_quirks(struct + } + break; + ++ case USB_ID(0x0d8c, 0x0103): ++ if (!strcmp(kctl->id.name, "PCM Playback Volume")) { ++ usb_audio_info(chip, ++ "set volume quirk for CM102-A+/102S+\n"); ++ cval->min = -256; ++ } ++ break; ++ + case USB_ID(0x0471, 0x0101): + case USB_ID(0x0471, 0x0104): + case USB_ID(0x0471, 0x0105): diff --git a/queue-3.18/powerpc-don-t-preempt_disable-in-show_cpuinfo.patch b/queue-3.18/powerpc-don-t-preempt_disable-in-show_cpuinfo.patch new file mode 100644 index 00000000000..4bbb2690379 --- /dev/null +++ b/queue-3.18/powerpc-don-t-preempt_disable-in-show_cpuinfo.patch @@ -0,0 +1,51 @@ +From 349524bc0da698ec77f2057cf4a4948eb6349265 Mon Sep 17 00:00:00 2001 +From: Benjamin Herrenschmidt +Date: Wed, 10 Jan 2018 17:10:12 +1100 +Subject: powerpc: Don't preempt_disable() in show_cpuinfo() + +From: Benjamin Herrenschmidt + +commit 349524bc0da698ec77f2057cf4a4948eb6349265 upstream. + +This causes warnings from cpufreq mutex code. This is also rather +unnecessary and ineffective. If we really want to prevent concurrent +unplug, we could take the unplug read lock but I don't see this being +critical. + +Fixes: cd77b5ce208c ("powerpc/powernv/cpufreq: Fix the frequency read by /proc/cpuinfo") +Signed-off-by: Benjamin Herrenschmidt +Signed-off-by: Michael Ellerman +Acked-by: Michal Suchanek +Signed-off-by: Greg Kroah-Hartman + +--- + arch/powerpc/kernel/setup-common.c | 11 ----------- + 1 file changed, 11 deletions(-) + +--- a/arch/powerpc/kernel/setup-common.c ++++ b/arch/powerpc/kernel/setup-common.c +@@ -217,14 +217,6 @@ static int show_cpuinfo(struct seq_file + unsigned short maj; + unsigned short min; + +- /* We only show online cpus: disable preempt (overzealous, I +- * knew) to prevent cpu going down. */ +- preempt_disable(); +- if (!cpu_online(cpu_id)) { +- preempt_enable(); +- return 0; +- } +- + #ifdef CONFIG_SMP + pvr = per_cpu(cpu_pvr, cpu_id); + #else +@@ -329,9 +321,6 @@ static int show_cpuinfo(struct seq_file + #ifdef CONFIG_SMP + seq_printf(m, "\n"); + #endif +- +- preempt_enable(); +- + /* If this is the last cpu, print the summary */ + if (cpumask_next(cpu_id, cpu_online_mask) >= nr_cpu_ids) + show_cpuinfo_summary(m); diff --git a/queue-3.18/series b/queue-3.18/series index 879c6c5955a..9c60991326f 100644 --- a/queue-3.18/series +++ b/queue-3.18/series @@ -20,3 +20,13 @@ revert-arm-dts-imx6qdl-wandboard-fix-audio-channel-swap.patch l2tp-revert-l2tp-fix-missing-print-session-offset-info.patch pipe-cap-initial-pipe-capacity-according-to-pipe-max-size-limit.patch kernel-exit.c-avoid-undefined-behaviour-when-calling-wait4.patch +usbip-usbip_host-refine-probe-and-disconnect-debug-msgs-to-be-useful.patch +usbip-usbip_host-delete-device-from-busid_table-after-rebind.patch +usbip-usbip_host-run-rebind-from-exit-when-module-is-removed.patch +usbip-fix-error-handling-in-stub_probe.patch +usbip-usbip_host-fix-null-ptr-deref-and-use-after-free-errors.patch +usbip-usbip_host-fix-bad-unlock-balance-during-stub_probe.patch +alsa-usb-mixer-volume-quirk-for-cm102-a-102s.patch +alsa-control-fix-a-redundant-copy-issue.patch +powerpc-don-t-preempt_disable-in-show_cpuinfo.patch +tracing-x86-xen-remove-zero-data-size-trace-events-trace_xen_mmu_flush_tlb-_all.patch diff --git a/queue-3.18/tracing-x86-xen-remove-zero-data-size-trace-events-trace_xen_mmu_flush_tlb-_all.patch b/queue-3.18/tracing-x86-xen-remove-zero-data-size-trace-events-trace_xen_mmu_flush_tlb-_all.patch new file mode 100644 index 00000000000..9b5b971a227 --- /dev/null +++ b/queue-3.18/tracing-x86-xen-remove-zero-data-size-trace-events-trace_xen_mmu_flush_tlb-_all.patch @@ -0,0 +1,84 @@ +From 45dd9b0666a162f8e4be76096716670cf1741f0e Mon Sep 17 00:00:00 2001 +From: "Steven Rostedt (VMware)" +Date: Wed, 9 May 2018 14:36:09 -0400 +Subject: tracing/x86/xen: Remove zero data size trace events trace_xen_mmu_flush_tlb{_all} + +From: Steven Rostedt (VMware) + +commit 45dd9b0666a162f8e4be76096716670cf1741f0e upstream. + +Doing an audit of trace events, I discovered two trace events in the xen +subsystem that use a hack to create zero data size trace events. This is not +what trace events are for. Trace events add memory footprint overhead, and +if all you need to do is see if a function is hit or not, simply make that +function noinline and use function tracer filtering. + +Worse yet, the hack used was: + + __array(char, x, 0) + +Which creates a static string of zero in length. There's assumptions about +such constructs in ftrace that this is a dynamic string that is nul +terminated. This is not the case with these tracepoints and can cause +problems in various parts of ftrace. + +Nuke the trace events! + +Link: http://lkml.kernel.org/r/20180509144605.5a220327@gandalf.local.home + +Cc: stable@vger.kernel.org +Fixes: 95a7d76897c1e ("xen/mmu: Use Xen specific TLB flush instead of the generic one.") +Reviewed-by: Juergen Gross +Signed-off-by: Steven Rostedt (VMware) +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/xen/mmu.c | 4 ---- + include/trace/events/xen.h | 16 ---------------- + 2 files changed, 20 deletions(-) + +--- a/arch/x86/xen/mmu.c ++++ b/arch/x86/xen/mmu.c +@@ -1246,8 +1246,6 @@ void xen_flush_tlb_all(void) + struct mmuext_op *op; + struct multicall_space mcs; + +- trace_xen_mmu_flush_tlb_all(0); +- + preempt_disable(); + + mcs = xen_mc_entry(sizeof(*op)); +@@ -1265,8 +1263,6 @@ static void xen_flush_tlb(void) + struct mmuext_op *op; + struct multicall_space mcs; + +- trace_xen_mmu_flush_tlb(0); +- + preempt_disable(); + + mcs = xen_mc_entry(sizeof(*op)); +--- a/include/trace/events/xen.h ++++ b/include/trace/events/xen.h +@@ -377,22 +377,6 @@ DECLARE_EVENT_CLASS(xen_mmu_pgd, + DEFINE_XEN_MMU_PGD_EVENT(xen_mmu_pgd_pin); + DEFINE_XEN_MMU_PGD_EVENT(xen_mmu_pgd_unpin); + +-TRACE_EVENT(xen_mmu_flush_tlb_all, +- TP_PROTO(int x), +- TP_ARGS(x), +- TP_STRUCT__entry(__array(char, x, 0)), +- TP_fast_assign((void)x), +- TP_printk("%s", "") +- ); +- +-TRACE_EVENT(xen_mmu_flush_tlb, +- TP_PROTO(int x), +- TP_ARGS(x), +- TP_STRUCT__entry(__array(char, x, 0)), +- TP_fast_assign((void)x), +- TP_printk("%s", "") +- ); +- + TRACE_EVENT(xen_mmu_flush_tlb_single, + TP_PROTO(unsigned long addr), + TP_ARGS(addr), diff --git a/queue-3.18/usbip-fix-error-handling-in-stub_probe.patch b/queue-3.18/usbip-fix-error-handling-in-stub_probe.patch new file mode 100644 index 00000000000..ec25153ea3b --- /dev/null +++ b/queue-3.18/usbip-fix-error-handling-in-stub_probe.patch @@ -0,0 +1,73 @@ +From 3ff67445750a84de67faaf52c6e1895cb09f2c56 Mon Sep 17 00:00:00 2001 +From: Alexey Khoroshilov +Date: Sat, 29 Nov 2014 01:29:10 +0300 +Subject: usbip: fix error handling in stub_probe() + +From: Alexey Khoroshilov + +commit 3ff67445750a84de67faaf52c6e1895cb09f2c56 upstream. + +If usb_hub_claim_port() fails, no resources are deallocated and +if stub_add_files() fails, port is not released. + +The patch fixes these issues and rearranges error handling code. + +Found by Linux Driver Verification project (linuxtesting.org). + +Signed-off-by: Alexey Khoroshilov +Acked-by: Valentina Manea +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/usbip/stub_dev.c | 26 +++++++++++++++----------- + 1 file changed, 15 insertions(+), 11 deletions(-) + +--- a/drivers/usb/usbip/stub_dev.c ++++ b/drivers/usb/usbip/stub_dev.c +@@ -313,7 +313,6 @@ static int stub_probe(struct usb_device + { + struct stub_device *sdev = NULL; + const char *udev_busid = dev_name(&udev->dev); +- int err = 0; + struct bus_id_priv *busid_priv; + int rc; + +@@ -374,23 +373,28 @@ static int stub_probe(struct usb_device + (struct usb_dev_state *) udev); + if (rc) { + dev_dbg(&udev->dev, "unable to claim port\n"); +- return rc; ++ goto err_port; + } + +- err = stub_add_files(&udev->dev); +- if (err) { ++ rc = stub_add_files(&udev->dev); ++ if (rc) { + dev_err(&udev->dev, "stub_add_files for %s\n", udev_busid); +- dev_set_drvdata(&udev->dev, NULL); +- usb_put_dev(udev); +- kthread_stop_put(sdev->ud.eh); +- +- busid_priv->sdev = NULL; +- stub_device_free(sdev); +- return err; ++ goto err_files; + } + busid_priv->status = STUB_BUSID_ALLOC; + + return 0; ++err_files: ++ usb_hub_release_port(udev->parent, udev->portnum, ++ (struct usb_dev_state *) udev); ++err_port: ++ dev_set_drvdata(&udev->dev, NULL); ++ usb_put_dev(udev); ++ kthread_stop_put(sdev->ud.eh); ++ ++ busid_priv->sdev = NULL; ++ stub_device_free(sdev); ++ return rc; + } + + static void shutdown_busid(struct bus_id_priv *busid_priv) diff --git a/queue-3.18/usbip-usbip_host-delete-device-from-busid_table-after-rebind.patch b/queue-3.18/usbip-usbip_host-delete-device-from-busid_table-after-rebind.patch new file mode 100644 index 00000000000..abe5481d33c --- /dev/null +++ b/queue-3.18/usbip-usbip_host-delete-device-from-busid_table-after-rebind.patch @@ -0,0 +1,46 @@ +From 1e180f167d4e413afccbbb4a421b48b2de832549 Mon Sep 17 00:00:00 2001 +From: "Shuah Khan (Samsung OSG)" +Date: Mon, 30 Apr 2018 16:17:19 -0600 +Subject: usbip: usbip_host: delete device from busid_table after rebind + +From: Shuah Khan (Samsung OSG) + +commit 1e180f167d4e413afccbbb4a421b48b2de832549 upstream. + +Device is left in the busid_table after unbind and rebind. Rebind +initiates usb bus scan and the original driver claims the device. +After rescan the device should be deleted from the busid_table as +it no longer belongs to usbip_host. + +Fix it to delete the device after device_attach() succeeds. + +Signed-off-by: Shuah Khan (Samsung OSG) +Cc: stable +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/usbip/stub_main.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/usb/usbip/stub_main.c ++++ b/drivers/usb/usbip/stub_main.c +@@ -201,6 +201,9 @@ static ssize_t rebind_store(struct devic + if (!bid) + return -ENODEV; + ++ /* mark the device for deletion so probe ignores it during rescan */ ++ bid->status = STUB_BUSID_OTHER; ++ + /* device_attach() callers should hold parent lock for USB */ + if (bid->udev->dev.parent) + device_lock(bid->udev->dev.parent); +@@ -212,6 +215,9 @@ static ssize_t rebind_store(struct devic + return ret; + } + ++ /* delete device from busid_table */ ++ del_match_busid((char *) buf); ++ + return count; + } + diff --git a/queue-3.18/usbip-usbip_host-fix-bad-unlock-balance-during-stub_probe.patch b/queue-3.18/usbip-usbip_host-fix-bad-unlock-balance-during-stub_probe.patch new file mode 100644 index 00000000000..8ef008c94c5 --- /dev/null +++ b/queue-3.18/usbip-usbip_host-fix-bad-unlock-balance-during-stub_probe.patch @@ -0,0 +1,54 @@ +From c171654caa875919be3c533d3518da8be5be966e Mon Sep 17 00:00:00 2001 +From: "Shuah Khan (Samsung OSG)" +Date: Tue, 15 May 2018 17:57:23 -0600 +Subject: usbip: usbip_host: fix bad unlock balance during stub_probe() + +From: Shuah Khan (Samsung OSG) + +commit c171654caa875919be3c533d3518da8be5be966e upstream. + +stub_probe() calls put_busid_priv() in an error path when device isn't +found in the busid_table. Fix it by making put_busid_priv() safe to be +called with null struct bus_id_priv pointer. + +This problem happens when "usbip bind" is run without loading usbip_host +driver and then running modprobe. The first failed bind attempt unbinds +the device from the original driver and when usbip_host is modprobed, +stub_probe() runs and doesn't find the device in its busid table and calls +put_busid_priv(0 with null bus_id_priv pointer. + +usbip-host 3-10.2: 3-10.2 is not in match_busid table... skip! + +[ 367.359679] ===================================== +[ 367.359681] WARNING: bad unlock balance detected! +[ 367.359683] 4.17.0-rc4+ #5 Not tainted +[ 367.359685] ------------------------------------- +[ 367.359688] modprobe/2768 is trying to release lock ( +[ 367.359689] +================================================================== +[ 367.359696] BUG: KASAN: null-ptr-deref in print_unlock_imbalance_bug+0x99/0x110 +[ 367.359699] Read of size 8 at addr 0000000000000058 by task modprobe/2768 + +[ 367.359705] CPU: 4 PID: 2768 Comm: modprobe Not tainted 4.17.0-rc4+ #5 + +Fixes: 22076557b07c ("usbip: usbip_host: fix NULL-ptr deref and use-after-free errors") in usb-linus +Signed-off-by: Shuah Khan (Samsung OSG) +Cc: stable +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/usbip/stub_main.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/usb/usbip/stub_main.c ++++ b/drivers/usb/usbip/stub_main.c +@@ -96,7 +96,8 @@ struct bus_id_priv *get_busid_priv(const + + void put_busid_priv(struct bus_id_priv *bid) + { +- spin_unlock(&bid->busid_lock); ++ if (bid) ++ spin_unlock(&bid->busid_lock); + } + + static int add_match_busid(char *busid) diff --git a/queue-3.18/usbip-usbip_host-fix-null-ptr-deref-and-use-after-free-errors.patch b/queue-3.18/usbip-usbip_host-fix-null-ptr-deref-and-use-after-free-errors.patch new file mode 100644 index 00000000000..b6309380fc4 --- /dev/null +++ b/queue-3.18/usbip-usbip_host-fix-null-ptr-deref-and-use-after-free-errors.patch @@ -0,0 +1,298 @@ +From 22076557b07c12086eeb16b8ce2b0b735f7a27e7 Mon Sep 17 00:00:00 2001 +From: "Shuah Khan (Samsung OSG)" +Date: Mon, 14 May 2018 20:49:58 -0600 +Subject: usbip: usbip_host: fix NULL-ptr deref and use-after-free errors + +From: Shuah Khan (Samsung OSG) + +commit 22076557b07c12086eeb16b8ce2b0b735f7a27e7 upstream. + +usbip_host updates device status without holding lock from stub probe, +disconnect and rebind code paths. When multiple requests to import a +device are received, these unprotected code paths step all over each +other and drive fails with NULL-ptr deref and use-after-free errors. + +The driver uses a table lock to protect the busid array for adding and +deleting busids to the table. However, the probe, disconnect and rebind +paths get the busid table entry and update the status without holding +the busid table lock. Add a new finer grain lock to protect the busid +entry. This new lock will be held to search and update the busid entry +fields from get_busid_idx(), add_match_busid() and del_match_busid(). + +match_busid_show() does the same to access the busid entry fields. + +get_busid_priv() changed to return the pointer to the busid entry holding +the busid lock. stub_probe(), stub_disconnect() and stub_device_rebind() +call put_busid_priv() to release the busid lock before returning. This +changes fixes the unprotected code paths eliminating the race conditions +in updating the busid entries. + +Reported-by: Jakub Jirasek +Signed-off-by: Shuah Khan (Samsung OSG) +Cc: stable +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/usbip/stub.h | 2 ++ + drivers/usb/usbip/stub_dev.c | 33 +++++++++++++++++++++++---------- + drivers/usb/usbip/stub_main.c | 40 +++++++++++++++++++++++++++++++++++----- + 3 files changed, 60 insertions(+), 15 deletions(-) + +--- a/drivers/usb/usbip/stub.h ++++ b/drivers/usb/usbip/stub.h +@@ -88,6 +88,7 @@ struct bus_id_priv { + struct stub_device *sdev; + struct usb_device *udev; + char shutdown_busid; ++ spinlock_t busid_lock; + }; + + /* stub_priv is allocated from stub_priv_cache */ +@@ -98,6 +99,7 @@ extern struct usb_device_driver stub_dri + + /* stub_main.c */ + struct bus_id_priv *get_busid_priv(const char *busid); ++void put_busid_priv(struct bus_id_priv *bid); + int del_match_busid(char *busid); + void stub_device_cleanup_urbs(struct stub_device *sdev); + +--- a/drivers/usb/usbip/stub_dev.c ++++ b/drivers/usb/usbip/stub_dev.c +@@ -314,7 +314,7 @@ static int stub_probe(struct usb_device + struct stub_device *sdev = NULL; + const char *udev_busid = dev_name(&udev->dev); + struct bus_id_priv *busid_priv; +- int rc; ++ int rc = 0; + + dev_dbg(&udev->dev, "Enter probe\n"); + +@@ -331,13 +331,15 @@ static int stub_probe(struct usb_device + * other matched drivers by the driver core. + * See driver_probe_device() in driver/base/dd.c + */ +- return -ENODEV; ++ rc = -ENODEV; ++ goto call_put_busid_priv; + } + + if (udev->descriptor.bDeviceClass == USB_CLASS_HUB) { + dev_dbg(&udev->dev, "%s is a usb hub device... skip!\n", + udev_busid); +- return -ENODEV; ++ rc = -ENODEV; ++ goto call_put_busid_priv; + } + + if (!strcmp(udev->bus->bus_name, "vhci_hcd")) { +@@ -345,13 +347,16 @@ static int stub_probe(struct usb_device + "%s is attached on vhci_hcd... skip!\n", + udev_busid); + +- return -ENODEV; ++ rc = -ENODEV; ++ goto call_put_busid_priv; + } + + /* ok, this is my device */ + sdev = stub_device_alloc(udev); +- if (!sdev) +- return -ENOMEM; ++ if (!sdev) { ++ rc = -ENOMEM; ++ goto call_put_busid_priv; ++ } + + dev_info(&udev->dev, + "usbip-host: register new device (bus %u dev %u)\n", +@@ -383,7 +388,9 @@ static int stub_probe(struct usb_device + } + busid_priv->status = STUB_BUSID_ALLOC; + +- return 0; ++ rc = 0; ++ goto call_put_busid_priv; ++ + err_files: + usb_hub_release_port(udev->parent, udev->portnum, + (struct usb_dev_state *) udev); +@@ -394,6 +401,9 @@ err_port: + + busid_priv->sdev = NULL; + stub_device_free(sdev); ++ ++call_put_busid_priv: ++ put_busid_priv(busid_priv); + return rc; + } + +@@ -432,7 +442,7 @@ static void stub_disconnect(struct usb_d + /* get stub_device */ + if (!sdev) { + dev_err(&udev->dev, "could not get device"); +- return; ++ goto call_put_busid_priv; + } + + dev_set_drvdata(&udev->dev, NULL); +@@ -447,12 +457,12 @@ static void stub_disconnect(struct usb_d + (struct usb_dev_state *) udev); + if (rc) { + dev_dbg(&udev->dev, "unable to release port\n"); +- return; ++ goto call_put_busid_priv; + } + + /* If usb reset is called from event handler */ + if (busid_priv->sdev->ud.eh == current) +- return; ++ goto call_put_busid_priv; + + /* shutdown the current connection */ + shutdown_busid(busid_priv); +@@ -465,6 +475,9 @@ static void stub_disconnect(struct usb_d + + if (busid_priv->status == STUB_BUSID_ALLOC) + busid_priv->status = STUB_BUSID_ADDED; ++ ++call_put_busid_priv: ++ put_busid_priv(busid_priv); + } + + #ifdef CONFIG_PM +--- a/drivers/usb/usbip/stub_main.c ++++ b/drivers/usb/usbip/stub_main.c +@@ -40,6 +40,8 @@ static spinlock_t busid_table_lock; + + static void init_busid_table(void) + { ++ int i; ++ + /* + * This also sets the bus_table[i].status to + * STUB_BUSID_OTHER, which is 0. +@@ -47,6 +49,9 @@ static void init_busid_table(void) + memset(busid_table, 0, sizeof(busid_table)); + + spin_lock_init(&busid_table_lock); ++ ++ for (i = 0; i < MAX_BUSID; i++) ++ spin_lock_init(&busid_table[i].busid_lock); + } + + /* +@@ -58,15 +63,20 @@ static int get_busid_idx(const char *bus + int i; + int idx = -1; + +- for (i = 0; i < MAX_BUSID; i++) ++ for (i = 0; i < MAX_BUSID; i++) { ++ spin_lock(&busid_table[i].busid_lock); + if (busid_table[i].name[0]) + if (!strncmp(busid_table[i].name, busid, BUSID_SIZE)) { + idx = i; ++ spin_unlock(&busid_table[i].busid_lock); + break; + } ++ spin_unlock(&busid_table[i].busid_lock); ++ } + return idx; + } + ++/* Returns holding busid_lock. Should call put_busid_priv() to unlock */ + struct bus_id_priv *get_busid_priv(const char *busid) + { + int idx; +@@ -74,13 +84,21 @@ struct bus_id_priv *get_busid_priv(const + + spin_lock(&busid_table_lock); + idx = get_busid_idx(busid); +- if (idx >= 0) ++ if (idx >= 0) { + bid = &(busid_table[idx]); ++ /* get busid_lock before returning */ ++ spin_lock(&bid->busid_lock); ++ } + spin_unlock(&busid_table_lock); + + return bid; + } + ++void put_busid_priv(struct bus_id_priv *bid) ++{ ++ spin_unlock(&bid->busid_lock); ++} ++ + static int add_match_busid(char *busid) + { + int i; +@@ -93,15 +111,19 @@ static int add_match_busid(char *busid) + goto out; + } + +- for (i = 0; i < MAX_BUSID; i++) ++ for (i = 0; i < MAX_BUSID; i++) { ++ spin_lock(&busid_table[i].busid_lock); + if (!busid_table[i].name[0]) { + strlcpy(busid_table[i].name, busid, BUSID_SIZE); + if ((busid_table[i].status != STUB_BUSID_ALLOC) && + (busid_table[i].status != STUB_BUSID_REMOV)) + busid_table[i].status = STUB_BUSID_ADDED; + ret = 0; ++ spin_unlock(&busid_table[i].busid_lock); + break; + } ++ spin_unlock(&busid_table[i].busid_lock); ++ } + + out: + spin_unlock(&busid_table_lock); +@@ -122,6 +144,8 @@ int del_match_busid(char *busid) + /* found */ + ret = 0; + ++ spin_lock(&busid_table[idx].busid_lock); ++ + if (busid_table[idx].status == STUB_BUSID_OTHER) + memset(busid_table[idx].name, 0, BUSID_SIZE); + +@@ -129,6 +153,7 @@ int del_match_busid(char *busid) + (busid_table[idx].status != STUB_BUSID_ADDED)) + busid_table[idx].status = STUB_BUSID_REMOV; + ++ spin_unlock(&busid_table[idx].busid_lock); + out: + spin_unlock(&busid_table_lock); + +@@ -141,9 +166,12 @@ static ssize_t show_match_busid(struct d + char *out = buf; + + spin_lock(&busid_table_lock); +- for (i = 0; i < MAX_BUSID; i++) ++ for (i = 0; i < MAX_BUSID; i++) { ++ spin_lock(&busid_table[i].busid_lock); + if (busid_table[i].name[0]) + out += sprintf(out, "%s ", busid_table[i].name); ++ spin_unlock(&busid_table[i].busid_lock); ++ } + spin_unlock(&busid_table_lock); + out += sprintf(out, "\n"); + +@@ -219,7 +247,7 @@ static void stub_device_rebind(void) + } + spin_unlock(&busid_table_lock); + +- /* now run rebind */ ++ /* now run rebind - no need to hold locks. driver files are removed */ + for (i = 0; i < MAX_BUSID; i++) { + if (busid_table[i].name[0] && + busid_table[i].shutdown_busid) { +@@ -249,6 +277,8 @@ static ssize_t rebind_store(struct devic + + /* mark the device for deletion so probe ignores it during rescan */ + bid->status = STUB_BUSID_OTHER; ++ /* release the busid lock */ ++ put_busid_priv(bid); + + ret = do_rebind((char *) buf, bid); + if (ret < 0) diff --git a/queue-3.18/usbip-usbip_host-refine-probe-and-disconnect-debug-msgs-to-be-useful.patch b/queue-3.18/usbip-usbip_host-refine-probe-and-disconnect-debug-msgs-to-be-useful.patch new file mode 100644 index 00000000000..e9555427d07 --- /dev/null +++ b/queue-3.18/usbip-usbip_host-refine-probe-and-disconnect-debug-msgs-to-be-useful.patch @@ -0,0 +1,40 @@ +From 28b68acc4a88dcf91fd1dcf2577371dc9bf574cc Mon Sep 17 00:00:00 2001 +From: Shuah Khan +Date: Wed, 11 Apr 2018 18:13:30 -0600 +Subject: usbip: usbip_host: refine probe and disconnect debug msgs to be useful + +From: Shuah Khan + +commit 28b68acc4a88dcf91fd1dcf2577371dc9bf574cc upstream. + +Refine probe and disconnect debug msgs to be useful and say what is +in progress. + +Signed-off-by: Shuah Khan +Cc: stable +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/usbip/stub_dev.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/usb/usbip/stub_dev.c ++++ b/drivers/usb/usbip/stub_dev.c +@@ -317,7 +317,7 @@ static int stub_probe(struct usb_device + struct bus_id_priv *busid_priv; + int rc; + +- dev_dbg(&udev->dev, "Enter\n"); ++ dev_dbg(&udev->dev, "Enter probe\n"); + + /* check we should claim or not by busid_table */ + busid_priv = get_busid_priv(udev_busid); +@@ -415,7 +415,7 @@ static void stub_disconnect(struct usb_d + struct bus_id_priv *busid_priv; + int rc; + +- dev_dbg(&udev->dev, "Enter\n"); ++ dev_dbg(&udev->dev, "Enter disconnect\n"); + + busid_priv = get_busid_priv(udev_busid); + if (!busid_priv) { diff --git a/queue-3.18/usbip-usbip_host-run-rebind-from-exit-when-module-is-removed.patch b/queue-3.18/usbip-usbip_host-run-rebind-from-exit-when-module-is-removed.patch new file mode 100644 index 00000000000..993fd112d50 --- /dev/null +++ b/queue-3.18/usbip-usbip_host-run-rebind-from-exit-when-module-is-removed.patch @@ -0,0 +1,135 @@ +From 7510df3f29d44685bab7b1918b61a8ccd57126a9 Mon Sep 17 00:00:00 2001 +From: "Shuah Khan (Samsung OSG)" +Date: Mon, 30 Apr 2018 16:17:20 -0600 +Subject: usbip: usbip_host: run rebind from exit when module is removed + +From: Shuah Khan (Samsung OSG) + +commit 7510df3f29d44685bab7b1918b61a8ccd57126a9 upstream. + +After removing usbip_host module, devices it releases are left without +a driver. For example, when a keyboard or a mass storage device are +bound to usbip_host when it is removed, these devices are no longer +bound to any driver. + +Fix it to run device_attach() from the module exit routine to restore +the devices to their original drivers. This includes cleanup changes +and moving device_attach() code to a common routine to be called from +rebind_store() and usbip_host_exit(). + +Signed-off-by: Shuah Khan (Samsung OSG) +Cc: stable +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/usbip/stub_dev.c | 6 ---- + drivers/usb/usbip/stub_main.c | 60 +++++++++++++++++++++++++++++++++++------- + 2 files changed, 52 insertions(+), 14 deletions(-) + +--- a/drivers/usb/usbip/stub_dev.c ++++ b/drivers/usb/usbip/stub_dev.c +@@ -459,12 +459,8 @@ static void stub_disconnect(struct usb_d + busid_priv->sdev = NULL; + stub_device_free(sdev); + +- if (busid_priv->status == STUB_BUSID_ALLOC) { ++ if (busid_priv->status == STUB_BUSID_ALLOC) + busid_priv->status = STUB_BUSID_ADDED; +- } else { +- busid_priv->status = STUB_BUSID_OTHER; +- del_match_busid((char *)udev_busid); +- } + } + + #ifdef CONFIG_PM +--- a/drivers/usb/usbip/stub_main.c ++++ b/drivers/usb/usbip/stub_main.c +@@ -28,6 +28,7 @@ + #define DRIVER_DESC "USB/IP Host Driver" + + struct kmem_cache *stub_priv_cache; ++ + /* + * busid_tables defines matching busids that usbip can grab. A user can change + * dynamically what device is locally used and what device is exported to a +@@ -184,6 +185,51 @@ static ssize_t store_match_busid(struct + static DRIVER_ATTR(match_busid, S_IRUSR | S_IWUSR, show_match_busid, + store_match_busid); + ++static int do_rebind(char *busid, struct bus_id_priv *busid_priv) ++{ ++ int ret; ++ ++ /* device_attach() callers should hold parent lock for USB */ ++ if (busid_priv->udev->dev.parent) ++ device_lock(busid_priv->udev->dev.parent); ++ ret = device_attach(&busid_priv->udev->dev); ++ if (busid_priv->udev->dev.parent) ++ device_unlock(busid_priv->udev->dev.parent); ++ if (ret < 0) { ++ dev_err(&busid_priv->udev->dev, "rebind failed\n"); ++ return ret; ++ } ++ return 0; ++} ++ ++static void stub_device_rebind(void) ++{ ++#if IS_MODULE(CONFIG_USBIP_HOST) ++ struct bus_id_priv *busid_priv; ++ int i; ++ ++ /* update status to STUB_BUSID_OTHER so probe ignores the device */ ++ spin_lock(&busid_table_lock); ++ for (i = 0; i < MAX_BUSID; i++) { ++ if (busid_table[i].name[0] && ++ busid_table[i].shutdown_busid) { ++ busid_priv = &(busid_table[i]); ++ busid_priv->status = STUB_BUSID_OTHER; ++ } ++ } ++ spin_unlock(&busid_table_lock); ++ ++ /* now run rebind */ ++ for (i = 0; i < MAX_BUSID; i++) { ++ if (busid_table[i].name[0] && ++ busid_table[i].shutdown_busid) { ++ busid_priv = &(busid_table[i]); ++ do_rebind(busid_table[i].name, busid_priv); ++ } ++ } ++#endif ++} ++ + static ssize_t rebind_store(struct device_driver *dev, const char *buf, + size_t count) + { +@@ -204,16 +250,9 @@ static ssize_t rebind_store(struct devic + /* mark the device for deletion so probe ignores it during rescan */ + bid->status = STUB_BUSID_OTHER; + +- /* device_attach() callers should hold parent lock for USB */ +- if (bid->udev->dev.parent) +- device_lock(bid->udev->dev.parent); +- ret = device_attach(&bid->udev->dev); +- if (bid->udev->dev.parent) +- device_unlock(bid->udev->dev.parent); +- if (ret < 0) { +- dev_err(&bid->udev->dev, "rebind failed\n"); ++ ret = do_rebind((char *) buf, bid); ++ if (ret < 0) + return ret; +- } + + /* delete device from busid_table */ + del_match_busid((char *) buf); +@@ -339,6 +378,9 @@ static void __exit usbip_host_exit(void) + */ + usb_deregister_device_driver(&stub_driver); + ++ /* initiate scan to attach devices */ ++ stub_device_rebind(); ++ + kmem_cache_destroy(stub_priv_cache); + } + -- 2.47.3