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

Configure Feed

Select the types of activity you want to include in your feed.

perf/x86/intel/uncore: Fix iounmap() leak on global_init failure

Kernel test robot reported:

Unverified Error/Warning (likely false positive, kindly check if
interested):
arch/x86/events/intel/uncore_discovery.c:293:2-8:
ERROR: missing iounmap; ioremap on line 288 and execution via
conditional on line 292

If domain->global_init() fails in __parse_discovery_table(), the
ioremap'ed MMIO region is not released before returning, resulting
in an MMIO mapping leak.

Fixes: b575fc0e3357 ("perf/x86/intel/uncore: Add domain global init callback")
Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Zide Chen <zide.chen@intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Dapeng Mi <dapeng1.mi@linux.intel.com>
Link: https://patch.msgid.link/20260313174050.171704-2-zide.chen@intel.com

authored by

Zide Chen and committed by
Peter Zijlstra
e2a39d1a 591cd656

+10 -5
+10 -5
arch/x86/events/intel/uncore_discovery.c
··· 264 264 struct uncore_unit_discovery unit; 265 265 void __iomem *io_addr; 266 266 unsigned long size; 267 + int ret = 0; 267 268 int i; 268 269 269 270 size = UNCORE_DISCOVERY_GLOBAL_MAP_SIZE; ··· 274 273 275 274 /* Read Global Discovery State */ 276 275 memcpy_fromio(&global, io_addr, sizeof(struct uncore_global_discovery)); 276 + iounmap(io_addr); 277 + 277 278 if (uncore_discovery_invalid_unit(global)) { 278 279 pr_info("Invalid Global Discovery State: 0x%llx 0x%llx 0x%llx\n", 279 280 global.table1, global.ctl, global.table3); 280 - iounmap(io_addr); 281 281 return -EINVAL; 282 282 } 283 - iounmap(io_addr); 284 283 285 284 size = (1 + global.max_units) * global.stride * 8; 286 285 io_addr = ioremap(addr, size); 287 286 if (!io_addr) 288 287 return -ENOMEM; 289 288 290 - if (domain->global_init && domain->global_init(global.ctl)) 291 - return -ENODEV; 289 + if (domain->global_init && domain->global_init(global.ctl)) { 290 + ret = -ENODEV; 291 + goto out; 292 + } 292 293 293 294 /* Parsing Unit Discovery State */ 294 295 for (i = 0; i < global.max_units; i++) { ··· 310 307 } 311 308 312 309 *parsed = true; 310 + 311 + out: 313 312 iounmap(io_addr); 314 - return 0; 313 + return ret; 315 314 } 316 315 317 316 static int parse_discovery_table(struct uncore_discovery_domain *domain,