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

drivers/virt/fsl_hypervisor.c: dereferencing error pointers in ioctl

strndup_user() returns error pointers on error, and then in the error
handling we pass the error pointers to kfree(). It will cause an Oops.

Link: http://lkml.kernel.org/r/20181218082003.GD32567@kadam
Fixes: 6db7199407ca ("drivers/virt: introduce Freescale hypervisor management driver")
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Reviewed-by: Andrew Morton <akpm@linux-foundation.org>
Cc: Timur Tabi <timur@freescale.com>
Cc: Mihai Caraman <mihai.caraman@freescale.com>
Cc: Kumar Gala <galak@kernel.crashing.org>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Dan Carpenter and committed by
Linus Torvalds
c8ea3663 871789d4

+13 -13
+13 -13
drivers/virt/fsl_hypervisor.c
··· 331 331 struct fsl_hv_ioctl_prop param; 332 332 char __user *upath, *upropname; 333 333 void __user *upropval; 334 - char *path = NULL, *propname = NULL; 335 - void *propval = NULL; 334 + char *path, *propname; 335 + void *propval; 336 336 int ret = 0; 337 337 338 338 /* Get the parameters from the user. */ ··· 344 344 upropval = (void __user *)(uintptr_t)param.propval; 345 345 346 346 path = strndup_user(upath, FH_DTPROP_MAX_PATHLEN); 347 - if (IS_ERR(path)) { 348 - ret = PTR_ERR(path); 349 - goto out; 350 - } 347 + if (IS_ERR(path)) 348 + return PTR_ERR(path); 351 349 352 350 propname = strndup_user(upropname, FH_DTPROP_MAX_PATHLEN); 353 351 if (IS_ERR(propname)) { 354 352 ret = PTR_ERR(propname); 355 - goto out; 353 + goto err_free_path; 356 354 } 357 355 358 356 if (param.proplen > FH_DTPROP_MAX_PROPLEN) { 359 357 ret = -EINVAL; 360 - goto out; 358 + goto err_free_propname; 361 359 } 362 360 363 361 propval = kmalloc(param.proplen, GFP_KERNEL); 364 362 if (!propval) { 365 363 ret = -ENOMEM; 366 - goto out; 364 + goto err_free_propname; 367 365 } 368 366 369 367 if (set) { 370 368 if (copy_from_user(propval, upropval, param.proplen)) { 371 369 ret = -EFAULT; 372 - goto out; 370 + goto err_free_propval; 373 371 } 374 372 375 373 param.ret = fh_partition_set_dtprop(param.handle, ··· 386 388 if (copy_to_user(upropval, propval, param.proplen) || 387 389 put_user(param.proplen, &p->proplen)) { 388 390 ret = -EFAULT; 389 - goto out; 391 + goto err_free_propval; 390 392 } 391 393 } 392 394 } ··· 394 396 if (put_user(param.ret, &p->ret)) 395 397 ret = -EFAULT; 396 398 397 - out: 398 - kfree(path); 399 + err_free_propval: 399 400 kfree(propval); 401 + err_free_propname: 400 402 kfree(propname); 403 + err_free_path: 404 + kfree(path); 401 405 402 406 return ret; 403 407 }