Bug 207911

Summary: kiconv reference count integer overflow
Product: Base System Reporter: CTurt <ecturt>
Component: kernAssignee: freebsd-bugs (Nobody) <bugs>
Status: New ---    
Severity: Affects Only Me CC: emaste, op, secteam, shawn.webb
Priority: ---    
Version: CURRENT   
Hardware: Any   
OS: Any   

Description CTurt 2016-03-11 19:20:05 UTC
The `kiconv` module doesn't perform checks on the reference count of its converter class before incrementing and decrementing it, sys/libkern/iconv.c:

static int
iconv_register_converter(struct iconv_converter_class *dcp)
{
	kobj_class_compile((struct kobj_class*)dcp);
	dcp->refs++;
	TAILQ_INSERT_TAIL(&iconv_converters, dcp, cc_link);
	return 0;
}

static int
iconv_unregister_converter(struct iconv_converter_class *dcp)
{
	dcp->refs--;
	if (dcp->refs > 1) {
		ICDEBUG("converter has %d references left\n", dcp->refs);
		return EBUSY;
	}
	TAILQ_REMOVE(&iconv_converters, dcp, cc_link);
	kobj_class_free((struct kobj_class*)dcp);
	return 0;
}

Since `refs` field is declared as `u_int`, if `iconv_register_converter` is called enough times it will overflow from `UINT_MAX` to `0` and then be incremented to `1`. Then when `iconv_unregister_converter` is called, the check against `dcp->refs` will be bypassed and its converter class will then be freed even though it still has references; leading to use after free behaviour.

This is mostly theoretical since it is unlikely to be possible to register this many converter classes without encountering other issues, such as running out of memory. In addition, the `iconv_register_converter` is only called on the `MOD_LOAD` event, which is root only, so is unlikely to present a security risk.