Page MenuHomeFreeBSD

iconv uses strlen directly on user supplied memory
ClosedPublic

Authored by dab on Feb 26 2018, 3:55 PM.
Tags
None
Referenced Files
Unknown Object (File)
Fri, Apr 26, 8:55 PM
Unknown Object (File)
Fri, Apr 26, 7:12 PM
Unknown Object (File)
Fri, Apr 26, 12:02 PM
Unknown Object (File)
Feb 7 2024, 8:09 AM
Unknown Object (File)
Nov 12 2023, 3:57 PM
Unknown Object (File)
Oct 19 2023, 2:52 AM
Unknown Object (File)
Aug 26 2023, 9:04 PM
Unknown Object (File)
Aug 7 2023, 10:27 PM

Details

Summary

This change comes from PR 207302, submitted by CTurt <cturt@hardenedbsd.org> of Hardened BSD. The writeup from the PR is included below:

iconv_sysctl_add from sys/libkern/iconv.c incorrectly limits the size of user strings, such that several out of bounds reads could have been possible.

static int
iconv_sysctl_add(SYSCTL_HANDLER_ARGS)
{
	struct iconv_converter_class *dcp;
	struct iconv_cspair *csp;
	struct iconv_add_in din;
	struct iconv_add_out dout;
	int error;

	error = SYSCTL_IN(req, &din, sizeof(din));
	if (error)
		return error;
	if (din.ia_version != ICONV_ADD_VER)
		return EINVAL;
	if (din.ia_datalen > ICONV_CSMAXDATALEN)
		return EINVAL;
	if (strlen(din.ia_from) >= ICONV_CSNMAXLEN)
		return EINVAL;
	if (strlen(din.ia_to) >= ICONV_CSNMAXLEN)
		return EINVAL;
	if (strlen(din.ia_converter) >= ICONV_CNVNMAXLEN)
		return EINVAL;
...

Since the din struct is directly copied from userland, there is no guarantee that the strings supplied will be NULL terminated. The strlen calls could continue reading past the designated buffer sizes.

Declaration of struct iconv_add_in is found in sys/sys/iconv.h:

struct iconv_add_in {
	int	ia_version;
	char	ia_converter[ICONV_CNVNMAXLEN];
	char	ia_to[ICONV_CSNMAXLEN];
	char	ia_from[ICONV_CSNMAXLEN];
	int	ia_datalen;
	const void *ia_data;
};

Our strings are followed by the ia_datalen member, which is checked before the strlen calls:

if (din.ia_datalen > ICONV_CSMAXDATALEN)

Since ICONV_CSMAXDATALEN has value 0x41000 (and is unsigned), this ensures that din.ia_datalen contains at least 1 byte of 0, so it is not possible to trigger a read out of bounds of the struct however, this code is fragile and could introduce subtle bugs in the future if the struct is ever modified.

Diff Detail

Repository
rS FreeBSD src repository - subversion
Lint
Lint Not Applicable
Unit
Tests Not Applicable