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

PCI: tegra: Fix OF node reference leak

Each iteration of for_each_child_of_node() executes of_node_put() on the
previous node, but in some return paths in the middle of the loop
of_node_put() is missing thus causing a reference leak.

Hence stash these mid-loop return values in a variable 'err' and add a
new label err_node_put which executes of_node_put() on the previous node
and returns 'err' on failure.

Change mid-loop return statements to point to jump to this label to
fix the reference leak.

Issue found with Coccinelle.

Signed-off-by: Nishka Dasgupta <nishkadg.linux@gmail.com>
[lorenzo.pieralisi@arm.com: rewrote commit log]
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>

authored by

Nishka Dasgupta and committed by
Lorenzo Pieralisi
9e38e690 5f9e832c

+15 -7
+15 -7
drivers/pci/controller/pci-tegra.c
··· 2237 2237 err = of_pci_get_devfn(port); 2238 2238 if (err < 0) { 2239 2239 dev_err(dev, "failed to parse address: %d\n", err); 2240 - return err; 2240 + goto err_node_put; 2241 2241 } 2242 2242 2243 2243 index = PCI_SLOT(err); 2244 2244 2245 2245 if (index < 1 || index > soc->num_ports) { 2246 2246 dev_err(dev, "invalid port number: %d\n", index); 2247 - return -EINVAL; 2247 + err = -EINVAL; 2248 + goto err_node_put; 2248 2249 } 2249 2250 2250 2251 index--; ··· 2254 2253 if (err < 0) { 2255 2254 dev_err(dev, "failed to parse # of lanes: %d\n", 2256 2255 err); 2257 - return err; 2256 + goto err_node_put; 2258 2257 } 2259 2258 2260 2259 if (value > 16) { 2261 2260 dev_err(dev, "invalid # of lanes: %u\n", value); 2262 - return -EINVAL; 2261 + err = -EINVAL; 2262 + goto err_node_put; 2263 2263 } 2264 2264 2265 2265 lanes |= value << (index << 3); ··· 2274 2272 lane += value; 2275 2273 2276 2274 rp = devm_kzalloc(dev, sizeof(*rp), GFP_KERNEL); 2277 - if (!rp) 2278 - return -ENOMEM; 2275 + if (!rp) { 2276 + err = -ENOMEM; 2277 + goto err_node_put; 2278 + } 2279 2279 2280 2280 err = of_address_to_resource(port, 0, &rp->regs); 2281 2281 if (err < 0) { 2282 2282 dev_err(dev, "failed to parse address: %d\n", err); 2283 - return err; 2283 + goto err_node_put; 2284 2284 } 2285 2285 2286 2286 INIT_LIST_HEAD(&rp->list); ··· 2334 2330 return err; 2335 2331 2336 2332 return 0; 2333 + 2334 + err_node_put: 2335 + of_node_put(port); 2336 + return err; 2337 2337 } 2338 2338 2339 2339 /*