From 4df1d2ffe1765f7bbfae61ca3c3bedbc83fa699d Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 15 Dec 2020 15:48:22 +0000 Subject: [PATCH] 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 Change-Id: Ib9a21f2305f6d70de3e760da62dbfdd66889200a Signed-off-by: Giuliano Procida --- drivers/usb/gadget/function/f_accessory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/function/f_accessory.c b/drivers/usb/gadget/function/f_accessory.c index 97a6bd8bac90..592d59c94222 100644 --- a/drivers/usb/gadget/function/f_accessory.c +++ b/drivers/usb/gadget/function/f_accessory.c @@ -824,13 +824,13 @@ static int acc_release(struct inode *ip, struct file *fp) 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; }