New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 639836 link

Starred by 1 user

Issue metadata

Status: WontFix
Owner:
Closed: Aug 2016
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: Linux , Windows , Chrome , Mac
Pri: 1
Type: Bug-Security



Sign in to add a comment

Security: PDFium: Integer Overflow in opj_pi_create_decode Function

Reported by stackexp...@gmail.com, Aug 22 2016

Issue description

VULNERABILITY DETAILS
This is a integer overflow issue in function opj_pi_create_decode. The source code of this function was listed as follows.

----------------------
Source Code Analysis
----------------------
opj_pi_iterator_t *opj_pi_create_decode(opj_image_t *p_image,
										opj_cp_t *p_cp,
										OPJ_UINT32 p_tile_no)
{
	/* loop */
	OPJ_UINT32 pino;
	OPJ_UINT32 compno, resno;

	/* to store w, h, dx and dy fro all components and resolutions */
	OPJ_UINT32 * l_tmp_data;
	OPJ_UINT32 ** l_tmp_ptr;

	/* encoding prameters to set */
	OPJ_UINT32 l_max_res;
	OPJ_UINT32 l_max_prec;
	OPJ_INT32 l_tx0,l_tx1,l_ty0,l_ty1;
	OPJ_UINT32 l_dx_min,l_dy_min;
	OPJ_UINT32 l_bound;
	OPJ_UINT32 l_step_p , l_step_c , l_step_r , l_step_l ;
	OPJ_UINT32 l_data_stride;

	/* pointers */
	opj_pi_iterator_t *l_pi = 00;
	opj_tcp_t *l_tcp = 00;
	const opj_tccp_t *l_tccp = 00;
	opj_pi_comp_t *l_current_comp = 00;
	opj_image_comp_t * l_img_comp = 00;
	opj_pi_iterator_t * l_current_pi = 00;
	OPJ_UINT32 * l_encoding_value_ptr = 00;

	/* preconditions in debug */
	assert(p_cp != 00);
	assert(p_image != 00);
	assert(p_tile_no < p_cp->tw * p_cp->th);

	/* initializations */
	l_tcp = &p_cp->tcps[p_tile_no];
	l_bound = l_tcp->numpocs+1;

	l_data_stride = 4 * OPJ_J2K_MAXRLVLS;
	l_tmp_data = (OPJ_UINT32*)opj_malloc(
		l_data_stride * p_image->numcomps * sizeof(OPJ_UINT32));
	if
		(! l_tmp_data)
	{
		return 00;
	}
	l_tmp_ptr = (OPJ_UINT32**)opj_malloc(
		p_image->numcomps * sizeof(OPJ_UINT32 *));
	if
		(! l_tmp_ptr)
	{
		opj_free(l_tmp_data);
		return 00;
	}

	/* memory allocation for pi */
	l_pi = opj_pi_create(p_image, p_cp, p_tile_no);
	if (!l_pi) {
		opj_free(l_tmp_data);
		opj_free(l_tmp_ptr);
		return 00;
	}

	l_encoding_value_ptr = l_tmp_data;
	/* update pointer array */
	for
		(compno = 0; compno < p_image->numcomps; ++compno)
	{
		l_tmp_ptr[compno] = l_encoding_value_ptr;
		l_encoding_value_ptr += l_data_stride;
	}
	/* get encoding parameters */
	opj_get_all_encoding_parameters(p_image,p_cp,p_tile_no,&l_tx0,&l_tx1,&l_ty0,&l_ty1,&l_dx_min,&l_dy_min,&l_max_prec,&l_max_res,l_tmp_ptr);

	/* step calculations */
	l_step_p = 1;
	l_step_c = l_max_prec * l_step_p;
	l_step_r = p_image->numcomps * l_step_c;
	l_step_l = l_max_res * l_step_r;

	/* set values for first packet iterator */
	l_current_pi = l_pi;

	/* memory allocation for include */
	l_current_pi->include = 00;
	if
		(l_step_l && l_tcp->numlayers < UINT_MAX / l_step_l - 1)
	{
		l_current_pi->include = (OPJ_INT16*)opj_calloc((l_tcp->numlayers + 1) * l_step_l, sizeof(OPJ_INT16));  // <---------------------------------- integer overflow
	}

	if
		(!l_current_pi->include)
	{
		opj_free(l_tmp_data);
		opj_free(l_tmp_ptr);
		opj_pi_destroy(l_pi, l_bound);
		return 00;
	}


----------------------
Vulnerability Analysis
----------------------
The overflow check was made before calling the opj_calloc function. I think the check logical was insufficient.
For example, we can make sure that l_tcp->numlayers < UINT_MAX / l_step_l - 1.
But (l_tcp->numlayers + 1) * l_step_l * sizeof(OPJ_INT16) still could overflow 0xFFFFFFFF.

The attached poc.pdf file could assign 0x100e0 to l_step_l and 0xFF19 to l_tcp->numlayers. Thus the total bytes required from the opj_calloc function was 0x100e0*(0xFF19+1)*2=0x1fffe7800. This could lead to integer overflow situation.

The code was reachable here. But I'm not able to produce OOB read or OOB write behaviors. However, I think this doesn't mean that it has not security impact.

 Issue 453553  was a similar one. In that issue, the integer overflow happened during the calculation of total bytes required.


----------------------
Suggest Patch
----------------------
// remember to divide sizeof(OPJ_INT16)

	if
		(l_step_l && l_tcp->numlayers < UINT_MAX / sizeof(OPJ_INT16) / l_step_l - 1)
	{
		l_current_pi->include = (OPJ_INT16*)opj_calloc((l_tcp->numlayers + 1) * l_step_l, sizeof(OPJ_INT16));
	}

VERSION
Chrome Version: [x.x.x.x] + [stable, beta, or dev]
Operating System: [Please indicate OS, version, and service pack level]

REPRODUCTION CASE
Please include a demonstration of the security bug, such as an attached
HTML or binary file that reproduces the bug when loaded in Chrome. PLEASE
make the file as small as possible and remove any content not required to
demonstrate the bug.

FOR CRASHES, PLEASE INCLUDE THE FOLLOWING ADDITIONAL INFORMATION
Type of crash: [tab, browser, etc.]
Crash State: [see link above: stack trace, registers, exception record]
Client ID (if relevant): [see link above]

 
poc.pdf
1.8 KB Download
Cc: thestig@chromium.org
Components: Internals>Plugins>PDF Infra>Client>Pdfium
+jam@, could you help triage this one since you're in the owner list? 
Cc: -thestig@chromium.org jialiul@chromium.org
Components: -Infra>Client>Pdfium
Labels: OS-Chrome OS-Linux OS-Mac OS-Windows Pri-1
Owner: och...@chromium.org
jialiu:
- Again, Infra>Client>Pdfium is the wrong component.
- There's no need to CC me explicitly. I already get all the Internals>Plugins>PDF bugs.
- Also, I'm not jam. :-P
Status: Assigned (was: Unconfirmed)
Sorry.... My bad. I meant to cc jam@, since he is in the owner list too (load balancing, don't want to bug you with too many issues), but end up with putting your email in.. Sincerely apologize, and thanks for triaging it. 
Labels: Security_Severity-Medium Security_Impact-Stable
Owner: dsinclair@chromium.org
Dan, can you please take a look.
I've uploaded a patch for this issue at https://codereview.chromium.org/2270353002/ .

The patch file was not uploaded and third_party\libopenjpeg20\README.pdfium was not updated since another patch for openjpeg was under reviewing.
Project Member

Comment 6 by sheriffbot@chromium.org, Aug 24 2016

Labels: M-53

Comment 7 by tsepez@chromium.org, Aug 24 2016

The multiplication of (l_tcp->numlayers + 1) * l_step_l by sizeof(OPJ_UINT16) is taking place inside the calloc(), which is responsible for detecting overflow and returning NULL (there were bugs with this half a dozen years ago, but we think platforms have fixed their libraries).  Which may be why you can't trigger it.


Hi tsepez, you're right. I found that the latest libc.so.6 file in Ubuntu 14.04 LTS can handle this condition. But I'm not sure whether the old versions of Linux can handle it or not.

Comment 9 by tsepez@chromium.org, Aug 25 2016

Status: WontFix (was: Assigned)
Based on the number of places in our codebase that rely on this property of calloc(), I think I'm going to "wontfix" this issue.
Project Member

Comment 10 by sheriffbot@chromium.org, Dec 2 2016

Labels: -Restrict-View-SecurityTeam allpublic
This bug has been closed for more than 14 weeks. Removing security view restrictions.

For more details visit https://www.chromium.org/issue-tracking/autotriage - Your friendly Sheriffbot

Sign in to add a comment