Two problems on the dpll error paths in ptp_ocp_probe(). dpll_device_register() takes a second reference and stores bp as the registration private data, and only dpll_device_unregister() drops it. out_dpll dropped bp->tracker but never unregistered, so a dpll_pin_get() or dpll_pin_register() failure left the device registered and visible to userspace with a priv pointer into the storage devlink_free() releases a few lines later, as well as leaking the registration object. A failing dpll_device_register() jumped to the same label as the failing dpll_device_get(), so the reference taken by dpll_device_get() was never dropped either. Give that case its own label. Fixes: 09eeb3aecc6c ("ptp_ocp: implement DPLL ops") Signed-off-by: Sagi Maimon --- drivers/ptp/ptp_ocp.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c index 401b04f12d2b..f4299878c27c 100644 --- a/drivers/ptp/ptp_ocp.c +++ b/drivers/ptp/ptp_ocp.c @@ -5124,7 +5124,7 @@ ptp_ocp_probe(struct pci_dev *pdev, const struct pci_device_id *id) err = dpll_device_register(bp->dpll, DPLL_TYPE_PPS, &dpll_ops, bp); if (err) - goto out_devlink; + goto out_dpll_put; for (i = 0; i < OCP_SMA_NUM; i++) { bp->sma[i].dpll_pin = dpll_pin_get(clkid, i, THIS_MODULE, @@ -5150,6 +5150,12 @@ ptp_ocp_probe(struct pci_dev *pdev, const struct pci_device_id *id) dpll_pin_unregister(bp->dpll, bp->sma[i].dpll_pin, &dpll_pins_ops, &bp->sma[i]); dpll_pin_put(bp->sma[i].dpll_pin, &bp->sma[i].tracker); } + /* dpll_device_register() takes a second reference and stores bp; only + * dpll_device_unregister() drops it. Without this the device stays + * visible with a priv pointer into storage devlink_free() will release. + */ + dpll_device_unregister(bp->dpll, &dpll_ops, bp); +out_dpll_put: dpll_device_put(bp->dpll, &bp->tracker); out_devlink: devlink_unregister(devlink); -- 2.47.0