Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Input: psmouse - fix cleaning up SMBus companions

When trying to destroy platform data after destruction of SMbus companion,
we need to make sure that we are actually dealing with an SMB companion
device, and not some random I2C client device.

Fixes: 8eb92e5c9133 ("Input: psmouse - add support for SMBus companions")
Reported-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Tested-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

+19 -11
+19 -11
drivers/input/mouse/psmouse-smbus.c
··· 61 61 62 62 static void psmouse_smbus_detach_i2c_client(struct i2c_client *client) 63 63 { 64 - struct psmouse_smbus_dev *smbdev; 64 + struct psmouse_smbus_dev *smbdev, *tmp; 65 65 66 66 mutex_lock(&psmouse_smbus_mutex); 67 67 68 - list_for_each_entry(smbdev, &psmouse_smbus_list, node) { 69 - if (smbdev->client == client) { 68 + list_for_each_entry_safe(smbdev, tmp, &psmouse_smbus_list, node) { 69 + if (smbdev->client != client) 70 + continue; 71 + 72 + kfree(client->dev.platform_data); 73 + client->dev.platform_data = NULL; 74 + 75 + if (!smbdev->dead) { 70 76 psmouse_dbg(smbdev->psmouse, 71 77 "Marking SMBus companion %s as gone\n", 72 78 dev_name(&smbdev->client->dev)); 73 - smbdev->client = NULL; 74 79 smbdev->dead = true; 75 80 serio_rescan(smbdev->psmouse->ps2dev.serio); 81 + } else { 82 + list_del(&smbdev->node); 83 + kfree(smbdev); 76 84 } 77 85 } 78 - 79 - kfree(client->dev.platform_data); 80 - client->dev.platform_data = NULL; 81 86 82 87 mutex_unlock(&psmouse_smbus_mutex); 83 88 } ··· 167 162 struct psmouse_smbus_dev *smbdev = psmouse->private; 168 163 169 164 mutex_lock(&psmouse_smbus_mutex); 170 - list_del(&smbdev->node); 171 - mutex_unlock(&psmouse_smbus_mutex); 172 165 173 - if (smbdev->client) { 166 + if (smbdev->dead) { 167 + list_del(&smbdev->node); 168 + kfree(smbdev); 169 + } else { 170 + smbdev->dead = true; 174 171 psmouse_dbg(smbdev->psmouse, 175 172 "posting removal request for SMBus companion %s\n", 176 173 dev_name(&smbdev->client->dev)); 177 174 psmouse_smbus_schedule_remove(smbdev->client); 178 175 } 179 176 180 - kfree(smbdev); 177 + mutex_unlock(&psmouse_smbus_mutex); 178 + 181 179 psmouse->private = NULL; 182 180 } 183 181