Commit e2a39d1a authored by Zide Chen's avatar Zide Chen Committed by Peter Zijlstra
Browse files

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: b575fc0e ("perf/x86/intel/uncore: Add domain global init callback")
Reported-by: default avatarkernel test robot <lkp@intel.com>
Signed-off-by: default avatarZide Chen <zide.chen@intel.com>
Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: default avatarDapeng Mi <dapeng1.mi@linux.intel.com>
Link: https://patch.msgid.link/20260313174050.171704-2-zide.chen@intel.com
parent 591cd656
Loading
Loading
Loading
Loading
+10 −5
Original line number Diff line number Diff line
@@ -264,6 +264,7 @@ static int __parse_discovery_table(struct uncore_discovery_domain *domain,
	struct uncore_unit_discovery unit;
	void __iomem *io_addr;
	unsigned long size;
	int ret = 0;
	int i;

	size = UNCORE_DISCOVERY_GLOBAL_MAP_SIZE;
@@ -273,21 +274,23 @@ static int __parse_discovery_table(struct uncore_discovery_domain *domain,

	/* Read Global Discovery State */
	memcpy_fromio(&global, io_addr, sizeof(struct uncore_global_discovery));
	iounmap(io_addr);

	if (uncore_discovery_invalid_unit(global)) {
		pr_info("Invalid Global Discovery State: 0x%llx 0x%llx 0x%llx\n",
			global.table1, global.ctl, global.table3);
		iounmap(io_addr);
		return -EINVAL;
	}
	iounmap(io_addr);

	size = (1 + global.max_units) * global.stride * 8;
	io_addr = ioremap(addr, size);
	if (!io_addr)
		return -ENOMEM;

	if (domain->global_init && domain->global_init(global.ctl))
		return -ENODEV;
	if (domain->global_init && domain->global_init(global.ctl)) {
		ret = -ENODEV;
		goto out;
	}

	/* Parsing Unit Discovery State */
	for (i = 0; i < global.max_units; i++) {
@@ -307,8 +310,10 @@ static int __parse_discovery_table(struct uncore_discovery_domain *domain,
	}

	*parsed = true;

out:
	iounmap(io_addr);
	return 0;
	return ret;
}

static int parse_discovery_table(struct uncore_discovery_domain *domain,