diff options
author | Will Deacon | 2020-12-15 09:48:22 -0600 |
---|---|---|
committer | Giuliano Procida | 2020-12-30 04:20:47 -0600 |
commit | 926e1040f4037b12ffabac4e9a895b0832d3ac42 (patch) | |
tree | e06a1920d65d0ca1368a7a02b8e97da171090076 | |
parent | 342a4badfd6a728f35328b7755da01cba49f051d (diff) | |
download | kernel-926e1040f4037b12ffabac4e9a895b0832d3ac42.tar.gz kernel-926e1040f4037b12ffabac4e9a895b0832d3ac42.tar.xz kernel-926e1040f4037b12ffabac4e9a895b0832d3ac42.zip |
ANDROID: usb: f_accessory: Fix teardown ordering in acc_release()
acc_release() attempts to synchronise with acc_open() using an atomic
'open_excl' member in 'struct acc_dev'. Unfortunately, acc_release()
prematurely resets this atomic variable to zero, meaning there is a
potential race on 'dev->disconnected':
acc_open() acc_release()
atomic_xchg(open_excl), 0)
atomic_xchg(open_excl, 1)
dev->disconnected = 0; dev->disconnected = 1;
Fix the race by ensuring that the 'disconnected' field is written
before clearing 'open_excl' in acc_release().
Bug: 173789633
Signed-off-by: Will Deacon <willdeacon@google.com>
Change-Id: Ib9a21f2305f6d70de3e760da62dbfdd66889200a
Signed-off-by: Giuliano Procida <gprocida@google.com>
-rw-r--r-- | drivers/usb/gadget/function/f_accessory.c | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/drivers/usb/gadget/function/f_accessory.c b/drivers/usb/gadget/function/f_accessory.c index 089e27790d29..ab3e47c1083e 100644 --- a/drivers/usb/gadget/function/f_accessory.c +++ b/drivers/usb/gadget/function/f_accessory.c | |||
@@ -899,13 +899,13 @@ static int acc_release(struct inode *ip, struct file *fp) | |||
899 | if (!dev) | 899 | if (!dev) |
900 | return -ENOENT; | 900 | return -ENOENT; |
901 | 901 | ||
902 | WARN_ON(!atomic_xchg(&dev->open_excl, 0)); | ||
903 | /* indicate that we are disconnected | 902 | /* indicate that we are disconnected |
904 | * still could be online so don't touch online flag | 903 | * still could be online so don't touch online flag |
905 | */ | 904 | */ |
906 | dev->disconnected = 1; | 905 | dev->disconnected = 1; |
907 | 906 | ||
908 | fp->private_data = NULL; | 907 | fp->private_data = NULL; |
908 | WARN_ON(!atomic_xchg(&dev->open_excl, 0)); | ||
909 | put_acc_dev(dev); | 909 | put_acc_dev(dev); |
910 | return 0; | 910 | return 0; |
911 | } | 911 | } |