Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0999bcc4 authored by Will Deacon's avatar Will Deacon Committed by Giuliano Procida
Browse files

ANDROID: usb: f_accessory: Don't corrupt global state on double registration



If acc_setup() is called when there is already an allocated instance,
misc_register() will fail but the error path leaves a dangling pointer
to freed memory in the global 'acc_dev' state.

Fix this by ensuring that the refcount is zero before we start, and then
using a cmpxchg() from NULL to serialise any concurrent initialisers.

Bug: 173789633
Signed-off-by: default avatarWill Deacon <willdeacon@google.com>
Change-Id: I2c26289dcce7dbc493964516c49b05d04aaa6839
Signed-off-by: default avatarGiuliano Procida <gprocida@google.com>
parent 0bd4d0a7
Loading
Loading
Loading
Loading
+12 −4
Original line number Diff line number Diff line
@@ -1258,6 +1258,9 @@ static int acc_setup(void)
	struct acc_dev *dev;
	int ret;

	if (kref_read(&ref->kref))
		return -EBUSY;

	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
	if (!dev)
		return -ENOMEM;
@@ -1274,16 +1277,21 @@ static int acc_setup(void)
	INIT_WORK(&dev->hid_work, acc_hid_work);

	dev->ref = ref;
	kref_init(&ref->kref);
	ref->acc_dev = dev;
	if (cmpxchg_relaxed(&ref->acc_dev, NULL, dev)) {
		ret = -EBUSY;
		goto err_free_dev;
	}

	ret = misc_register(&acc_device);
	if (ret)
		goto err;
		goto err_zap_ptr;

	kref_init(&ref->kref);
	return 0;

err:
err_zap_ptr:
	ref->acc_dev = NULL;
err_free_dev:
	kfree(dev);
	pr_err("USB accessory gadget driver failed to initialize\n");
	return ret;