]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.9-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 30 Mar 2017 08:58:35 +0000 (10:58 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 30 Mar 2017 08:58:35 +0000 (10:58 +0200)
added patches:
fscrypt-remove-broken-support-for-detecting-keyring-key-revocation.patch
sched-rt-add-a-missing-rescheduling-point.patch
usb-musb-fix-possible-spinlock-deadlock.patch

queue-4.9/fscrypt-remove-broken-support-for-detecting-keyring-key-revocation.patch [new file with mode: 0644]
queue-4.9/kvm-x86-cleanup-the-page-tracking-srcu-instance.patch [deleted file]
queue-4.9/sched-rt-add-a-missing-rescheduling-point.patch [new file with mode: 0644]
queue-4.9/series
queue-4.9/usb-musb-fix-possible-spinlock-deadlock.patch [new file with mode: 0644]

diff --git a/queue-4.9/fscrypt-remove-broken-support-for-detecting-keyring-key-revocation.patch b/queue-4.9/fscrypt-remove-broken-support-for-detecting-keyring-key-revocation.patch
new file mode 100644 (file)
index 0000000..bf6ccee
--- /dev/null
@@ -0,0 +1,245 @@
+From 1b53cf9815bb4744958d41f3795d5d5a1d365e2d Mon Sep 17 00:00:00 2001
+From: Eric Biggers <ebiggers@google.com>
+Date: Tue, 21 Feb 2017 15:07:11 -0800
+Subject: fscrypt: remove broken support for detecting keyring key revocation
+
+From: Eric Biggers <ebiggers@google.com>
+
+commit 1b53cf9815bb4744958d41f3795d5d5a1d365e2d upstream.
+
+Filesystem encryption ostensibly supported revoking a keyring key that
+had been used to "unlock" encrypted files, causing those files to become
+"locked" again.  This was, however, buggy for several reasons, the most
+severe of which was that when key revocation happened to be detected for
+an inode, its fscrypt_info was immediately freed, even while other
+threads could be using it for encryption or decryption concurrently.
+This could be exploited to crash the kernel or worse.
+
+This patch fixes the use-after-free by removing the code which detects
+the keyring key having been revoked, invalidated, or expired.  Instead,
+an encrypted inode that is "unlocked" now simply remains unlocked until
+it is evicted from memory.  Note that this is no worse than the case for
+block device-level encryption, e.g. dm-crypt, and it still remains
+possible for a privileged user to evict unused pages, inodes, and
+dentries by running 'sync; echo 3 > /proc/sys/vm/drop_caches', or by
+simply unmounting the filesystem.  In fact, one of those actions was
+already needed anyway for key revocation to work even somewhat sanely.
+This change is not expected to break any applications.
+
+In the future I'd like to implement a real API for fscrypt key
+revocation that interacts sanely with ongoing filesystem operations ---
+waiting for existing operations to complete and blocking new operations,
+and invalidating and sanitizing key material and plaintext from the VFS
+caches.  But this is a hard problem, and for now this bug must be fixed.
+
+This bug affected almost all versions of ext4, f2fs, and ubifs
+encryption, and it was potentially reachable in any kernel configured
+with encryption support (CONFIG_EXT4_ENCRYPTION=y,
+CONFIG_EXT4_FS_ENCRYPTION=y, CONFIG_F2FS_FS_ENCRYPTION=y, or
+CONFIG_UBIFS_FS_ENCRYPTION=y).  Note that older kernels did not use the
+shared fs/crypto/ code, but due to the potential security implications
+of this bug, it may still be worthwhile to backport this fix to them.
+
+Fixes: b7236e21d55f ("ext4 crypto: reorganize how we store keys in the inode")
+Signed-off-by: Eric Biggers <ebiggers@google.com>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Acked-by: Michael Halcrow <mhalcrow@google.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/crypto/crypto.c       |   10 ---------
+ fs/crypto/fname.c        |    2 -
+ fs/crypto/keyinfo.c      |   52 ++++++++---------------------------------------
+ include/linux/fscrypto.h |    2 -
+ 4 files changed, 11 insertions(+), 55 deletions(-)
+
+--- a/fs/crypto/crypto.c
++++ b/fs/crypto/crypto.c
+@@ -352,7 +352,6 @@ EXPORT_SYMBOL(fscrypt_zeroout_range);
+ static int fscrypt_d_revalidate(struct dentry *dentry, unsigned int flags)
+ {
+       struct dentry *dir;
+-      struct fscrypt_info *ci;
+       int dir_has_key, cached_with_key;
+       if (flags & LOOKUP_RCU)
+@@ -364,18 +363,11 @@ static int fscrypt_d_revalidate(struct d
+               return 0;
+       }
+-      ci = d_inode(dir)->i_crypt_info;
+-      if (ci && ci->ci_keyring_key &&
+-          (ci->ci_keyring_key->flags & ((1 << KEY_FLAG_INVALIDATED) |
+-                                        (1 << KEY_FLAG_REVOKED) |
+-                                        (1 << KEY_FLAG_DEAD))))
+-              ci = NULL;
+-
+       /* this should eventually be an flag in d_flags */
+       spin_lock(&dentry->d_lock);
+       cached_with_key = dentry->d_flags & DCACHE_ENCRYPTED_WITH_KEY;
+       spin_unlock(&dentry->d_lock);
+-      dir_has_key = (ci != NULL);
++      dir_has_key = (d_inode(dir)->i_crypt_info != NULL);
+       dput(dir);
+       /*
+--- a/fs/crypto/fname.c
++++ b/fs/crypto/fname.c
+@@ -350,7 +350,7 @@ int fscrypt_setup_filename(struct inode
+               fname->disk_name.len = iname->len;
+               return 0;
+       }
+-      ret = get_crypt_info(dir);
++      ret = fscrypt_get_encryption_info(dir);
+       if (ret && ret != -EOPNOTSUPP)
+               return ret;
+--- a/fs/crypto/keyinfo.c
++++ b/fs/crypto/keyinfo.c
+@@ -99,6 +99,7 @@ static int validate_user_key(struct fscr
+       kfree(full_key_descriptor);
+       if (IS_ERR(keyring_key))
+               return PTR_ERR(keyring_key);
++      down_read(&keyring_key->sem);
+       if (keyring_key->type != &key_type_logon) {
+               printk_once(KERN_WARNING
+@@ -106,11 +107,9 @@ static int validate_user_key(struct fscr
+               res = -ENOKEY;
+               goto out;
+       }
+-      down_read(&keyring_key->sem);
+       ukp = user_key_payload(keyring_key);
+       if (ukp->datalen != sizeof(struct fscrypt_key)) {
+               res = -EINVAL;
+-              up_read(&keyring_key->sem);
+               goto out;
+       }
+       master_key = (struct fscrypt_key *)ukp->data;
+@@ -121,17 +120,11 @@ static int validate_user_key(struct fscr
+                               "%s: key size incorrect: %d\n",
+                               __func__, master_key->size);
+               res = -ENOKEY;
+-              up_read(&keyring_key->sem);
+               goto out;
+       }
+       res = derive_key_aes(ctx->nonce, master_key->raw, raw_key);
+-      up_read(&keyring_key->sem);
+-      if (res)
+-              goto out;
+-
+-      crypt_info->ci_keyring_key = keyring_key;
+-      return 0;
+ out:
++      up_read(&keyring_key->sem);
+       key_put(keyring_key);
+       return res;
+ }
+@@ -173,12 +166,11 @@ static void put_crypt_info(struct fscryp
+       if (!ci)
+               return;
+-      key_put(ci->ci_keyring_key);
+       crypto_free_skcipher(ci->ci_ctfm);
+       kmem_cache_free(fscrypt_info_cachep, ci);
+ }
+-int get_crypt_info(struct inode *inode)
++int fscrypt_get_encryption_info(struct inode *inode)
+ {
+       struct fscrypt_info *crypt_info;
+       struct fscrypt_context ctx;
+@@ -188,21 +180,15 @@ int get_crypt_info(struct inode *inode)
+       u8 *raw_key = NULL;
+       int res;
++      if (inode->i_crypt_info)
++              return 0;
++
+       res = fscrypt_initialize();
+       if (res)
+               return res;
+       if (!inode->i_sb->s_cop->get_context)
+               return -EOPNOTSUPP;
+-retry:
+-      crypt_info = ACCESS_ONCE(inode->i_crypt_info);
+-      if (crypt_info) {
+-              if (!crypt_info->ci_keyring_key ||
+-                              key_validate(crypt_info->ci_keyring_key) == 0)
+-                      return 0;
+-              fscrypt_put_encryption_info(inode, crypt_info);
+-              goto retry;
+-      }
+       res = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx));
+       if (res < 0) {
+@@ -230,7 +216,6 @@ retry:
+       crypt_info->ci_data_mode = ctx.contents_encryption_mode;
+       crypt_info->ci_filename_mode = ctx.filenames_encryption_mode;
+       crypt_info->ci_ctfm = NULL;
+-      crypt_info->ci_keyring_key = NULL;
+       memcpy(crypt_info->ci_master_key, ctx.master_key_descriptor,
+                               sizeof(crypt_info->ci_master_key));
+@@ -285,14 +270,8 @@ got_key:
+       if (res)
+               goto out;
+-      kzfree(raw_key);
+-      raw_key = NULL;
+-      if (cmpxchg(&inode->i_crypt_info, NULL, crypt_info) != NULL) {
+-              put_crypt_info(crypt_info);
+-              goto retry;
+-      }
+-      return 0;
+-
++      if (cmpxchg(&inode->i_crypt_info, NULL, crypt_info) == NULL)
++              crypt_info = NULL;
+ out:
+       if (res == -ENOKEY)
+               res = 0;
+@@ -300,6 +279,7 @@ out:
+       kzfree(raw_key);
+       return res;
+ }
++EXPORT_SYMBOL(fscrypt_get_encryption_info);
+ void fscrypt_put_encryption_info(struct inode *inode, struct fscrypt_info *ci)
+ {
+@@ -317,17 +297,3 @@ void fscrypt_put_encryption_info(struct
+       put_crypt_info(ci);
+ }
+ EXPORT_SYMBOL(fscrypt_put_encryption_info);
+-
+-int fscrypt_get_encryption_info(struct inode *inode)
+-{
+-      struct fscrypt_info *ci = inode->i_crypt_info;
+-
+-      if (!ci ||
+-              (ci->ci_keyring_key &&
+-               (ci->ci_keyring_key->flags & ((1 << KEY_FLAG_INVALIDATED) |
+-                                             (1 << KEY_FLAG_REVOKED) |
+-                                             (1 << KEY_FLAG_DEAD)))))
+-              return get_crypt_info(inode);
+-      return 0;
+-}
+-EXPORT_SYMBOL(fscrypt_get_encryption_info);
+--- a/include/linux/fscrypto.h
++++ b/include/linux/fscrypto.h
+@@ -79,7 +79,6 @@ struct fscrypt_info {
+       u8 ci_filename_mode;
+       u8 ci_flags;
+       struct crypto_skcipher *ci_ctfm;
+-      struct key *ci_keyring_key;
+       u8 ci_master_key[FS_KEY_DESCRIPTOR_SIZE];
+ };
+@@ -256,7 +255,6 @@ extern int fscrypt_has_permitted_context
+ extern int fscrypt_inherit_context(struct inode *, struct inode *,
+                                       void *, bool);
+ /* keyinfo.c */
+-extern int get_crypt_info(struct inode *);
+ extern int fscrypt_get_encryption_info(struct inode *);
+ extern void fscrypt_put_encryption_info(struct inode *, struct fscrypt_info *);
diff --git a/queue-4.9/kvm-x86-cleanup-the-page-tracking-srcu-instance.patch b/queue-4.9/kvm-x86-cleanup-the-page-tracking-srcu-instance.patch
deleted file mode 100644 (file)
index eb506ff..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-From 2beb6dad2e8f95d710159d5befb390e4f62ab5cf Mon Sep 17 00:00:00 2001
-From: Paolo Bonzini <pbonzini@redhat.com>
-Date: Mon, 27 Mar 2017 17:53:50 +0200
-Subject: KVM: x86: cleanup the page tracking SRCU instance
-
-From: Paolo Bonzini <pbonzini@redhat.com>
-
-commit 2beb6dad2e8f95d710159d5befb390e4f62ab5cf upstream.
-
-SRCU uses a delayed work item.  Skip cleaning it up, and
-the result is use-after-free in the work item callbacks.
-
-Reported-by: Dmitry Vyukov <dvyukov@google.com>
-Suggested-by: Dmitry Vyukov <dvyukov@google.com>
-Fixes: 0eb05bf290cfe8610d9680b49abef37febd1c38a
-Reviewed-by: Xiao Guangrong <xiaoguangrong.eric@gmail.com>
-Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
----
- arch/x86/include/asm/kvm_page_track.h |    1 +
- arch/x86/kvm/page_track.c             |    8 ++++++++
- arch/x86/kvm/x86.c                    |    1 +
- 3 files changed, 10 insertions(+)
-
---- a/arch/x86/include/asm/kvm_page_track.h
-+++ b/arch/x86/include/asm/kvm_page_track.h
-@@ -35,6 +35,7 @@ struct kvm_page_track_notifier_node {
- };
- void kvm_page_track_init(struct kvm *kvm);
-+void kvm_page_track_cleanup(struct kvm *kvm);
- void kvm_page_track_free_memslot(struct kvm_memory_slot *free,
-                                struct kvm_memory_slot *dont);
---- a/arch/x86/kvm/page_track.c
-+++ b/arch/x86/kvm/page_track.c
-@@ -156,6 +156,14 @@ bool kvm_page_track_is_active(struct kvm
-       return !!ACCESS_ONCE(slot->arch.gfn_track[mode][index]);
- }
-+void kvm_page_track_cleanup(struct kvm *kvm)
-+{
-+      struct kvm_page_track_notifier_head *head;
-+
-+      head = &kvm->arch.track_notifier_head;
-+      cleanup_srcu_struct(&head->track_srcu);
-+}
-+
- void kvm_page_track_init(struct kvm *kvm)
- {
-       struct kvm_page_track_notifier_head *head;
---- a/arch/x86/kvm/x86.c
-+++ b/arch/x86/kvm/x86.c
-@@ -7976,6 +7976,7 @@ void kvm_arch_destroy_vm(struct kvm *kvm
-       kvm_free_vcpus(kvm);
-       kvfree(rcu_dereference_check(kvm->arch.apic_map, 1));
-       kvm_mmu_uninit_vm(kvm);
-+      kvm_page_track_cleanup(kvm);
- }
- void kvm_arch_free_memslot(struct kvm *kvm, struct kvm_memory_slot *free,
diff --git a/queue-4.9/sched-rt-add-a-missing-rescheduling-point.patch b/queue-4.9/sched-rt-add-a-missing-rescheduling-point.patch
new file mode 100644 (file)
index 0000000..bd0aaf0
--- /dev/null
@@ -0,0 +1,76 @@
+From 619bd4a71874a8fd78eb6ccf9f272c5e98bcc7b7 Mon Sep 17 00:00:00 2001
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Tue, 24 Jan 2017 15:40:06 +0100
+Subject: sched/rt: Add a missing rescheduling point
+
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+
+commit 619bd4a71874a8fd78eb6ccf9f272c5e98bcc7b7 upstream.
+
+Since the change in commit:
+
+  fd7a4bed1835 ("sched, rt: Convert switched_{from, to}_rt() / prio_changed_rt() to balance callbacks")
+
+... we don't reschedule a task under certain circumstances:
+
+Lets say task-A, SCHED_OTHER, is running on CPU0 (and it may run only on
+CPU0) and holds a PI lock. This task is removed from the CPU because it
+used up its time slice and another SCHED_OTHER task is running. Task-B on
+CPU1 runs at RT priority and asks for the lock owned by task-A. This
+results in a priority boost for task-A. Task-B goes to sleep until the
+lock has been made available. Task-A is already runnable (but not active),
+so it receives no wake up.
+
+The reality now is that task-A gets on the CPU once the scheduler decides
+to remove the current task despite the fact that a high priority task is
+enqueued and waiting. This may take a long time.
+
+The desired behaviour is that CPU0 immediately reschedules after the
+priority boost which made task-A the task with the lowest priority.
+
+Suggested-by: Peter Zijlstra <peterz@infradead.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Mike Galbraith <efault@gmx.de>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Fixes: fd7a4bed1835 ("sched, rt: Convert switched_{from, to}_rt() prio_changed_rt() to balance callbacks")
+Link: http://lkml.kernel.org/r/20170124144006.29821-1-bigeasy@linutronix.de
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/sched/deadline.c |    3 +--
+ kernel/sched/rt.c       |    3 +--
+ 2 files changed, 2 insertions(+), 4 deletions(-)
+
+--- a/kernel/sched/deadline.c
++++ b/kernel/sched/deadline.c
+@@ -1729,12 +1729,11 @@ static void switched_to_dl(struct rq *rq
+ #ifdef CONFIG_SMP
+               if (tsk_nr_cpus_allowed(p) > 1 && rq->dl.overloaded)
+                       queue_push_tasks(rq);
+-#else
++#endif
+               if (dl_task(rq->curr))
+                       check_preempt_curr_dl(rq, p, 0);
+               else
+                       resched_curr(rq);
+-#endif
+       }
+ }
+--- a/kernel/sched/rt.c
++++ b/kernel/sched/rt.c
+@@ -2198,10 +2198,9 @@ static void switched_to_rt(struct rq *rq
+ #ifdef CONFIG_SMP
+               if (tsk_nr_cpus_allowed(p) > 1 && rq->rt.overloaded)
+                       queue_push_tasks(rq);
+-#else
++#endif /* CONFIG_SMP */
+               if (p->prio < rq->curr->prio)
+                       resched_curr(rq);
+-#endif /* CONFIG_SMP */
+       }
+ }
index 21514e8a2e4699f141fac495e9fbb9f9a425533b..c62286021f49a4a3edc190ce89ccf7fcb2070c95 100644 (file)
@@ -3,7 +3,6 @@ xfrm_user-validate-xfrm_msg_newae-xfrma_replay_esn_val-replay_window.patch
 xfrm_user-validate-xfrm_msg_newae-incoming-esn-size-harder.patch
 kvm-nvmx-invvpid-handling-improvements.patch
 kvm-nvmx-fix-nested-vpid-vmx-exec-control.patch
-kvm-x86-cleanup-the-page-tracking-srcu-instance.patch
 virtio_balloon-init-1st-buffer-in-stats-vq.patch
 pinctrl-qcom-don-t-clear-status-bit-on-irq_unmask.patch
 c6x-ptrace-remove-useless-ptrace_setregset-implementation.patch
@@ -13,3 +12,6 @@ sparc-ptrace-preserve-previous-registers-for-short-regset-write.patch
 metag-ptrace-preserve-previous-registers-for-short-regset-write.patch
 metag-ptrace-provide-default-txstatus-for-short-nt_prstatus.patch
 metag-ptrace-reject-partial-nt_metag_rpipe-writes.patch
+fscrypt-remove-broken-support-for-detecting-keyring-key-revocation.patch
+sched-rt-add-a-missing-rescheduling-point.patch
+usb-musb-fix-possible-spinlock-deadlock.patch
diff --git a/queue-4.9/usb-musb-fix-possible-spinlock-deadlock.patch b/queue-4.9/usb-musb-fix-possible-spinlock-deadlock.patch
new file mode 100644 (file)
index 0000000..5b094ed
--- /dev/null
@@ -0,0 +1,88 @@
+From bc1e2154542071e3cfe1734b143af9b8bdacf8bd Mon Sep 17 00:00:00 2001
+From: Bin Liu <b-liu@ti.com>
+Date: Fri, 10 Mar 2017 14:43:37 -0600
+Subject: usb: musb: fix possible spinlock deadlock
+
+From: Bin Liu <b-liu@ti.com>
+
+commit bc1e2154542071e3cfe1734b143af9b8bdacf8bd upstream.
+
+The DSPS glue calls del_timer_sync() in its musb_platform_disable()
+implementation, which requires the caller to not hold a lock. But
+musb_remove() calls musb_platform_disable() will musb->lock held. This
+could causes spinlock deadlock.
+
+So change musb_remove() to call musb_platform_disable() without holds
+musb->lock. This doesn't impact the musb_platform_disable implementation
+in other glue drivers.
+
+root@am335x-evm:~# modprobe -r musb-dsps
+[  126.134879] musb-hdrc musb-hdrc.1: remove, state 1
+[  126.140465] usb usb2: USB disconnect, device number 1
+[  126.146178] usb 2-1: USB disconnect, device number 2
+[  126.416985] musb-hdrc musb-hdrc.1: USB bus 2 deregistered
+[  126.423943]
+[  126.425525] ======================================================
+[  126.431997] [ INFO: possible circular locking dependency detected ]
+[  126.438564] 4.11.0-rc1-00003-g1557f13bca04-dirty #77 Not tainted
+[  126.444852] -------------------------------------------------------
+[  126.451414] modprobe/778 is trying to acquire lock:
+[  126.456523]  (((&glue->timer))){+.-...}, at: [<c01b8788>] del_timer_sync+0x0/0xd0
+[  126.464403]
+[  126.464403] but task is already holding lock:
+[  126.470511]  (&(&musb->lock)->rlock){-.-...}, at: [<bf30b7f8>] musb_remove+0x50/0x1
+30 [musb_hdrc]
+[  126.479965]
+[  126.479965] which lock already depends on the new lock.
+[  126.479965]
+[  126.488531]
+[  126.488531] the existing dependency chain (in reverse order) is:
+[  126.496368]
+[  126.496368] -> #1 (&(&musb->lock)->rlock){-.-...}:
+[  126.502968]        otg_timer+0x80/0xec [musb_dsps]
+[  126.507990]        call_timer_fn+0xb4/0x390
+[  126.512372]        expire_timers+0xf0/0x1fc
+[  126.516754]        run_timer_softirq+0x80/0x178
+[  126.521511]        __do_softirq+0xc4/0x554
+[  126.525802]        irq_exit+0xe8/0x158
+[  126.529735]        __handle_domain_irq+0x58/0xb8
+[  126.534583]        __irq_usr+0x54/0x80
+[  126.538507]
+[  126.538507] -> #0 (((&glue->timer))){+.-...}:
+[  126.544636]        del_timer_sync+0x40/0xd0
+[  126.549066]        musb_remove+0x6c/0x130 [musb_hdrc]
+[  126.554370]        platform_drv_remove+0x24/0x3c
+[  126.559206]        device_release_driver_internal+0x14c/0x1e0
+[  126.565225]        bus_remove_device+0xd8/0x108
+[  126.569970]        device_del+0x1e4/0x308
+[  126.574170]        platform_device_del+0x24/0x8c
+[  126.579006]        platform_device_unregister+0xc/0x20
+[  126.584394]        dsps_remove+0x14/0x30 [musb_dsps]
+[  126.589595]        platform_drv_remove+0x24/0x3c
+[  126.594432]        device_release_driver_internal+0x14c/0x1e0
+[  126.600450]        driver_detach+0x38/0x6c
+[  126.604740]        bus_remove_driver+0x4c/0xa0
+[  126.609407]        SyS_delete_module+0x11c/0x1e4
+[  126.614252]        __sys_trace_return+0x0/0x10
+
+Fixes: ea2f35c01d5ea ("usb: musb: Fix sleeping function called from invalid context for hdrc glue")
+Acked-by: Tony Lindgren <tony@atomide.com>
+Signed-off-by: Bin Liu <b-liu@ti.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/musb/musb_core.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/musb/musb_core.c
++++ b/drivers/usb/musb/musb_core.c
+@@ -2467,8 +2467,8 @@ static int musb_remove(struct platform_d
+       pm_runtime_get_sync(musb->controller);
+       musb_host_cleanup(musb);
+       musb_gadget_cleanup(musb);
+-      spin_lock_irqsave(&musb->lock, flags);
+       musb_platform_disable(musb);
++      spin_lock_irqsave(&musb->lock, flags);
+       musb_generic_disable(musb);
+       spin_unlock_irqrestore(&musb->lock, flags);
+       musb_writeb(musb->mregs, MUSB_DEVCTL, 0);