rc: Fix invalid free_region and/or free_irq on probe failure
Subsystems (2)
PATCH 1/1 rc: Fix invalid free_region and/or free_irq on probe failure
fintek-cir, ite-cir and nuvoton-cir may try to free an I/O region and/or IRQ handler that was never allocated after a failure in their respective probe functions. Add and use separate labels on the failure path so they will do the right cleanup after each possible point of failure.
Compile-tested only.
--- drivers/media/rc/fintek-cir.c | 13 ++++++------- drivers/media/rc/ite-cir.c | 14 ++++++-------- drivers/media/rc/nuvoton-cir.c | 26 ++++++++++++-------------- 3 files changed, 24 insertions(+), 29 deletions(-)
drivers/media/rc/fintek-cir.c +6 -7
@@ -556,11 +556,11 @@ static int fintek_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_idif (request_irq (fintek->cir_irq, fintek_cir_isr,IRQF_SHARED ,FINTEK_DRIVER_NAME , (void *)fintek)) - goto failure; + goto failure2; ret =rc_register_device (rdev);if (ret) - goto failure; + goto failure3;device_init_wakeup (&pdev->dev, true); fintek->rdev = rdev;
@@ -570,12 +570,11 @@ static int fintek_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_idreturn 0 ; +failure3: +free_irq (fintek->cir_irq, fintek); +failure2: +release_region (fintek->cir_addr, fintek->cir_port_len); failure: -if (fintek->cir_irq) -free_irq (fintek->cir_irq, fintek); -if (fintek->cir_addr) -release_region (fintek->cir_addr, fintek->cir_port_len); -rc_free_device (rdev);kfree (fintek);
drivers/media/rc/ite-cir.c +6 -8
@@ -1598,24 +1598,22 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_idif (request_irq (itdev->cir_irq, ite_cir_isr,IRQF_SHARED ,ITE_DRIVER_NAME , (void *)itdev)) - goto failure; + goto failure2; ret =rc_register_device (rdev);if (ret) - goto failure; + goto failure3; itdev->rdev = rdev;ite_pr (KERN_NOTICE ,"driver has been successfully loaded\n" );return 0 ; +failure3: +free_irq (itdev->cir_irq, itdev); +failure2: +release_region (itdev->cir_addr, itdev->params.io_region_size); failure: -if (itdev->cir_irq) -free_irq (itdev->cir_irq, itdev); - -if (itdev->cir_addr) -release_region (itdev->cir_addr, itdev->params.io_region_size); -rc_free_device (rdev);kfree (itdev);
drivers/media/rc/nuvoton-cir.c +12 -14
@@ -1075,19 +1075,19 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)if (request_irq (nvt->cir_irq, nvt_cir_isr,IRQF_SHARED ,NVT_DRIVER_NAME , (void *)nvt)) - goto failure; + goto failure2;if (!request_region (nvt->cir_wake_addr,CIR_IOREG_LENGTH ,NVT_DRIVER_NAME )) - goto failure; + goto failure3;if (request_irq (nvt->cir_wake_irq, nvt_cir_wake_isr,IRQF_SHARED ,NVT_DRIVER_NAME , (void *)nvt)) - goto failure; + goto failure4; ret =rc_register_device (rdev);if (ret) - goto failure; + goto failure5;device_init_wakeup (&pdev->dev, true); nvt->rdev = rdev;
@@ -1099,17 +1099,15 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)return 0 ; +failure5: +free_irq (nvt->cir_wake_irq, nvt); +failure4: +release_region (nvt->cir_wake_addr,CIR_IOREG_LENGTH ); +failure3: +free_irq (nvt->cir_irq, nvt); +failure2: +release_region (nvt->cir_addr,CIR_IOREG_LENGTH ); failure: -if (nvt->cir_irq) -free_irq (nvt->cir_irq, nvt); -if (nvt->cir_addr) -release_region (nvt->cir_addr,CIR_IOREG_LENGTH ); - -if (nvt->cir_wake_irq) -free_irq (nvt->cir_wake_irq, nvt); -if (nvt->cir_wake_addr) -release_region (nvt->cir_wake_addr,CIR_IOREG_LENGTH ); -rc_free_device (rdev);kfree (nvt);
Signature · 1 line
1.7.10
Quoted 9 lines · Ben Hutchings
fintek-cir, ite-cir and nuvoton-cir may try to free an I/O region and/or IRQ handler that was never allocated after a failure in their respective probe functions. Add and use separate labels on the failure path so they will do the right cleanup after each possible point of failure.
Compile-tested only.
Signed-off-by Ben Hutchings <[email protected]>
And this should probably go to stable as well, if you agree it's a valid fix.
Ben.
Quoted 130 lines
--- drivers/media/rc/fintek-cir.c | 13 ++++++------- drivers/media/rc/ite-cir.c | 14 ++++++-------- drivers/media/rc/nuvoton-cir.c | 26 ++++++++++++-------------- 3 files changed, 24 insertions(+), 29 deletions(-)drivers/media/rc/fintek-cir.c +6
-7@@ -556,11 +556,11 @@ static int fintek_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_idif (request_irq (fintek->cir_irq, fintek_cir_isr,IRQF_SHARED ,FINTEK_DRIVER_NAME , (void *)fintek)) - goto failure; + goto failure2; ret =rc_register_device (rdev);if (ret) - goto failure; + goto failure3;device_init_wakeup (&pdev->dev, true); fintek->rdev = rdev;@@ -570,12 +570,11 @@ static int fintek_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_idreturn 0 ; +failure3: +free_irq (fintek->cir_irq, fintek); +failure2: +release_region (fintek->cir_addr, fintek->cir_port_len); failure: -if (fintek->cir_irq) -free_irq (fintek->cir_irq, fintek); -if (fintek->cir_addr) -release_region (fintek->cir_addr, fintek->cir_port_len); -rc_free_device (rdev);kfree (fintek);drivers/media/rc/ite-cir.c +6
-8@@ -1598,24 +1598,22 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_idif (request_irq (itdev->cir_irq, ite_cir_isr,IRQF_SHARED ,ITE_DRIVER_NAME , (void *)itdev)) - goto failure; + goto failure2; ret =rc_register_device (rdev);if (ret) - goto failure; + goto failure3; itdev->rdev = rdev;ite_pr (KERN_NOTICE ,"driver has been successfully loaded\n" );return 0 ; +failure3: +free_irq (itdev->cir_irq, itdev); +failure2: +release_region (itdev->cir_addr, itdev->params.io_region_size); failure: -if (itdev->cir_irq) -free_irq (itdev->cir_irq, itdev); - -if (itdev->cir_addr) -release_region (itdev->cir_addr, itdev->params.io_region_size); -rc_free_device (rdev);kfree (itdev);drivers/media/rc/nuvoton-cir.c +12
-14@@ -1075,19 +1075,19 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)if (request_irq (nvt->cir_irq, nvt_cir_isr,IRQF_SHARED ,NVT_DRIVER_NAME , (void *)nvt)) - goto failure; + goto failure2;if (!request_region (nvt->cir_wake_addr,CIR_IOREG_LENGTH ,NVT_DRIVER_NAME )) - goto failure; + goto failure3;if (request_irq (nvt->cir_wake_irq, nvt_cir_wake_isr,IRQF_SHARED ,NVT_DRIVER_NAME , (void *)nvt)) - goto failure; + goto failure4; ret =rc_register_device (rdev);if (ret) - goto failure; + goto failure5;device_init_wakeup (&pdev->dev, true); nvt->rdev = rdev;@@ -1099,17 +1099,15 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)return 0 ; +failure5: +free_irq (nvt->cir_wake_irq, nvt); +failure4: +release_region (nvt->cir_wake_addr,CIR_IOREG_LENGTH ); +failure3: +free_irq (nvt->cir_irq, nvt); +failure2: +release_region (nvt->cir_addr,CIR_IOREG_LENGTH ); failure: -if (nvt->cir_irq) -free_irq (nvt->cir_irq, nvt); -if (nvt->cir_addr) -release_region (nvt->cir_addr,CIR_IOREG_LENGTH ); - -if (nvt->cir_wake_irq) -free_irq (nvt->cir_wake_irq, nvt); -if (nvt->cir_wake_addr) -release_region (nvt->cir_wake_addr,CIR_IOREG_LENGTH ); -rc_free_device (rdev);kfree (nvt);
Signature · 2 lines
Ben Hutchings The two most common things in the universe are hydrogen and stupidity.