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>
diff --git a/drivers/usb/gadget/function/f_accessory.c b/drivers/usb/gadget/function/f_accessory.c
index 97a6bd8..592d59c 100644
--- a/drivers/usb/gadget/function/f_accessory.c
+++ b/drivers/usb/gadget/function/f_accessory.c
@@ -824,13 +824,13 @@
if (!dev)
return -ENOENT;
- WARN_ON(!atomic_xchg(&dev->open_excl, 0));
/* indicate that we are disconnected
* still could be online so don't touch online flag
*/
dev->disconnected = 1;
fp->private_data = NULL;
+ WARN_ON(!atomic_xchg(&dev->open_excl, 0));
put_acc_dev(dev);
return 0;
}