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

platform/x86: classmate-laptop: Add missing NULL pointer checks

In a few places in the Classmate laptop driver, code using the accel
object may run before that object's address is stored in the driver
data of the input device using it.

For example, cmpc_accel_sensitivity_store_v4() is the "show" method
of cmpc_accel_sensitivity_attr_v4 which is added in cmpc_accel_add_v4(),
before calling dev_set_drvdata() for inputdev->dev. If the sysfs
attribute is accessed prematurely, the dev_get_drvdata(&inputdev->dev)
call in in cmpc_accel_sensitivity_store_v4() returns NULL which
leads to a NULL pointer dereference going forward.

Moreover, sysfs attributes using the input device are added before
initializing that device by cmpc_add_acpi_notify_device() and if one
of them is accessed before running that function, a NULL pointer
dereference will occur.

For example, cmpc_accel_sensitivity_attr_v4 is added before calling
cmpc_add_acpi_notify_device() and if it is read prematurely, the
dev_get_drvdata(&acpi->dev) call in cmpc_accel_sensitivity_show_v4()
returns NULL which leads to a NULL pointer dereference going forward.

Fix this by adding NULL pointer checks in all of the relevant places.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Link: https://patch.msgid.link/12825381.O9o76ZdvQC@rafael.j.wysocki
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>

authored by

Rafael J. Wysocki and committed by
Ilpo Järvinen
fe747d71 662c9cb8

+32
+32
drivers/platform/x86/classmate-laptop.c
··· 207 207 208 208 acpi = to_acpi_device(dev); 209 209 inputdev = dev_get_drvdata(&acpi->dev); 210 + if (!inputdev) 211 + return -ENXIO; 212 + 210 213 accel = dev_get_drvdata(&inputdev->dev); 214 + if (!accel) 215 + return -ENXIO; 211 216 212 217 return sysfs_emit(buf, "%d\n", accel->sensitivity); 213 218 } ··· 229 224 230 225 acpi = to_acpi_device(dev); 231 226 inputdev = dev_get_drvdata(&acpi->dev); 227 + if (!inputdev) 228 + return -ENXIO; 229 + 232 230 accel = dev_get_drvdata(&inputdev->dev); 231 + if (!accel) 232 + return -ENXIO; 233 233 234 234 r = kstrtoul(buf, 0, &sensitivity); 235 235 if (r) ··· 266 256 267 257 acpi = to_acpi_device(dev); 268 258 inputdev = dev_get_drvdata(&acpi->dev); 259 + if (!inputdev) 260 + return -ENXIO; 261 + 269 262 accel = dev_get_drvdata(&inputdev->dev); 263 + if (!accel) 264 + return -ENXIO; 270 265 271 266 return sysfs_emit(buf, "%d\n", accel->g_select); 272 267 } ··· 288 273 289 274 acpi = to_acpi_device(dev); 290 275 inputdev = dev_get_drvdata(&acpi->dev); 276 + if (!inputdev) 277 + return -ENXIO; 278 + 291 279 accel = dev_get_drvdata(&inputdev->dev); 280 + if (!accel) 281 + return -ENXIO; 292 282 293 283 r = kstrtoul(buf, 0, &g_select); 294 284 if (r) ··· 322 302 323 303 acpi = to_acpi_device(input->dev.parent); 324 304 accel = dev_get_drvdata(&input->dev); 305 + if (!accel) 306 + return -ENXIO; 325 307 326 308 cmpc_accel_set_sensitivity_v4(acpi->handle, accel->sensitivity); 327 309 cmpc_accel_set_g_select_v4(acpi->handle, accel->g_select); ··· 571 549 572 550 acpi = to_acpi_device(dev); 573 551 inputdev = dev_get_drvdata(&acpi->dev); 552 + if (!inputdev) 553 + return -ENXIO; 554 + 574 555 accel = dev_get_drvdata(&inputdev->dev); 556 + if (!accel) 557 + return -ENXIO; 575 558 576 559 return sysfs_emit(buf, "%d\n", accel->sensitivity); 577 560 } ··· 593 566 594 567 acpi = to_acpi_device(dev); 595 568 inputdev = dev_get_drvdata(&acpi->dev); 569 + if (!inputdev) 570 + return -ENXIO; 571 + 596 572 accel = dev_get_drvdata(&inputdev->dev); 573 + if (!accel) 574 + return -ENXIO; 597 575 598 576 r = kstrtoul(buf, 0, &sensitivity); 599 577 if (r)