x86/speculation: Protect against userspace-userspace spectreRSB

The article "Spectre Returns! Speculation Attacks using the Return Stack
Buffer" [1] describes two new (sub-)variants of spectrev2-like attacks,
making use solely of the RSB contents even on CPUs that don't fallback to
BTB on RSB underflow (Skylake+).

Mitigate userspace-userspace attacks by always unconditionally filling RSB on
context switch when the generic spectrev2 mitigation has been enabled.

[1] https://arxiv.org/pdf/1807.07940.pdf

Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Josh Poimboeuf <jpoimboe@redhat.com>
Acked-by: Tim Chen <tim.c.chen@linux.intel.com>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: David Woodhouse <dwmw@amazon.co.uk>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: stable@vger.kernel.org
Link: https://lkml.kernel.org/r/nycvar.YFH.7.76.1807261308190.997@cbobk.fhfr.pm

@@ -313,23 +313,6 @@ static enum spectre_v2_mitigation_cmd __init spectre_v2_parse_cmdline(void)
 	return cmd;
 }

-/* Check for Skylake-like CPUs (for RSB handling) */
-static bool __init is_skylake_era(void)
-{
-	if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
-	    boot_cpu_data.x86 == 6) {
-		switch (boot_cpu_data.x86_model) {
-		case INTEL_FAM6_SKYLAKE_MOBILE:
-		case INTEL_FAM6_SKYLAKE_DESKTOP:
-		case INTEL_FAM6_SKYLAKE_X:
-		case INTEL_FAM6_KABYLAKE_MOBILE:
-		case INTEL_FAM6_KABYLAKE_DESKTOP:
-			return true;
-		}
-	}
-	return false;
-}
-
 static void __init spectre_v2_select_mitigation(void)
 {
 	enum spectre_v2_mitigation_cmd cmd = spectre_v2_parse_cmdline();
@@ -390,22 +373,15 @@ static void __init spectre_v2_select_mitigation(void)
 	pr_info("%s\n", spectre_v2_strings[mode]);

 	/*
-	 * If neither SMEP nor PTI are available, there is a risk of
-	 * hitting userspace addresses in the RSB after a context switch
-	 * from a shallow call stack to a deeper one. To prevent this fill
-	 * the entire RSB, even when using IBRS.
+	 * If spectre v2 protection has been enabled, unconditionally fill
+	 * RSB during a context switch; this protects against two independent
+	 * issues:
 	 *
-	 * Skylake era CPUs have a separate issue with *underflow* of the
-	 * RSB, when they will predict 'ret' targets from the generic BTB.
-	 * The proper mitigation for this is IBRS. If IBRS is not supported
-	 * or deactivated in favour of retpolines the RSB fill on context
-	 * switch is required.
+	 *	- RSB underflow (and switch to BTB) on Skylake+
+	 *	- SpectreRSB variant of spectre v2 on X86_BUG_SPECTRE_V2 CPUs
 	 */
-	if ((!boot_cpu_has(X86_FEATURE_PTI) &&
-	     !boot_cpu_has(X86_FEATURE_SMEP)) || is_skylake_era()) {
-		setup_force_cpu_cap(X86_FEATURE_RSB_CTXSW);
-		pr_info("Spectre v2 mitigation: Filling RSB on context switch\n");
-	}
+	setup_force_cpu_cap(X86_FEATURE_RSB_CTXSW);
+	pr_info("Spectre v2 / SpectreRSB mitigation: Filling RSB on context switch\n");

 	/* Initialize Indirect Branch Prediction Barrier if supported */
 	if (boot_cpu_has(X86_FEATURE_IBPB)) {


These changes repair bugs of #871 and #872

@@ -553,20 +553,18 @@ static void tif_32sto16u(const OPJ_INT32* pSrc, OPJ_UINT16* pDst, OPJ_SIZE_T len

 int imagetotif(opj_image_t * image, const char *outfile)
 {
-	int width, height;
-	int bps,adjust, sgnd;
-	int tiPhoto;
+	uint32 width, height, bps, tiPhoto;
+	int adjust, sgnd;
 	TIFF *tif;
 	tdata_t buf;
-	tsize_t strip_size;
+	tmsize_t strip_size, rowStride;
 	OPJ_UINT32 i, numcomps;
-	OPJ_SIZE_T rowStride;
 	OPJ_INT32* buffer32s = NULL;
 	OPJ_INT32 const* planes[4];
 	convert_32s_PXCX cvtPxToCx = NULL;
 	convert_32sXXx_C1R cvt32sToTif = NULL;

-	bps = (int)image->comps[0].prec;
+	bps = (uint32)image->comps[0].prec;
 	planes[0] = image->comps[0].data;

 	numcomps = image->numcomps;
@@ -674,22 +672,22 @@ int imagetotif(opj_image_t * image, const char *outfile)
 			break;
 	}
 	sgnd = (int)image->comps[0].sgnd;
-	adjust = sgnd ? 1 << (image->comps[0].prec - 1) : 0;
-	width   = (int)image->comps[0].w;
-	height  = (int)image->comps[0].h;
+	adjust = sgnd ? (int)(1 << (image->comps[0].prec - 1)) : 0;
+	width   = (uint32)image->comps[0].w;
+	height  = (uint32)image->comps[0].h;

 	TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, width);
 	TIFFSetField(tif, TIFFTAG_IMAGELENGTH, height);
-	TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, numcomps);
+	TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, (uint32)numcomps);
 	TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bps);
 	TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
 	TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
 	TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, tiPhoto);
 	TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, 1);

 	strip_size = TIFFStripSize(tif);
-	rowStride = ((OPJ_SIZE_T)width * numcomps * (OPJ_SIZE_T)bps + 7U) / 8U;
-	if (rowStride != (OPJ_SIZE_T)strip_size) {
+	rowStride = (width * numcomps * bps + 7U) / 8U;
+	if (rowStride != strip_size) {
 		fprintf(stderr, "Invalid TIFF strip size\n");
 		TIFFClose(tif);
 		return 1;
@@ -699,7 +697,7 @@ int imagetotif(opj_image_t * image, const char *outfile)
 		TIFFClose(tif);
 		return 1;
 	}
-	buffer32s = (OPJ_INT32 *)malloc((OPJ_SIZE_T)width * numcomps * sizeof(OPJ_INT32));
+	buffer32s = (OPJ_INT32 *)malloc((OPJ_SIZE_T)(width * numcomps * sizeof(OPJ_INT32)));
 	if (buffer32s == NULL) {
 		_TIFFfree(buf);
 		TIFFClose(tif);
@@ -1211,20 +1209,19 @@ opj_image_t* tiftoimage(const char *filename, opj_cparameters_t *parameters)
 	TIFF *tif;
 	tdata_t buf;
 	tstrip_t strip;
-	tsize_t strip_size;
+	tmsize_t strip_size;
 	int j, currentPlane, numcomps = 0, w, h;
 	OPJ_COLOR_SPACE color_space = OPJ_CLRSPC_UNKNOWN;
 	opj_image_cmptparm_t cmptparm[4]; /* RGBA */
 	opj_image_t *image = NULL;
 	int has_alpha = 0;
-	unsigned short tiBps, tiPhoto, tiSf, tiSpp, tiPC;
-	unsigned int tiWidth, tiHeight;
+	uint32 tiBps, tiPhoto, tiSf, tiSpp, tiPC, tiWidth, tiHeight;
 	OPJ_BOOL is_cinema = OPJ_IS_CINEMA(parameters->rsiz);
 	convert_XXx32s_C1R cvtTifTo32s = NULL;
 	convert_32s_CXPX cvtCxToPx = NULL;
 	OPJ_INT32* buffer32s = NULL;
 	OPJ_INT32* planes[4];
-	OPJ_SIZE_T rowStride;
+	tmsize_t rowStride;

 	tif = TIFFOpen(filename, "r");

@@ -1243,22 +1240,35 @@ opj_image_t* tiftoimage(const char *filename, opj_cparameters_t *parameters)
 	TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &tiSpp);
 	TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &tiPhoto);
 	TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &tiPC);
-	w= (int)tiWidth;
-	h= (int)tiHeight;
-
-	if(tiBps > 16U) {
-		fprintf(stderr,"tiftoimage: Bits=%d, Only 1 to 16 bits implemented\n",tiBps);
-		fprintf(stderr,"\tAborting\n");
+
+	if(tiSpp == 0 || tiSpp > 4) { /* should be 1 ... 4 */
+		fprintf(stderr,"tiftoimage: Bad value for samples per pixel == %hu.\n"
+		 "\tAborting.\n", tiSpp);
+		TIFFClose(tif);
+		return NULL;
+	}
+	if(tiBps > 16U || tiBps == 0) {
+		fprintf(stderr,"tiftoimage: Bad values for Bits == %d.\n"
+		 "\tMax. 16 Bits are allowed here.\n\tAborting.\n",tiBps);
 		TIFFClose(tif);
 		return NULL;
 	}
 	if(tiPhoto != PHOTOMETRIC_MINISBLACK && tiPhoto != PHOTOMETRIC_RGB) {
-		fprintf(stderr,"tiftoimage: Bad color format %d.\n\tOnly RGB(A) and GRAY(A) has been implemented\n",(int) tiPhoto);
+		fprintf(stderr,"tiftoimage: Bad color format %d.\n"
+		 "\tOnly RGB(A) and GRAY(A) has been implemented\n",(int) tiPhoto);
 		fprintf(stderr,"\tAborting\n");
 		TIFFClose(tif);
 		return NULL;
 	}
-
+	if(tiWidth == 0 || tiHeight == 0) {
+		fprintf(stderr,"tiftoimage: Bad values for width(%u) "
+		 "and/or height(%u)\n\tAborting.\n",tiWidth,tiHeight);
+		TIFFClose(tif);
+		return NULL;
+	}
+	w= (int)tiWidth;
+	h= (int)tiHeight;
+
 	switch (tiBps) {
 		case 1:
 		case 2:
@@ -1312,7 +1322,7 @@ opj_image_t* tiftoimage(const char *filename, opj_cparameters_t *parameters)

 		TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES,
 													&extrasamples, &sampleinfo);
-
+
 		if(extrasamples >= 1)
 		{
 			switch(sampleinfo[0])
@@ -1333,7 +1343,7 @@ opj_image_t* tiftoimage(const char *filename, opj_cparameters_t *parameters)
 		else /* extrasamples == 0 */
 			if(tiSpp == 4 || tiSpp == 2) has_alpha = 1;
 	}
-
+
 	/* initialize image components */
 	memset(&cmptparm[0], 0, 4 * sizeof(opj_image_cmptparm_t));

@@ -1346,7 +1356,7 @@ opj_image_t* tiftoimage(const char *filename, opj_cparameters_t *parameters)
 	} else {
 		is_cinema = 0U;
 	}
-
+
 	if(tiPhoto == PHOTOMETRIC_RGB) /* RGB(A) */
 	{
 		numcomps = 3 + has_alpha;
@@ -1384,26 +1394,40 @@ opj_image_t* tiftoimage(const char *filename, opj_cparameters_t *parameters)
 	image->x0 = (OPJ_UINT32)parameters->image_offset_x0;
 	image->y0 = (OPJ_UINT32)parameters->image_offset_y0;
 	image->x1 =	!image->x0 ? (OPJ_UINT32)(w - 1) * (OPJ_UINT32)subsampling_dx + 1 :
-	image->x0 + (OPJ_UINT32)(w - 1) * (OPJ_UINT32)subsampling_dx + 1;
+	 image->x0 + (OPJ_UINT32)(w - 1) * (OPJ_UINT32)subsampling_dx + 1;
+	if(image->x1 <= image->x0) {
+		fprintf(stderr,"tiftoimage: Bad value for image->x1(%d) vs. "
+		 "image->x0(%d)\n\tAborting.\n",image->x1,image->x0);
+		TIFFClose(tif);
+		opj_image_destroy(image);
+		return NULL;
+	}
 	image->y1 =	!image->y0 ? (OPJ_UINT32)(h - 1) * (OPJ_UINT32)subsampling_dy + 1 :
-	image->y0 + (OPJ_UINT32)(h - 1) * (OPJ_UINT32)subsampling_dy + 1;
-
+	 image->y0 + (OPJ_UINT32)(h - 1) * (OPJ_UINT32)subsampling_dy + 1;
+	if(image->y1 <= image->y0) {
+		fprintf(stderr,"tiftoimage: Bad value for image->y1(%d) vs. "
+		 "image->y0(%d)\n\tAborting.\n",image->y1,image->y0);
+		TIFFClose(tif);
+		opj_image_destroy(image);
+		return NULL;
+	}
+
 	for(j = 0; j < numcomps; j++)
 	{
 		planes[j] = image->comps[j].data;
 	}
 	image->comps[numcomps - 1].alpha = (OPJ_UINT16)(1 - (numcomps & 1));

 	strip_size = TIFFStripSize(tif);
-
+
 	buf = _TIFFmalloc(strip_size);
 	if (buf == NULL) {
 		TIFFClose(tif);
 		opj_image_destroy(image);
 		return NULL;
 	}
-	rowStride = ((OPJ_SIZE_T)w * tiSpp * tiBps + 7U) / 8U;
-	buffer32s = (OPJ_INT32 *)malloc((OPJ_SIZE_T)w * tiSpp * sizeof(OPJ_INT32));
+	rowStride = (w * tiSpp * tiBps + 7U) / 8U;
+	buffer32s = (OPJ_INT32 *)malloc((OPJ_SIZE_T)(w * tiSpp * sizeof(OPJ_INT32)));
 	if (buffer32s == NULL) {
 		_TIFFfree(buf);
 		TIFFClose(tif);
@@ -1421,11 +1445,20 @@ opj_image_t* tiftoimage(const char *filename, opj_cparameters_t *parameters)
 		for(; (h > 0) && (strip < TIFFNumberOfStrips(tif)); strip++)
 		{
 				const OPJ_UINT8 *dat8;
-				OPJ_SIZE_T ssize;
+				tmsize_t ssize;

-				ssize = (OPJ_SIZE_T)TIFFReadEncodedStrip(tif, strip, buf, strip_size);
+				ssize = TIFFReadEncodedStrip(tif, strip, buf, strip_size);
+				if(ssize < 1 || ssize > strip_size) {
+					fprintf(stderr,"tiftoimage: Bad value for ssize(%ld) "
+                     "vs. strip_size(%ld).\n\tAborting.\n",ssize,strip_size);
+					_TIFFfree(buf);
+					_TIFFfree(buffer32s);
+					TIFFClose(tif);
+					opj_image_destroy(image);
+					return NULL;
+				}
 				dat8 = (const OPJ_UINT8*)buf;
-
+
 				while (ssize >= rowStride) {
 					cvtTifTo32s(dat8, buffer32s, (OPJ_SIZE_T)w * tiSpp);
 					cvtCxToPx(buffer32s, planes, (OPJ_SIZE_T)w);


Fix a buffer overflow

Fixes #635

Thanks to HongxuChen for reporting it

@@ -354,7 +354,9 @@ matchCurrentInput(
 		const InString *input, int pos, const widechar *passInstructions, int passIC) {
 	int k;
 	int kk = pos;
-	for (k = passIC + 2; k < passIC + 2 + passInstructions[passIC + 1]; k++)
+	for (k = passIC + 2;
+			((k < passIC + 2 + passInstructions[passIC + 1]) && (kk < input->length));
+			k++)
 		if (input->chars[kk] == ENDSEGMENT || passInstructions[k] != input->chars[kk++])
 			return 0;
 	return 1;


Fix for bug #76582

The brigade seems to end up in a messed up state if something fails
in shutdown, so we clean it up.

@@ -678,6 +678,7 @@ zend_first_try {
 	if (!parent_req) {
 		php_apache_request_dtor(r TSRMLS_CC);
 		ctx->request_processed = 1;
+		apr_brigade_cleanup(brigade);
 		bucket = apr_bucket_eos_create(r->connection->bucket_alloc);
 		APR_BRIGADE_INSERT_TAIL(brigade, bucket);


@@ -1472,7 +1472,8 @@ static Image *ReadPICTImage(const ImageInfo *image_info,
               c=ReadBlobByte(image);
               if (c == EOF)
                 break;
-              (void) fputc(c,file);
+              if (fputc(c,file) != c)
+                break;
             }
           }
         (void) fclose(file);


fixed out of bounds writes

Thanks to Eric Sesterhenn from X41 D-SEC GmbH
for reporting the problems.

@@ -79,7 +79,7 @@ sc_pkcs15emu_esteid_init (sc_pkcs15_card_t * p15card)
 	/* read the serial (document number) */
 	r = sc_read_record (card, SC_ESTEID_PD_DOCUMENT_NR, buff, sizeof(buff), SC_RECORD_BY_REC_NR);
 	SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "read document number failed");
-	buff[r] = '\0';
+	buff[MIN((size_t) r, (sizeof buff)-1)] = '\0';
 	set_string (&p15card->tokeninfo->serial_number, (const char *) buff);

 	p15card->tokeninfo->flags = SC_PKCS15_TOKEN_PRN_GENERATION


@@ -408,7 +408,7 @@ static int tcos_select_file(sc_card_t *card,
 	file->path = *in_path;

 	for(i=2; i+1<apdu.resplen && i+1+apdu.resp[i+1]<apdu.resplen; i+=2+apdu.resp[i+1]){
-		int j, len=apdu.resp[i+1];
+		size_t j, len=apdu.resp[i+1];
 		unsigned char type=apdu.resp[i], *d=apdu.resp+i+2;

 		switch (type) {
@@ -432,8 +432,8 @@ static int tcos_select_file(sc_card_t *card,
 			file->id = (d[0]<<8) | d[1];
 			break;
 		case 0x84:
-			memcpy(file->name, d, len);
-			file->namelen = len;
+			file->namelen = MIN(sizeof file->name, len);
+			memcpy(file->name, d, file->namelen);
 			break;
 		case 0x86:
 			sc_file_set_sec_attr(file, d, len);


@@ -518,7 +518,9 @@ static int muscle_list_files(sc_card_t *card, u8 *buf, size_t bufLen)
 	mscfs_check_cache(priv->fs);

 	for(x = 0; x < fs->cache.size; x++) {
-		u8* oid= fs->cache.array[x].objectId.id;
+		u8* oid = fs->cache.array[x].objectId.id;
+		if (bufLen < 2)
+			break;
 		sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
 			"FILE: %02X%02X%02X%02X\n",
 			oid[0],oid[1],oid[2],oid[3]);
@@ -527,7 +529,8 @@ static int muscle_list_files(sc_card_t *card, u8 *buf, size_t bufLen)
 			buf[1] = oid[3];
 			if(buf[0] == 0x00 && buf[1] == 0x00) continue; /* No directories/null names outside of root */
 			buf += 2;
-			count+=2;
+			count += 2;
+			bufLen -= 2;
 		}
 	}
 	return count;


@@ -951,7 +951,7 @@ decrypt_response(struct sc_card *card, unsigned char *in, size_t inlen, unsigned
 	while (0x80 != plaintext[cipher_len - 2] && (cipher_len - 2 > 0))
 		cipher_len--;

-	if (2 == cipher_len)
+	if (2 == cipher_len || *out_len < cipher_len - 2)
 		return -1;

 	memcpy(out, plaintext, cipher_len - 2);
@@ -977,6 +977,7 @@ epass2003_sm_unwrap_apdu(struct sc_card *card, struct sc_apdu *sm, struct sc_apd
 	r = sc_check_sw(card, sm->sw1, sm->sw2);
 	if (r == SC_SUCCESS) {
 		if (exdata->sm) {
+			len = plain->resplen;
 			if (0 != decrypt_response(card, sm->resp, sm->resplen, plain->resp, &len))
 				return SC_ERROR_CARD_CMD_FAILED;
 		}


@@ -794,7 +794,7 @@ static int cac_get_serial_nr_from_CUID(sc_card_t* card, sc_serial_number_t* seri
         }
 	if (priv->cac_id_len) {
 		serial->len = MIN(priv->cac_id_len, SC_MAX_SERIALNR);
-		memcpy(serial->value, priv->cac_id, priv->cac_id_len);
+		memcpy(serial->value, priv->cac_id, serial->len);
 		SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_SUCCESS);
 	}
 	SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_FILE_NOT_FOUND);


@@ -339,10 +339,11 @@ const char * util_acl_to_str(const sc_acl_entry_t *e)
 			strcpy(buf, "????");
 			break;
 		}
-		strcat(line, buf);
-		strcat(line, " ");
+		strncat(line, buf, sizeof line);
+		strncat(line, " ", sizeof line);
 		e = e->next;
 	}
+	line[(sizeof line)-1] = '\0'; /* make sure it's NUL terminated */
 	line[strlen(line)-1] = 0; /* get rid of trailing space */
 	return line;
 }


@@ -149,7 +149,7 @@ int read_file(struct sc_card *card, char *str_path, unsigned char **data, size_t
 		goto err;
 	}

-	len = file ? file->size : 4096;
+	len = file && file->size > 0 ? file->size : 4096;
 	p = realloc(*data, len);
 	if (!p) {
 		goto err;


@@ -21,6 +21,7 @@
 #include "config.h"

 #include "libopensc/sc-ossl-compat.h"
+#include "libopensc/internal.h"
 #include <openssl/bn.h>
 #include <openssl/rsa.h>
 #include <openssl/x509.h>
@@ -331,7 +332,7 @@ static int read_public_key(RSA *rsa)
 		fprintf(stderr, "Unable to select public key file: %s\n", sc_strerror(r));
 		return 2;
 	}
-	bufsize = file->size;
+	bufsize = MIN(file->size, sizeof buf);
 	sc_file_free(file);
 	r = sc_read_binary(card, 0, buf, bufsize, 0);
 	if (r < 0) {
@@ -382,7 +383,7 @@ static int read_private_key(RSA *rsa)
 	e = sc_file_get_acl_entry(file, SC_AC_OP_READ);
 	if (e == NULL || e->method == SC_AC_NEVER)
 		return 10;
-	bufsize = file->size;
+	bufsize = MIN(file->size, sizeof buf);
 	sc_file_free(file);
 	r = sc_read_binary(card, 0, buf, bufsize, 0);
 	if (r < 0) {


@@ -628,7 +628,7 @@ int sc_file_set_sec_attr(sc_file_t *file, const u8 *sec_attr,
 		return SC_ERROR_INVALID_ARGUMENTS;
 	}

-	if (sec_attr == NULL) {
+	if (sec_attr == NULL || sec_attr_len) {
 		if (file->sec_attr != NULL)
 			free(file->sec_attr);
 		file->sec_attr = NULL;


voutf: fix bad arethmetic when outputting warnings to stderr

CVE-2018-16842
Reported-by: Brian Carpenter
Bug: https://curl.haxx.se/docs/CVE-2018-16842.html

@@ -67,7 +67,7 @@ static void voutf(struct GlobalConfig *config,
         (void)fwrite(ptr, cut + 1, 1, config->errors);
         fputs("\n", config->errors);
         ptr += cut + 1; /* skip the space too */
-        len -= cut;
+        len -= cut + 1;
       }
       else {
         fputs(ptr, config->errors);


Fixed CVE-2018-8788

Thanks to Eyal Itkin from Check Point Software Technologies.

@@ -51,6 +51,7 @@ static BOOL nsc_context_initialize_encode(NSC_CONTEXT* context)
 		for (i = 0; i < 5; i++)
 		{
 			BYTE* tmp = (BYTE*) realloc(context->priv->PlaneBuffers[i], length);
+
 			if (!tmp)
 				goto fail;

@@ -87,7 +88,7 @@ static BOOL nsc_context_initialize_encode(NSC_CONTEXT* context)
 	return FALSE;
 }

-static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, const BYTE* data,
+static BOOL nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, const BYTE* data,
                                       UINT32 scanline)
 {
 	UINT16 x;
@@ -104,10 +105,20 @@ static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, const BYTE* data,
 	INT16 b_val;
 	BYTE a_val;
 	UINT32 tempWidth;
+
+	if (!context || data || (scanline == 0))
+		return FALSE;
+
 	tempWidth = ROUND_UP_TO(context->width, 8);
 	rw = (context->ChromaSubsamplingLevel ? tempWidth : context->width);
 	ccl = context->ColorLossLevel;

+	if (context->priv->PlaneBuffersLength < rw * scanline)
+		return FALSE;
+
+	if (rw < scanline * 2)
+		return FALSE;
+
 	for (y = 0; y < context->height; y++)
 	{
 		src = data + (context->height - 1 - y) * scanline;
@@ -242,31 +253,37 @@ static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, const BYTE* data,
 		CopyMemory(coplane, coplane - rw, rw);
 		CopyMemory(cgplane, cgplane - rw, rw);
 	}
+
+	return TRUE;
 }

-static void nsc_encode_subsampling(NSC_CONTEXT* context)
+static BOOL nsc_encode_subsampling(NSC_CONTEXT* context)
 {
 	UINT16 x;
 	UINT16 y;
-	BYTE* co_dst;
-	BYTE* cg_dst;
-	INT8* co_src0;
-	INT8* co_src1;
-	INT8* cg_src0;
-	INT8* cg_src1;
 	UINT32 tempWidth;
 	UINT32 tempHeight;
+
+	if (!context)
+		return FALSE;
+
 	tempWidth = ROUND_UP_TO(context->width, 8);
 	tempHeight = ROUND_UP_TO(context->height, 2);

+	if (tempHeight == 0)
+		return FALSE;
+
+	if (tempWidth > context->priv->PlaneBuffersLength / tempHeight)
+		return FALSE;
+
 	for (y = 0; y < tempHeight >> 1; y++)
 	{
-		co_dst = context->priv->PlaneBuffers[1] + y * (tempWidth >> 1);
-		cg_dst = context->priv->PlaneBuffers[2] + y * (tempWidth >> 1);
-		co_src0 = (INT8*) context->priv->PlaneBuffers[1] + (y << 1) * tempWidth;
-		co_src1 = co_src0 + tempWidth;
-		cg_src0 = (INT8*) context->priv->PlaneBuffers[2] + (y << 1) * tempWidth;
-		cg_src1 = cg_src0 + tempWidth;
+		BYTE* co_dst = context->priv->PlaneBuffers[1] + y * (tempWidth >> 1);
+		BYTE* cg_dst = context->priv->PlaneBuffers[2] + y * (tempWidth >> 1);
+		const INT8* co_src0 = (INT8*) context->priv->PlaneBuffers[1] + (y << 1) * tempWidth;
+		const INT8* co_src1 = co_src0 + tempWidth;
+		const INT8* cg_src0 = (INT8*) context->priv->PlaneBuffers[2] + (y << 1) * tempWidth;
+		const INT8* cg_src1 = cg_src0 + tempWidth;

 		for (x = 0; x < tempWidth >> 1; x++)
 		{
@@ -280,19 +297,28 @@ static void nsc_encode_subsampling(NSC_CONTEXT* context)
 			cg_src1 += 2;
 		}
 	}
+
+	return TRUE;
 }

-void nsc_encode(NSC_CONTEXT* context, const BYTE* bmpdata, UINT32 rowstride)
+BOOL nsc_encode(NSC_CONTEXT* context, const BYTE* bmpdata, UINT32 rowstride)
 {
-	nsc_encode_argb_to_aycocg(context, bmpdata, rowstride);
+	if (!context || !bmpdata || (rowstride == 0))
+		return FALSE;
+
+	if (!nsc_encode_argb_to_aycocg(context, bmpdata, rowstride))
+		return FALSE;

 	if (context->ChromaSubsamplingLevel)
 	{
-		nsc_encode_subsampling(context);
+		if (!nsc_encode_subsampling(context))
+			return FALSE;
 	}
+
+	return TRUE;
 }

-static UINT32 nsc_rle_encode(BYTE* in, BYTE* out, UINT32 originalSize)
+static UINT32 nsc_rle_encode(const BYTE* in, BYTE* out, UINT32 originalSize)
 {
 	UINT32 left;
 	UINT32 runlength = 1;


bpf: 32-bit RSH verification must truncate input before the ALU op

When I wrote commit 468f6eafa6c4 ("bpf: fix 32-bit ALU op verification"), I
assumed that, in order to emulate 64-bit arithmetic with 32-bit logic, it
is sufficient to just truncate the output to 32 bits; and so I just moved
the register size coercion that used to be at the start of the function to
the end of the function.

That assumption is true for almost every op, but not for 32-bit right
shifts, because those can propagate information towards the least
significant bit. Fix it by always truncating inputs for 32-bit ops to 32
bits.

Also get rid of the coerce_reg_to_size() after the ALU op, since that has
no effect.

Fixes: 468f6eafa6c4 ("bpf: fix 32-bit ALU op verification")
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
Signed-off-by: Jann Horn <jannh@google.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>

@@ -2896,6 +2896,15 @@ static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env,
 	u64 umin_val, umax_val;
 	u64 insn_bitness = (BPF_CLASS(insn->code) == BPF_ALU64) ? 64 : 32;

+	if (insn_bitness == 32) {
+		/* Relevant for 32-bit RSH: Information can propagate towards
+		 * LSB, so it isn't sufficient to only truncate the output to
+		 * 32 bits.
+		 */
+		coerce_reg_to_size(dst_reg, 4);
+		coerce_reg_to_size(&src_reg, 4);
+	}
+
 	smin_val = src_reg.smin_value;
 	smax_val = src_reg.smax_value;
 	umin_val = src_reg.umin_value;
@@ -3131,7 +3140,6 @@ static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env,
 	if (BPF_CLASS(insn->code) != BPF_ALU64) {
 		/* 32-bit ALU ops are (32,32)->32 */
 		coerce_reg_to_size(dst_reg, 4);
-		coerce_reg_to_size(&src_reg, 4);
 	}

 	__reg_deduce_bounds(dst_reg);


@@ -75,6 +75,9 @@

 void URI_FUNC(ResetUri)(URI_TYPE(Uri) * uri) {
+	if (uri == NULL) {
+		return;
+	}
 	memset(uri, 0, sizeof(URI_TYPE(Uri)));
 }


When opening files for write, ensure they aren't symbolic links

Issue #1048 identified that if, for example, a non privileged user
created a symbolic link from /etc/keepalvied.data to /etc/passwd,
writing to /etc/keepalived.data (which could be invoked via DBus)
would cause /etc/passwd to be overwritten.

This commit stops keepalived writing to pathnames where the ultimate
component is a symbolic link, by setting O_NOFOLLOW whenever opening
a file for writing.

This might break some setups, where, for example, /etc/keepalived.data
was a symbolic link to /home/fred/keepalived.data. If this was the case,
instead create a symbolic link from /home/fred/keepalived.data to
/tmp/keepalived.data, so that the file is still accessible via
/home/fred/keepalived.data.

There doesn't appear to be a way around this backward incompatibility,
since even checking if the pathname is a symbolic link prior to opening
for writing would create a race condition.

Signed-off-by: Quentin Armitage <quentin@armitage.org.uk>

@@ -32,14 +32,15 @@
 #include "vrrp.h"
 #include "vrrp_data.h"
 #include "vrrp_print.h"
+#include "utils.h"

 static const char *dump_file = "/tmp/keepalived.data";
 static const char *stats_file = "/tmp/keepalived.stats";

 void
 vrrp_print_data(void)
 {
-	FILE *file = fopen (dump_file, "w");
+	FILE *file = fopen_safe(dump_file, "w");

 	if (!file) {
 		log_message(LOG_INFO, "Can't open %s (%d: %s)",
@@ -55,28 +56,24 @@ vrrp_print_data(void)
 void
 vrrp_print_stats(void)
 {
-	FILE *file;
-	file = fopen (stats_file, "w");
+	FILE *file = fopen_safe(stats_file, "w");
+	element e;
+	vrrp_t *vrrp;

 	if (!file) {
 		log_message(LOG_INFO, "Can't open %s (%d: %s)",
 			stats_file, errno, strerror(errno));
 		return;
 	}

-	list l = vrrp_data->vrrp;
-	element e;
-	vrrp_t *vrrp;

-	for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
-		vrrp = ELEMENT_DATA(e);
+	LIST_FOREACH(vrrp_data->vrrp, vrrp, e) {
 		fprintf(file, "VRRP Instance: %s\n", vrrp->iname);
 		fprintf(file, "  Advertisements:\n");
 		fprintf(file, "    Received: %" PRIu64 "\n", vrrp->stats->advert_rcvd);
 		fprintf(file, "    Sent: %d\n", vrrp->stats->advert_sent);
 		fprintf(file, "  Became master: %d\n", vrrp->stats->become_master);
-		fprintf(file, "  Released master: %d\n",
-			vrrp->stats->release_master);
+		fprintf(file, "  Released master: %d\n", vrrp->stats->release_master);
 		fprintf(file, "  Packet Errors:\n");
 		fprintf(file, "    Length: %" PRIu64 "\n", vrrp->stats->packet_len_err);
 		fprintf(file, "    TTL: %" PRIu64 "\n", vrrp->stats->ip_ttl_err);


Add command line and configuration option to set umask

Issue #1048 identified that files created by keepalived are created
with mode 0666. This commit changes the default to 0644, and also
allows the umask to be specified in the configuration or as a command
line option.

Signed-off-by: Quentin Armitage <quentin@armitage.org.uk>

@@ -35,6 +35,8 @@
 #include <sched.h>
 #endif
 #include <strings.h>
+#include <sys/types.h>
+#include <sys/stat.h>

 #ifdef _WITH_SNMP_
 #include "snmp.h"
@@ -1341,6 +1343,76 @@ no_checker_emails_handler(vector_t *strvec)
 }
 #endif

+static void
+umask_handler(vector_t *strvec)
+{
+	long umask_long;
+	mode_t umask_val = 0;
+	char *mask = strvec_slot(strvec, 1);
+	char *endptr;
+	unsigned i;
+	char *p;
+
+	if (umask_cmdline) {
+		log_message(LOG_INFO, "umask command line option specified, ignoring config option");
+		return;
+	}
+
+	if (isdigit(mask[0])) {
+		if (vector_size(strvec) != 2) {
+			report_config_error(CONFIG_GENERAL_ERROR, "%s parameter(s) to umask option", vector_size(strvec) == 1 ? "Missing" : "Extra");
+			return;
+		}
+		umask_long = strtol(mask, &endptr, 0);
+		if (*endptr || umask_long < 0 || umask_long & ~0777L) {
+			report_config_error(CONFIG_GENERAL_ERROR, "invalid umask value %s", mask);
+			return;
+		}
+		umask_val = umask_long & 0777;
+	}
+	else {
+		bool need_or = false;
+		for (i = 1; i < vector_size(strvec); i++) {
+			for (p = strvec_slot(strvec, i); *p; ) {
+				if (need_or) {
+					if (*p == '|') {
+						need_or = false;
+						p++;
+						continue;
+					}
+
+					report_config_error(CONFIG_GENERAL_ERROR, "Invalid umask syntax %s", FMT_STR_VSLOT(strvec, i));
+					return;
+				}
+
+				if      (!strncmp(p, "IRUSR", 5)) umask_val |= S_IRUSR;
+				else if (!strncmp(p, "IWUSR", 5)) umask_val |= S_IWUSR;
+				else if (!strncmp(p, "IXUSR", 5)) umask_val |= S_IXUSR;
+				else if (!strncmp(p, "IRGRP", 5)) umask_val |= S_IRGRP;
+				else if (!strncmp(p, "IWGRP", 5)) umask_val |= S_IWGRP;
+				else if (!strncmp(p, "IXGRP", 5)) umask_val |= S_IXGRP;
+				else if (!strncmp(p, "IROTH", 5)) umask_val |= S_IROTH;
+				else if (!strncmp(p, "IWOTH", 5)) umask_val |= S_IWOTH;
+				else if (!strncmp(p, "IXOTH", 5)) umask_val |= S_IXOTH;
+				else {
+					report_config_error(CONFIG_GENERAL_ERROR, "Unknown umask bit %s", p);
+					return;
+				}
+
+				p += 5;
+				need_or = true;
+			}
+		}
+		if (!need_or) {
+			report_config_error(CONFIG_GENERAL_ERROR, "umask missing bit value");
+			return;
+		}
+	}
+
+	global_data->umask = umask_val;
+	umask(umask_val);
+}
+
 void
 init_global_keywords(bool global_active)
 {
@@ -1483,4 +1555,5 @@ init_global_keywords(bool global_active)
 	install_keyword("vrrp_rx_bufs_policy", &vrrp_rx_bufs_policy_handler);
 	install_keyword("vrrp_rx_bufs_multiplier", &vrrp_rx_bufs_multiplier_handler);
 #endif
+	install_keyword("umask", &umask_handler);
 }


[mod_alias] security: potential path traversal with specific configs

Security: potential path traversal of a single directory above the alias
target with a specific mod_alias config where the alias which is matched
does not end in '/', but alias target filesystem path does end in '/'.

e.g. server.docroot = "/srv/www/host/HOSTNAME/docroot"
     alias.url = ( "/img" => "/srv/www/hosts/HOSTNAME/images/" )

If a malicious URL "/img../" were passed, the request would be
for directory "/srv/www/hosts/HOSTNAME/images/../" which would resolve
to "/srv/www/hosts/HOSTNAME/".  If mod_dirlisting were enabled, which
is not the default, this would result in listing the contents of the
directory above the alias.  An attacker might also try to directly
access files anywhere under that path, which is one level above the
intended aliased path.

credit: Orange Tsai(@orange_8361) from DEVCORE

@@ -181,6 +181,21 @@ PHYSICALPATH_FUNC(mod_alias_physical_handler) {
 					strncmp(uri_ptr, ds->key->ptr, alias_len))) {
 			/* matched */

+			/* check for path traversal in url-path following alias if key
+			 * does not end in slash, but replacement value ends in slash */
+			if (uri_ptr[alias_len] == '.') {
+				char *s = uri_ptr + alias_len + 1;
+				if (*s == '.') ++s;
+				if (*s == '/' || *s == '\0') {
+					size_t vlen = buffer_string_length(ds->value);
+					if (0 != alias_len && ds->key->ptr[alias_len-1] != '/'
+					    && 0 != vlen && ds->value->ptr[vlen-1] == '/') {
+						con->http_status = 403;
+						return HANDLER_FINISHED;
+					}
+				}
+			}
+
 			buffer_copy_buffer(con->physical.basedir, ds->value);
 			buffer_copy_buffer(srv->tmp_buf, ds->value);
 			buffer_append_string(srv->tmp_buf, uri_ptr + alias_len);


Fix #12374 - oobread crash in truncated dyldcache ##bin (#12381)

@@ -1,4 +1,4 @@
-/* radare - LGPL - Copyright 2010-2016 - nibble, pancake  */
+/* radare - LGPL - Copyright 2010-2018 - nibble, pancake  */

 #include <stdio.h>
 #include <r_types.h>
@@ -21,6 +21,23 @@ static int r_bin_dyldcache_apply_patch (struct r_buf_t* buf, ut32 data, ut64 off

 #define NZ_OFFSET(x) if((x) > 0) r_bin_dyldcache_apply_patch (dbuf, (x) - linkedit_offset, (ut64)((size_t)&(x) - (size_t)data))

+// make it public in util/buf.c ?
+static ut64 r_buf_read64le (RBuffer *buf, ut64 off) {
+	ut8 data[8] = {0};
+	r_buf_read_at (buf, off, data, 8);
+	return r_read_le64 (data);
+}
+
+static char *r_buf_read_string (RBuffer *buf, ut64 addr, int len) {
+	ut8 *data = malloc (len);
+	if (data) {
+		r_buf_read_at (buf, addr, data, len);
+		data[len-1] = 0;
+		return data;
+	}
+	return NULL;
+}
+
 /* TODO: Needs more testing and ERROR HANDLING */
 struct r_bin_dyldcache_lib_t *r_bin_dyldcache_extract(struct r_bin_dyldcache_obj_t* bin, int idx, int *nlib) {
 	ut64 liboff, linkedit_offset;
@@ -47,34 +64,41 @@ struct r_bin_dyldcache_lib_t *r_bin_dyldcache_extract(struct r_bin_dyldcache_obj
 	*nlib = bin->nlibs;
 	ret = R_NEW0 (struct r_bin_dyldcache_lib_t);
 	if (!ret) {
-		perror ("malloc (ret)");
 		return NULL;
 	}
 	if (bin->hdr.startaddr > bin->size) {
 	    	eprintf ("corrupted dyldcache");
 		free (ret);
 		return NULL;
 	}
+
 	if (bin->hdr.startaddr > bin->size || bin->hdr.baseaddroff > bin->size) {
 		eprintf ("corrupted dyldcache");
 		free (ret);
 		return NULL;
 	}
-	image_infos = (struct dyld_cache_image_info*) (bin->b->buf + bin->hdr.startaddr);
-	dyld_vmbase = *(ut64 *)(bin->b->buf + bin->hdr.baseaddroff);
+	int sz = bin->nlibs * sizeof (struct dyld_cache_image_info);
+	image_infos = malloc (sz); //(struct dyld_cache_image_info*) (bin->b->buf + bin->hdr.startaddr);
+	if (!image_infos) {
+		free (ret);
+		return NULL;
+	}
+	r_buf_read_at (bin->b, bin->hdr.startaddr, (ut8*)image_infos, sz);
+	dyld_vmbase = r_buf_read64le (bin->b, bin->hdr.baseaddroff);
 	liboff = image_infos[idx].address - dyld_vmbase;
 	if (liboff > bin->size) {
 		eprintf ("Corrupted file\n");
 		free (ret);
 		return NULL;
 	}
 	ret->offset = liboff;
-	if (image_infos[idx].pathFileOffset > bin->size) {
-	    eprintf ("corrupted file\n");
+	int pfo = image_infos[idx].pathFileOffset;
+	if (pfo < 0 || pfo > bin->size) {
+		eprintf ("corrupted file: pathFileOffset > bin->size (%d)\n", pfo);
 		free (ret);
 		return NULL;
 	}
-	libname = (char *)(bin->b->buf + image_infos[idx].pathFileOffset);
+	libname = r_buf_read_string (bin->b, pfo, 64);
 	/* Locate lib hdr in cache */
 	data = bin->b->buf + liboff;
 	mh = (struct mach_header *)data;
@@ -224,16 +248,15 @@ struct r_bin_dyldcache_obj_t* r_bin_dyldcache_new(const char* file) {
 }

 struct r_bin_dyldcache_obj_t* r_bin_dyldcache_from_bytes_new(const ut8* buf, ut64 size) {
-	struct r_bin_dyldcache_obj_t *bin;
-	if (!(bin = malloc (sizeof (struct r_bin_dyldcache_obj_t)))) {
+	struct r_bin_dyldcache_obj_t *bin = R_NEW0 (struct r_bin_dyldcache_obj_t);
+	if (!bin) {
 		return NULL;
 	}
-	memset (bin, 0, sizeof (struct r_bin_dyldcache_obj_t));
 	if (!buf) {
 		return r_bin_dyldcache_free (bin);
 	}
-	bin->b = r_buf_new();
-	if (!r_buf_set_bytes (bin->b, buf, size)) {
+	bin->b = r_buf_new ();
+	if (!bin->b || !r_buf_set_bytes (bin->b, buf, size)) {
 		return r_bin_dyldcache_free (bin);
 	}
 	if (!r_bin_dyldcache_init (bin)) {


userfaultfd: shmem/hugetlbfs: only allow to register VM_MAYWRITE vmas

After the VMA to register the uffd onto is found, check that it has
VM_MAYWRITE set before allowing registration.  This way we inherit all
common code checks before allowing to fill file holes in shmem and
hugetlbfs with UFFDIO_COPY.

The userfaultfd memory model is not applicable for readonly files unless
it's a MAP_PRIVATE.

Link: http://lkml.kernel.org/r/20181126173452.26955-4-aarcange@redhat.com
Fixes: ff62a3421044 ("hugetlb: implement memfd sealing")
Signed-off-by: Andrea Arcangeli <aarcange@redhat.com>
Reviewed-by: Mike Rapoport <rppt@linux.ibm.com>
Reviewed-by: Hugh Dickins <hughd@google.com>
Reported-by: Jann Horn <jannh@google.com>
Fixes: 4c27fe4c4c84 ("userfaultfd: shmem: add shmem_mcopy_atomic_pte for userfaultfd support")
Cc: <stable@vger.kernel.org>
Cc: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
Cc: Mike Kravetz <mike.kravetz@oracle.com>
Cc: Peter Xu <peterx@redhat.com>
Cc: stable@vger.kernel.org
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

@@ -205,8 +205,9 @@ static __always_inline ssize_t __mcopy_atomic_hugetlb(struct mm_struct *dst_mm,
 		if (!dst_vma || !is_vm_hugetlb_page(dst_vma))
 			goto out_unlock;
 		/*
-		 * Only allow __mcopy_atomic_hugetlb on userfaultfd
-		 * registered ranges.
+		 * Check the vma is registered in uffd, this is
+		 * required to enforce the VM_MAYWRITE check done at
+		 * uffd registration time.
 		 */
 		if (!dst_vma->vm_userfaultfd_ctx.ctx)
 			goto out_unlock;
@@ -459,13 +460,9 @@ static __always_inline ssize_t __mcopy_atomic(struct mm_struct *dst_mm,
 	if (!dst_vma)
 		goto out_unlock;
 	/*
-	 * Be strict and only allow __mcopy_atomic on userfaultfd
-	 * registered ranges to prevent userland errors going
-	 * unnoticed. As far as the VM consistency is concerned, it
-	 * would be perfectly safe to remove this check, but there's
-	 * no useful usage for __mcopy_atomic ouside of userfaultfd
-	 * registered ranges. This is after all why these are ioctls
-	 * belonging to the userfaultfd and not syscalls.
+	 * Check the vma is registered in uffd, this is required to
+	 * enforce the VM_MAYWRITE check done at uffd registration
+	 * time.
 	 */
 	if (!dst_vma->vm_userfaultfd_ctx.ctx)
 		goto out_unlock;


LibVNCClient: ignore server-sent cut text longer than 1MB

This is in line with how LibVNCServer does it
(28afb6c537dc82ba04d5f245b15ca7205c6dbb9c) and fixes part of #273.

@@ -2217,6 +2217,11 @@ HandleRFBServerMessage(rfbClient* client)

     msg.sct.length = rfbClientSwap32IfLE(msg.sct.length);

+    if (msg.sct.length > 1<<20) {
+	    rfbClientErr("Ignoring too big cut text length sent by server: %u B > 1 MB\n", (unsigned int)msg.sct.length);
+	    return FALSE;
+    }
+
     buffer = malloc((uint64_t)msg.sct.length+1);

     if (!ReadFromRFBServer(client, buffer, msg.sct.length)) {


Sync with upstream

Even though libgd/libgd#492 is not a relevant bug fix for PHP, since
the binding doesn't use the `gdImage*Ptr()` functions at all, we're
porting the fix to stay in sync here.

@@ -97,12 +97,18 @@ static void cl_hash (register count_int chsize, GifCtx *ctx);
 static void char_init (GifCtx *ctx);
 static void char_out (int c, GifCtx *ctx);
 static void flush_char (GifCtx *ctx);
+
+static int _gdImageGifCtx(gdImagePtr im, gdIOCtxPtr out);
+
 void * gdImageGifPtr (gdImagePtr im, int *size)
 {
   void *rv;
   gdIOCtx *out = gdNewDynamicCtx (2048, NULL);
-  gdImageGifCtx (im, out);
-  rv = gdDPExtractData (out, size);
+	if (!_gdImageGifCtx(im, out)) {
+		rv = gdDPExtractData(out, size);
+	} else {
+		rv = NULL;
+	}
   out->gd_free (out);
   return rv;
 }
@@ -115,6 +121,12 @@ void gdImageGif (gdImagePtr im, FILE * outFile)
 }

 void gdImageGifCtx(gdImagePtr im, gdIOCtxPtr out)
+{
+	_gdImageGifCtx(im, out);
+}
+
+/* returns 0 on success, 1 on failure */
+static int _gdImageGifCtx(gdImagePtr im, gdIOCtxPtr out)
 {
 	gdImagePtr pim = 0, tim = im;
 	int interlace, BitsPerPixel;
@@ -125,7 +137,7 @@ void gdImageGifCtx(gdImagePtr im, gdIOCtxPtr out)
 			based temporary image. */
 		pim = gdImageCreatePaletteFromTrueColor(im, 1, 256);
 		if (!pim) {
-			return;
+			return 1;
 		}
 		tim = pim;
 	}
@@ -138,6 +150,8 @@ void gdImageGifCtx(gdImagePtr im, gdIOCtxPtr out)
 		/* Destroy palette based temporary image. */
 		gdImageDestroy(	pim);
 	}
+
+    return 0;
 }

 static int


Fixed CVE-2019-9199, issue #40 (raises PdfError with PageNotFound code on error)

The error is the page 0 (0-based) not being found, before this fix that led to
a null pointer dereference (method call on a null pointer, undefined behavior),
now just a PdfError exception is raised.

@@ -148,7 +148,12 @@ namespace PoDoFo
 // 	std::cerr << "Document has "<< pcount << " page(s) " << endl;
 			if ( pcount > 0 ) // only here to avoid possible segfault, but PDF without page is not conform IIRC
 			{
-				PoDoFo::PdfRect rect ( sourceDoc->GetPage ( 0 )->GetMediaBox() );
+                PoDoFo::PdfPage* pFirstPage = sourceDoc->GetPage ( 0 );
+                if ( NULL == pFirstPage ) // Fixes CVE-2019-9199 (issue #40)
+                {
+                    PODOFO_RAISE_ERROR_INFO( ePdfError_PageNotFound, "First page (0) of source document not found" );
+                }
+                PoDoFo::PdfRect rect ( pFirstPage->GetMediaBox() );
 				// keep in mind it’s just a hint since PDF can have different page sizes in a same doc
 				sourceWidth =  rect.GetWidth() - rect.GetLeft();
 				sourceHeight =  rect.GetHeight() - rect.GetBottom() ;


Avoid OOB read (found by ASAN reported by F. Alonso)

@@ -27,7 +27,7 @@
 #include "file.h"

 #ifndef lint
-FILE_RCSID("@(#)$File: readelf.c,v 1.156 2018/10/19 00:33:04 christos Exp $")
+FILE_RCSID("@(#)$File: readelf.c,v 1.157 2019/01/02 19:44:14 christos Exp $")
 #endif

 #ifdef BUILTIN_ELF
@@ -752,7 +752,7 @@ do_core_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type,
 			char sbuf[512];
 			struct NetBSD_elfcore_procinfo pi;
 			memset(&pi, 0, sizeof(pi));
-			memcpy(&pi, nbuf + doff, descsz);
+			memcpy(&pi, nbuf + doff, MIN(descsz, sizeof(pi)));

 			if (file_printf(ms, ", from '%.31s', pid=%u, uid=%u, "
 			    "gid=%u, nlwps=%u, lwp=%u (signal %u/code %u)",


add some boundary checks on gf_text_get_utf8_line (#1188)

@@ -1715,7 +1715,7 @@ int mp4client_main(int argc, char **argv)
 					e = gf_dm_sess_process(sess);
 					if (!e) {
 						strncpy(the_url, gf_dm_sess_get_cache_name(sess), sizeof(the_url) - 1);
-						the_url[sizeof(the_cfg) - 1] = 0;
+						the_url[sizeof(the_url) - 1] = 0;
 					}
 					gf_dm_sess_del(sess);
 				}


Malicious RDP server security fixes

This commit includes fixes for a set of 21 vulnerabilities in
rdesktop when a malicious RDP server is used.

All vulnerabilities was identified and reported by Eyal Itkin.

 * Add rdp_protocol_error function that is used in several fixes
 * Refactor of process_bitmap_updates
 * Fix possible integer overflow in s_check_rem() on 32bit arch
 * Fix memory corruption in process_bitmap_data - CVE-2018-8794
 * Fix remote code execution in process_bitmap_data - CVE-2018-8795
 * Fix remote code execution in process_plane - CVE-2018-8797
 * Fix Denial of Service in mcs_recv_connect_response - CVE-2018-20175
 * Fix Denial of Service in mcs_parse_domain_params - CVE-2018-20175
 * Fix Denial of Service in sec_parse_crypt_info - CVE-2018-20176
 * Fix Denial of Service in sec_recv - CVE-2018-20176
 * Fix minor information leak in rdpdr_process - CVE-2018-8791
 * Fix Denial of Service in cssp_read_tsrequest - CVE-2018-8792
 * Fix remote code execution in cssp_read_tsrequest - CVE-2018-8793
 * Fix Denial of Service in process_bitmap_data - CVE-2018-8796
 * Fix minor information leak in rdpsnd_process_ping - CVE-2018-8798
 * Fix Denial of Service in process_secondary_order - CVE-2018-8799
 * Fix remote code execution in in ui_clip_handle_data - CVE-2018-8800
 * Fix major information leak in ui_clip_handle_data - CVE-2018-20174
 * Fix memory corruption in rdp_in_unistr - CVE-2018-20177
 * Fix Denial of Service in process_demand_active - CVE-2018-20178
 * Fix remote code execution in lspci_process - CVE-2018-20179
 * Fix remote code execution in rdpsnddbg_process - CVE-2018-20180
 * Fix remote code execution in seamless_process - CVE-2018-20181
 * Fix remote code execution in seamless_process_line - CVE-2018-20182

@@ -1,7 +1,8 @@
 /*  -*- c-basic-offset: 8 -*-
    rdesktop: A Remote Desktop Protocol client.
    Support for the Matrox "lspci" channel
-   Copyright (C) 2005 Matrox Graphics Inc.
+   Copyright (C) 2005 Matrox Graphics Inc.
+   Copyright 2018 Henrik Andersson <hean01@cendio.se> for Cendio AB

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -134,6 +135,12 @@ lspci_process(STREAM s)
 	unsigned int pkglen;
 	static char *rest = NULL;
 	char *buf;
+	struct stream packet = *s;
+
+	if (!s_check(s))
+	{
+		rdp_protocol_error("lspci_process(), stream is in unstable state", &packet);
+	}

 	pkglen = s->end - s->p;
 	/* str_handle_lines requires null terminated strings */


@@ -43,6 +43,8 @@ typedef signed short sint16;
 typedef unsigned int uint32;
 typedef signed int sint32;

+#define RD_UINT32_MAX (uint32)(-1)
+
 typedef void *RD_HBITMAP;
 typedef void *RD_HGLYPH;
 typedef void *RD_HCOLOURMAP;


@@ -285,6 +285,19 @@ rdp_in_unistr(STREAM s, int in_len, char **string, uint32 * str_size)
 	size_t ibl, obl;
 	char *pin, *pout;

+	struct stream packet = *s;
+
+	if ((in_len < 0) || ((uint32)in_len >= (RD_UINT32_MAX / 2)))
+	{
+		logger(Protocol, Error, "rdp_in_unistr(), length of unicode data is out of bounds.");
+		abort();
+	}
+
+	if (!s_check_rem(s, in_len))
+	{
+		rdp_protocol_error("rdp_in_unistr(), consume of unicode data from stream would overrun", &packet);
+	}
+
 	// if not already open
 	if (!icv_utf16_to_local)
 	{
@@ -1211,13 +1224,19 @@ process_demand_active(STREAM s)
 {
 	uint8 type;
 	uint16 len_src_descriptor, len_combined_caps;
+	struct stream packet = *s;

 	/* at this point we need to ensure that we have ui created */
 	rd_create_ui();

 	in_uint32_le(s, g_rdp_shareid);
 	in_uint16_le(s, len_src_descriptor);
 	in_uint16_le(s, len_combined_caps);
+
+	if (!s_check_rem(s, len_src_descriptor))
+	{
+		rdp_protocol_error("rdp_demand_active(), consume of source descriptor from stream would overrun", &packet);
+	}
 	in_uint8s(s, len_src_descriptor);

 	logger(Protocol, Debug, "process_demand_active(), shareid=0x%x", g_rdp_shareid);
@@ -1390,78 +1409,113 @@ process_pointer_pdu(STREAM s)
 	}
 }

-/* Process bitmap updates */
-void
-process_bitmap_updates(STREAM s)
+/* Process TS_BITMAP_DATA */
+static void
+process_bitmap_data(STREAM s)
 {
-	uint16 num_updates;
 	uint16 left, top, right, bottom, width, height;
-	uint16 cx, cy, bpp, Bpp, compress, bufsize, size;
+	uint16 cx, cy, bpp, Bpp, flags, bufsize, size;
 	uint8 *data, *bmpdata;
-	int i;
-
+
 	logger(Protocol, Debug, "%s()", __func__);

-	in_uint16_le(s, num_updates);
+	struct stream packet = *s;

-	for (i = 0; i < num_updates; i++)
-	{
-		in_uint16_le(s, left);
-		in_uint16_le(s, top);
-		in_uint16_le(s, right);
-		in_uint16_le(s, bottom);
-		in_uint16_le(s, width);
-		in_uint16_le(s, height);
-		in_uint16_le(s, bpp);
-		Bpp = (bpp + 7) / 8;
-		in_uint16_le(s, compress);
-		in_uint16_le(s, bufsize);
-
-		cx = right - left + 1;
-		cy = bottom - top + 1;
-
-		logger(Graphics, Debug,
-		       "process_bitmap_updates(), [%d,%d,%d,%d], [%d,%d], bpp=%d, compression=%d",
-		       left, top, right, bottom, width, height, Bpp, compress);
-
-		if (!compress)
-		{
-			int y;
-			bmpdata = (uint8 *) xmalloc(width * height * Bpp);
-			for (y = 0; y < height; y++)
-			{
-				in_uint8a(s, &bmpdata[(height - y - 1) * (width * Bpp)],
-					  width * Bpp);
-			}
-			ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
-			xfree(bmpdata);
-			continue;
-		}
+	in_uint16_le(s, left); /* destLeft */
+	in_uint16_le(s, top); /* destTop */
+	in_uint16_le(s, right); /* destRight */
+	in_uint16_le(s, bottom); /* destBottom */
+	in_uint16_le(s, width); /* width */
+	in_uint16_le(s, height); /* height */
+	in_uint16_le(s, bpp); /*bitsPerPixel */
+	Bpp = (bpp + 7) / 8;
+	in_uint16_le(s, flags); /* flags */
+	in_uint16_le(s, bufsize); /* bitmapLength */

+	cx = right - left + 1;
+	cy = bottom - top + 1;

-		if (compress & 0x400)
-		{
-			size = bufsize;
-		}
-		else
-		{
-			in_uint8s(s, 2);	/* pad */
-			in_uint16_le(s, size);
-			in_uint8s(s, 4);	/* line_size, final_size */
-		}
-		in_uint8p(s, data, size);
+	/* FIXME: There are a assumtion that we do not consider in
+		this code. The value of bpp is not passed to
+		ui_paint_bitmap() which relies on g_server_bpp for drawing
+		the bitmap data.
+
+		Does this means that we can sanity check bpp with g_server_bpp ?
+	*/
+
+	if (Bpp == 0 || width == 0 || height == 0)
+	{
+        logger(Protocol, Warning, "%s(), [%d,%d,%d,%d], [%d,%d], bpp=%d, flags=%x", __func__,
+				left, top, right, bottom, width, height, bpp, flags);
+		rdp_protocol_error("TS_BITMAP_DATA, unsafe size of bitmap data received from server", &packet);
+	}
+
+	if ((RD_UINT32_MAX / Bpp) <= (width * height))
+	{
+		logger(Protocol, Warning, "%s(), [%d,%d,%d,%d], [%d,%d], bpp=%d, flags=%x", __func__,
+				left, top, right, bottom, width, height, bpp, flags);
+		rdp_protocol_error("TS_BITMAP_DATA, unsafe size of bitmap data received from server", &packet);
+	}
+
+	if (flags == 0)
+	{
+		/* read uncompressed bitmap data */
+		int y;
 		bmpdata = (uint8 *) xmalloc(width * height * Bpp);
-		if (bitmap_decompress(bmpdata, width, height, data, size, Bpp))
+		for (y = 0; y < height; y++)
 		{
-			ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
+			in_uint8a(s, &bmpdata[(height - y - 1) * (width * Bpp)], width * Bpp);
 		}
-		else
-		{
-			logger(Graphics, Warning,
-			       "process_bitmap_updates(), failed to decompress bitmap");
-		}
-
+
+		ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
 		xfree(bmpdata);
+		return;
+	}
+
+	if (flags & NO_BITMAP_COMPRESSION_HDR)
+	{
+		size = bufsize;
+	}
+	else
+	{
+		/* Read TS_CD_HEADER */
+		in_uint8s(s, 2);        /* skip cbCompFirstRowSize (must be 0x0000) */
+		in_uint16_le(s, size);  /* cbCompMainBodySize */
+		in_uint8s(s, 2);        /* skip cbScanWidth */
+		in_uint8s(s, 2);        /* skip cbUncompressedSize */
+	}
+
+	/* read compressed bitmap data */
+	if (!s_check_rem(s, size))
+	{
+		rdp_protocol_error("process_bitmap_data(), consume of bitmap data from stream would overrun", &packet);
+	}
+	in_uint8p(s, data, size);
+	bmpdata = (uint8 *) xmalloc(width * height * Bpp);
+	if (bitmap_decompress(bmpdata, width, height, data, size, Bpp))
+	{
+		ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
+	}
+	else
+	{
+		logger(Protocol, Warning, "%s(), failed to decompress bitmap", __func__);
+	}
+
+	xfree(bmpdata);
+}
+
+/* Process TS_UPDATE_BITMAP_DATA */
+void
+process_bitmap_updates(STREAM s)
+{
+	int i;
+	uint16 num_updates;
+
+	in_uint16_le(s, num_updates);   /* rectangles */
+
+	for (i = 0; i < num_updates; i++)
+	{
+		process_bitmap_data(s);
 	}
 }

@@ -2013,3 +2067,21 @@ rdp_disconnect(void)
 	logger(Protocol, Debug, "%s()", __func__);
 	sec_disconnect();
 }
+
+/* Abort rdesktop upon protocol error
+
+   A protocol error is defined as:
+
+    - A value is outside specified range for example;
+      bpp for a bitmap is not allowed to be greater than the
+      value 32 but is represented by a byte in protocol.
+
+*/
+void
+rdp_protocol_error(const char *message, STREAM s)
+{
+	logger(Protocol, Error, "%s(), %s", __func__, message);
+	if (s)
+		hexdump(s->p, s_length(s));
+	exit(0);
+}


@@ -751,6 +751,9 @@ enum RDP_DESKTOP_ORIENTATION
 #define ENC_SALTED_CHECKSUM		0x0010
 #define NO_BITMAP_COMPRESSION_HDR	0x0400

+/* [MS-RDPBCGR], TS_BITMAP_DATA, flags */
+#define BITMAP_COMPRESSION              0x0001
+
 /* orderFlags, [MS-RDPBCGR] 2.2.7.1.3 */
 #define NEGOTIATEORDERSUPPORT	0x0002
 #define ZEROBOUNDSDELTASSUPPORT 0x0008


@@ -296,6 +296,9 @@ sec_encrypt(uint8 * data, int length)
 void
 sec_decrypt(uint8 * data, int length)
 {
+	if (length <= 0)
+		return;
+
 	if (g_sec_decrypt_use_count == 4096)
 	{
 		sec_update(g_sec_decrypt_key, g_sec_decrypt_update_key);
@@ -848,9 +851,11 @@ sec_recv(RD_BOOL * is_fastpath)
 	uint16 sec_flags;
 	uint16 channel;
 	STREAM s;
+	struct stream packet;

 	while ((s = mcs_recv(&channel, is_fastpath, &fastpath_hdr)) != NULL)
 	{
+		packet = *s;
 		if (*is_fastpath == True)
 		{
 			/* If fastpath packet is encrypted, read data
@@ -859,6 +864,10 @@ sec_recv(RD_BOOL * is_fastpath)
 			fastpath_flags = (fastpath_hdr & 0xC0) >> 6;
 			if (fastpath_flags & FASTPATH_OUTPUT_ENCRYPTED)
 			{
+				if (!s_check_rem(s, 8)) {
+					rdp_protocol_error("sec_recv(), consume fastpath signature from stream would overrun", &packet);
+				}
+
 				in_uint8s(s, 8);	/* signature */
 				sec_decrypt(s->p, s->end - s->p);
 			}
@@ -875,6 +884,10 @@ sec_recv(RD_BOOL * is_fastpath)
 			{
 				if (sec_flags & SEC_ENCRYPT)
 				{
+					if (!s_check_rem(s, 8)) {
+						rdp_protocol_error("sec_recv(), consume encrypt signature from stream would overrun", &packet);
+					}
+
 					in_uint8s(s, 8);	/* signature */
 					sec_decrypt(s->p, s->end - s->p);
 				}
@@ -889,6 +902,10 @@ sec_recv(RD_BOOL * is_fastpath)
 				{
 					uint8 swapbyte;

+					if (!s_check_rem(s, 8)) {
+						rdp_protocol_error("sec_recv(), consume redirect signature from stream would overrun", &packet);
+					}
+
 					in_uint8s(s, 8);	/* signature */
 					sec_decrypt(s->p, s->end - s->p);


@@ -1259,11 +1259,17 @@ process_secondary_order(STREAM s)
 	uint16 flags;
 	uint8 type;
 	uint8 *next_order;
+	struct stream packet = *s;

 	in_uint16_le(s, length);
 	in_uint16_le(s, flags);	/* used by bmpcache2 */
 	in_uint8(s, type);

+	if (!s_check_rem(s, length + 7))
+	{
+		rdp_protocol_error("process_secondary_order(), next order pointer would overrun stream", &packet);
+	}
+
 	next_order = s->p + (sint16) length + 7;

 	switch (type)


@@ -794,15 +794,15 @@ process_plane(uint8 * in, int width, int height, uint8 * out, int size)
 					replen = revcode;
 					collen = 0;
 				}
-				while (collen > 0)
+				while (indexw < width && collen > 0)
 				{
 					color = CVAL(in);
 					*out = color;
 					out += 4;
 					indexw++;
 					collen--;
 				}
-				while (replen > 0)
+				while (indexw < width && replen > 0)
 				{
 					*out = color;
 					out += 4;
@@ -824,7 +824,7 @@ process_plane(uint8 * in, int width, int height, uint8 * out, int size)
 					replen = revcode;
 					collen = 0;
 				}
-				while (collen > 0)
+				while (indexw < width && collen > 0)
 				{
 					x = CVAL(in);
 					if (x & 1)
@@ -844,7 +844,7 @@ process_plane(uint8 * in, int width, int height, uint8 * out, int size)
 					indexw++;
 					collen--;
 				}
-				while (replen > 0)
+				while (indexw < width && replen > 0)
 				{
 					x = last_line[indexw * 4] + color;
 					*out = x;


@@ -269,6 +269,12 @@ rdpsnd_process_training(STREAM in)
 	uint16 tick;
 	uint16 packsize;
 	STREAM out;
+	struct stream packet = *in;
+
+	if (!s_check_rem(in, 4))
+	{
+		rdp_protocol_error("rdpsnd_process_training(), consume of training data from stream would overrun", &packet);
+	}

 	in_uint16_le(in, tick);
 	in_uint16_le(in, packsize);
@@ -445,6 +451,11 @@ rdpsnddbg_process(STREAM s)
 	static char *rest = NULL;
 	char *buf;

+	if (!s_check(s))
+	{
+		rdp_protocol_error("rdpsnddbg_process(), stream is in unstable state", s);
+	}
+
 	pkglen = s->end - s->p;
 	/* str_handle_lines requires null terminated strings */
 	buf = (char *) xmalloc(pkglen + 1);


@@ -1,7 +1,8 @@
 /*  -*- c-basic-offset: 8 -*-
    rdesktop: A Remote Desktop Protocol client.
    Support for the Matrox "lspci" channel
-   Copyright (C) 2005 Matrox Graphics Inc.
+   Copyright (C) 2005 Matrox Graphics Inc.
+   Copyright 2018 Henrik Andersson <hean01@cendio.se> for Cendio AB

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by

@@ -134,6 +135,12 @@ lspci_process(STREAM s)
 	unsigned int pkglen;
 	static char *rest = NULL;
 	char *buf;
+	struct stream packet = *s;
+
+	if (!s_check(s))
+	{
+		rdp_protocol_error("lspci_process(), stream is in unstable state", &packet);
+	}

 	pkglen = s->end - s->p;
 	/* str_handle_lines requires null terminated strings */


@@ -285,6 +285,19 @@ rdp_in_unistr(STREAM s, int in_len, char **string, uint32 * str_size)
 	size_t ibl, obl;
 	char *pin, *pout;

+	struct stream packet = *s;
+
+	if ((in_len < 0) || ((uint32)in_len >= (RD_UINT32_MAX / 2)))
+	{
+		logger(Protocol, Error, "rdp_in_unistr(), length of unicode data is out of bounds.");
+		abort();
+	}
+
+	if (!s_check_rem(s, in_len))
+	{
+		rdp_protocol_error("rdp_in_unistr(), consume of unicode data from stream would overrun", &packet);
+	}
+
 	// if not already open
 	if (!icv_utf16_to_local)
 	{

@@ -1211,13 +1224,19 @@ process_demand_active(STREAM s)
 {
 	uint8 type;
 	uint16 len_src_descriptor, len_combined_caps;
+	struct stream packet = *s;

 	/* at this point we need to ensure that we have ui created */
 	rd_create_ui();

 	in_uint32_le(s, g_rdp_shareid);
 	in_uint16_le(s, len_src_descriptor);
 	in_uint16_le(s, len_combined_caps);
+
+	if (!s_check_rem(s, len_src_descriptor))
+	{
+		rdp_protocol_error("rdp_demand_active(), consume of source descriptor from stream would overrun", &packet);
+	}
 	in_uint8s(s, len_src_descriptor);

 	logger(Protocol, Debug, "process_demand_active(), shareid=0x%x", g_rdp_shareid);

@@ -1390,78 +1409,113 @@ process_pointer_pdu(STREAM s)
 	}
 }

-/* Process bitmap updates */
-void
-process_bitmap_updates(STREAM s)
+/* Process TS_BITMAP_DATA */
+static void
+process_bitmap_data(STREAM s)
 {
-	uint16 num_updates;
 	uint16 left, top, right, bottom, width, height;
-	uint16 cx, cy, bpp, Bpp, compress, bufsize, size;
+	uint16 cx, cy, bpp, Bpp, flags, bufsize, size;
 	uint8 *data, *bmpdata;
-	int i;
-
+
 	logger(Protocol, Debug, "%s()", __func__);

-	in_uint16_le(s, num_updates);
+	struct stream packet = *s;

-	for (i = 0; i < num_updates; i++)
-	{
-		in_uint16_le(s, left);
-		in_uint16_le(s, top);
-		in_uint16_le(s, right);
-		in_uint16_le(s, bottom);
-		in_uint16_le(s, width);
-		in_uint16_le(s, height);
-		in_uint16_le(s, bpp);
-		Bpp = (bpp + 7) / 8;
-		in_uint16_le(s, compress);
-		in_uint16_le(s, bufsize);
-
-		cx = right - left + 1;
-		cy = bottom - top + 1;
-
-		logger(Graphics, Debug,
-		       "process_bitmap_updates(), [%d,%d,%d,%d], [%d,%d], bpp=%d, compression=%d",
-		       left, top, right, bottom, width, height, Bpp, compress);
-
-		if (!compress)
-		{
-			int y;
-			bmpdata = (uint8 *) xmalloc(width * height * Bpp);
-			for (y = 0; y < height; y++)
-			{
-				in_uint8a(s, &bmpdata[(height - y - 1) * (width * Bpp)],
-					  width * Bpp);
-			}
-			ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
-			xfree(bmpdata);
-			continue;
-		}
+	in_uint16_le(s, left); /* destLeft */
+	in_uint16_le(s, top); /* destTop */
+	in_uint16_le(s, right); /* destRight */
+	in_uint16_le(s, bottom); /* destBottom */
+	in_uint16_le(s, width); /* width */
+	in_uint16_le(s, height); /* height */
+	in_uint16_le(s, bpp); /*bitsPerPixel */
+	Bpp = (bpp + 7) / 8;
+	in_uint16_le(s, flags); /* flags */
+	in_uint16_le(s, bufsize); /* bitmapLength */

+	cx = right - left + 1;
+	cy = bottom - top + 1;

-		if (compress & 0x400)
-		{
-			size = bufsize;
-		}
-		else
-		{
-			in_uint8s(s, 2);	/* pad */
-			in_uint16_le(s, size);
-			in_uint8s(s, 4);	/* line_size, final_size */
-		}
-		in_uint8p(s, data, size);
+	/* FIXME: There are a assumtion that we do not consider in
+		this code. The value of bpp is not passed to
+		ui_paint_bitmap() which relies on g_server_bpp for drawing
+		the bitmap data.
+
+		Does this means that we can sanity check bpp with g_server_bpp ?
+	*/
+
+	if (Bpp == 0 || width == 0 || height == 0)
+	{
+        logger(Protocol, Warning, "%s(), [%d,%d,%d,%d], [%d,%d], bpp=%d, flags=%x", __func__,
+				left, top, right, bottom, width, height, bpp, flags);
+		rdp_protocol_error("TS_BITMAP_DATA, unsafe size of bitmap data received from server", &packet);
+	}
+
+	if ((RD_UINT32_MAX / Bpp) <= (width * height))
+	{
+		logger(Protocol, Warning, "%s(), [%d,%d,%d,%d], [%d,%d], bpp=%d, flags=%x", __func__,
+				left, top, right, bottom, width, height, bpp, flags);
+		rdp_protocol_error("TS_BITMAP_DATA, unsafe size of bitmap data received from server", &packet);
+	}
+
+	if (flags == 0)
+	{
+		/* read uncompressed bitmap data */
+		int y;
 		bmpdata = (uint8 *) xmalloc(width * height * Bpp);
-		if (bitmap_decompress(bmpdata, width, height, data, size, Bpp))
+		for (y = 0; y < height; y++)
 		{
-			ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
+			in_uint8a(s, &bmpdata[(height - y - 1) * (width * Bpp)], width * Bpp);
 		}
-		else
-		{
-			logger(Graphics, Warning,
-			       "process_bitmap_updates(), failed to decompress bitmap");
-		}
-
+
+		ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
 		xfree(bmpdata);
+		return;
+	}
+
+	if (flags & NO_BITMAP_COMPRESSION_HDR)
+	{
+		size = bufsize;
+	}
+	else
+	{
+		/* Read TS_CD_HEADER */
+		in_uint8s(s, 2);        /* skip cbCompFirstRowSize (must be 0x0000) */
+		in_uint16_le(s, size);  /* cbCompMainBodySize */
+		in_uint8s(s, 2);        /* skip cbScanWidth */
+		in_uint8s(s, 2);        /* skip cbUncompressedSize */
+	}
+
+	/* read compressed bitmap data */
+	if (!s_check_rem(s, size))
+	{
+		rdp_protocol_error("process_bitmap_data(), consume of bitmap data from stream would overrun", &packet);
+	}
+	in_uint8p(s, data, size);
+	bmpdata = (uint8 *) xmalloc(width * height * Bpp);
+	if (bitmap_decompress(bmpdata, width, height, data, size, Bpp))
+	{
+		ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
+	}
+	else
+	{
+		logger(Protocol, Warning, "%s(), failed to decompress bitmap", __func__);
+	}
+
+	xfree(bmpdata);
+}
+
+/* Process TS_UPDATE_BITMAP_DATA */
+void
+process_bitmap_updates(STREAM s)
+{
+	int i;
+	uint16 num_updates;
+
+	in_uint16_le(s, num_updates);   /* rectangles */
+
+	for (i = 0; i < num_updates; i++)
+	{
+		process_bitmap_data(s);
 	}
 }

@@ -2013,3 +2067,21 @@ rdp_disconnect(void)
 	logger(Protocol, Debug, "%s()", __func__);
 	sec_disconnect();
 }
+
+/* Abort rdesktop upon protocol error
+
+   A protocol error is defined as:
+
+    - A value is outside specified range for example;
+      bpp for a bitmap is not allowed to be greater than the
+      value 32 but is represented by a byte in protocol.
+
+*/
+void
+rdp_protocol_error(const char *message, STREAM s)
+{
+	logger(Protocol, Error, "%s(), %s", __func__, message);
+	if (s)
+		hexdump(s->p, s_length(s));
+	exit(0);
+}


@@ -296,6 +296,9 @@ sec_encrypt(uint8 * data, int length)
 void
 sec_decrypt(uint8 * data, int length)
 {
+	if (length <= 0)
+		return;
+
 	if (g_sec_decrypt_use_count == 4096)
 	{
 		sec_update(g_sec_decrypt_key, g_sec_decrypt_update_key);

@@ -848,9 +851,11 @@ sec_recv(RD_BOOL * is_fastpath)
 	uint16 sec_flags;
 	uint16 channel;
 	STREAM s;
+	struct stream packet;

 	while ((s = mcs_recv(&channel, is_fastpath, &fastpath_hdr)) != NULL)
 	{
+		packet = *s;
 		if (*is_fastpath == True)
 		{
 			/* If fastpath packet is encrypted, read data

@@ -859,6 +864,10 @@ sec_recv(RD_BOOL * is_fastpath)
 			fastpath_flags = (fastpath_hdr & 0xC0) >> 6;
 			if (fastpath_flags & FASTPATH_OUTPUT_ENCRYPTED)
 			{
+				if (!s_check_rem(s, 8)) {
+					rdp_protocol_error("sec_recv(), consume fastpath signature from stream would overrun", &packet);
+				}
+
 				in_uint8s(s, 8);	/* signature */
 				sec_decrypt(s->p, s->end - s->p);
 			}

@@ -875,6 +884,10 @@ sec_recv(RD_BOOL * is_fastpath)
 			{
 				if (sec_flags & SEC_ENCRYPT)
 				{
+					if (!s_check_rem(s, 8)) {
+						rdp_protocol_error("sec_recv(), consume encrypt signature from stream would overrun", &packet);
+					}
+
 					in_uint8s(s, 8);	/* signature */
 					sec_decrypt(s->p, s->end - s->p);
 				}

@@ -889,6 +902,10 @@ sec_recv(RD_BOOL * is_fastpath)
 				{
 					uint8 swapbyte;

+					if (!s_check_rem(s, 8)) {
+						rdp_protocol_error("sec_recv(), consume redirect signature from stream would overrun", &packet);
+					}
+
 					in_uint8s(s, 8);	/* signature */
 					sec_decrypt(s->p, s->end - s->p);


@@ -794,15 +794,15 @@ process_plane(uint8 * in, int width, int height, uint8 * out, int size)
 					replen = revcode;
 					collen = 0;
 				}
-				while (collen > 0)
+				while (indexw < width && collen > 0)
 				{
 					color = CVAL(in);
 					*out = color;
 					out += 4;
 					indexw++;
 					collen--;
 				}
-				while (replen > 0)
+				while (indexw < width && replen > 0)
 				{
 					*out = color;
 					out += 4;

@@ -824,7 +824,7 @@ process_plane(uint8 * in, int width, int height, uint8 * out, int size)
 					replen = revcode;
 					collen = 0;
 				}
-				while (collen > 0)
+				while (indexw < width && collen > 0)
 				{
 					x = CVAL(in);
 					if (x & 1)

@@ -844,7 +844,7 @@ process_plane(uint8 * in, int width, int height, uint8 * out, int size)
 					indexw++;
 					collen--;
 				}
-				while (replen > 0)
+				while (indexw < width && replen > 0)
 				{
 					x = last_line[indexw * 4] + color;
 					*out = x;


@@ -269,6 +269,12 @@ rdpsnd_process_training(STREAM in)
 	uint16 tick;
 	uint16 packsize;
 	STREAM out;
+	struct stream packet = *in;
+
+	if (!s_check_rem(in, 4))
+	{
+		rdp_protocol_error("rdpsnd_process_training(), consume of training data from stream would overrun", &packet);
+	}

 	in_uint16_le(in, tick);
 	in_uint16_le(in, packsize);

@@ -445,6 +451,11 @@ rdpsnddbg_process(STREAM s)
 	static char *rest = NULL;
 	char *buf;

+	if (!s_check(s))
+	{
+		rdp_protocol_error("rdpsnddbg_process(), stream is in unstable state", s);
+	}
+
 	pkglen = s->end - s->p;
 	/* str_handle_lines requires null terminated strings */
 	buf = (char *) xmalloc(pkglen + 1);


Fix UAF in comps_objmrtree_unite function

The added field is not used at all in many places and it is probably the
left-over of some copy-paste.

@@ -285,7 +285,6 @@ void comps_objmrtree_unite(COMPS_ObjMRTree *rt1, COMPS_ObjMRTree *rt2) {
     struct Pair {
         COMPS_HSList * subnodes;
         char * key;
-        char added;
     } *pair, *parent_pair;

     pair = malloc(sizeof(struct Pair));
@@ -303,7 +302,6 @@ void comps_objmrtree_unite(COMPS_ObjMRTree *rt1, COMPS_ObjMRTree *rt2) {
         parent_pair = (struct Pair*) it->data;
         free(it);

-        pair->added = 0;
         for (it = tmp_subnodes->first; it != NULL; it=it->next) {
             pair = malloc(sizeof(struct Pair));
             pair->subnodes = ((COMPS_ObjMRTreeData*)it->data)->subnodes;


@@ -118,6 +118,7 @@ cliprdr_process(STREAM s)
 	uint16 type, status;
 	uint32 length, format;
 	uint8 *data;
+	struct stream packet = *s;

 	in_uint16_le(s, type);
 	in_uint16_le(s, status);
@@ -127,6 +128,11 @@ cliprdr_process(STREAM s)
 	logger(Clipboard, Debug, "cliprdr_process(), type=%d, status=%d, length=%d", type, status,
 	       length);

+	if (!s_check_rem(s, length))
+	{
+		rdp_protocol_error("cliprdr_process(), consume of packet from stream would overrun", &packet);
+	}
+
 	if (status == CLIPRDR_ERROR)
 	{
 		switch (type)


@@ -168,6 +168,12 @@ seamless_process_line(const char *line, void *data)

 			icon_buf[len] = strtol(byte, NULL, 16);
 			len++;
+
+			if ((size_t)len >= sizeof(icon_buf))
+			{
+				logger(Protocol, Warning, "seamless_process_line(), icon data would overrun icon_buf");
+				break;
+			}
 		}

 		ui_seamless_seticon(id, tok5, width, height, chunk, icon_buf, len);
@@ -370,6 +376,12 @@ seamless_process(STREAM s)
 {
 	unsigned int pkglen;
 	char *buf;
+	struct stream packet = *s;
+
+	if (!s_check(s))
+	{
+		rdp_protocol_error("seamless_process(), stream is in unstable state", &packet);
+	}

 	pkglen = s->end - s->p;
 	/* str_handle_lines requires null terminated strings */


@@ -45,9 +45,16 @@ mcs_out_domain_params(STREAM s, int max_channels, int max_users, int max_tokens,
 static RD_BOOL
 mcs_parse_domain_params(STREAM s)
 {
-	int length;
+	uint32 length;
+	struct stream packet = *s;

 	ber_parse_header(s, MCS_TAG_DOMAIN_PARAMS, &length);
+
+	if (!s_check_rem(s, length))
+	{
+		rdp_protocol_error("mcs_parse_domain_params(), consume domain params from stream would overrun", &packet);
+	}
+
 	in_uint8s(s, length);

 	return s_check(s);
@@ -89,8 +96,9 @@ mcs_recv_connect_response(STREAM mcs_data)
 {
 	UNUSED(mcs_data);
 	uint8 result;
-	int length;
+	uint32 length;
 	STREAM s;
+	struct stream packet;
 	RD_BOOL is_fastpath;
 	uint8 fastpath_hdr;

@@ -99,6 +107,8 @@ mcs_recv_connect_response(STREAM mcs_data)

 	if (s == NULL)
 		return False;
+
+	packet = *s;

 	ber_parse_header(s, MCS_CONNECT_RESPONSE, &length);

@@ -112,6 +122,12 @@ mcs_recv_connect_response(STREAM mcs_data)

 	ber_parse_header(s, BER_TAG_INTEGER, &length);
 	in_uint8s(s, length);	/* connect id */
+
+	if (!s_check_rem(s, length))
+	{
+		rdp_protocol_error("mcs_recv_connect_response(), consume connect id from stream would overrun", &packet);
+	}
+
 	mcs_parse_domain_params(s);

 	ber_parse_header(s, BER_TAG_OCTET_STRING, &length);


@@ -22,7 +22,7 @@

 /* Parse an ASN.1 BER header */
 RD_BOOL
-ber_parse_header(STREAM s, int tagval, int *length)
+ber_parse_header(STREAM s, int tagval, uint32 *length)
 {
 	int tag, len;


@@ -854,6 +854,7 @@ rdpdr_process(STREAM s)
 	uint16 vmin;
 	uint16 component;
 	uint16 pakid;
+	struct stream packet = *s;

 	logger(Protocol, Debug, "rdpdr_process()");
 	/* hexdump(s->p, s->end - s->p); */
@@ -873,8 +874,18 @@ rdpdr_process(STREAM s)
 				/* DR_CORE_SERVER_ANNOUNCE_REQ */
 				in_uint8s(s, 2);	/* skip versionMajor */
 				in_uint16_le(s, vmin);	/* VersionMinor */
+
 				in_uint32_le(s, g_client_id);	/* ClientID */

+				/* g_client_id is sent back to server,
+				   so lets check that we actually got
+				   valid data from stream to prevent
+				   that we leak back data to server */
+				if (!s_check(s))
+				{
+					rdp_protocol_error("rdpdr_process(), consume of g_client_id from stream did overrun", &packet);
+				}
+
 				/* The RDP client is responsibility to provide a random client id
 				   if server version is < 12 */
 				if (vmin < 0x000c)


@@ -595,6 +595,7 @@ cssp_read_tsrequest(STREAM token, STREAM pubkey)
 	STREAM s;
 	int length;
 	int tagval;
+	struct stream packet;

 	s = tcp_recv(NULL, 4);

@@ -622,6 +623,7 @@ cssp_read_tsrequest(STREAM token, STREAM pubkey)

 	// receive the remainings of message
 	s = tcp_recv(s, length);
+	packet = *s;

 	// parse the response and into nego token
 	if (!ber_in_header(s, &tagval, &length) ||
@@ -632,6 +634,12 @@ cssp_read_tsrequest(STREAM token, STREAM pubkey)
 	if (!ber_in_header(s, &tagval, &length) ||
 	    tagval != (BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0))
 		return False;
+
+	if (!s_check_rem(s, length))
+	{
+		 rdp_protocol_error("cssp_read_tsrequest(), consume of version from stream would overrun",
+				    &packet);
+	}
 	in_uint8s(s, length);

 	// negoToken [1]
@@ -653,7 +661,14 @@ cssp_read_tsrequest(STREAM token, STREAM pubkey)
 		if (!ber_in_header(s, &tagval, &length) || tagval != BER_TAG_OCTET_STRING)
 			return False;

-		token->end = token->p = token->data;
+		if (!s_check_rem(s, length))
+		{
+			rdp_protocol_error("cssp_read_tsrequest(), consume of token from stream would overrun",
+					   &packet);
+		}
+
+		s_realloc(token, length);
+		s_reset(token);
 		out_uint8p(token, s->p, length);
 		s_mark_end(token);
 	}


@@ -54,7 +54,7 @@ size_t in_ansi_string(STREAM s, char *string, size_t len);
 #define s_pop_layer(s,h)	(s)->p = (s)->h;
 #define s_mark_end(s)		(s)->end = (s)->p;
 #define s_check(s)		((s)->p <= (s)->end)
-#define s_check_rem(s,n)	((s)->p + n <= (s)->end)
+#define s_check_rem(s,n) (s_check(s) && (n <= (s)->end - (s)->p))
 #define s_check_end(s)		((s)->p == (s)->end)
 #define s_length(s)		((s)->end - (s)->data)
 #define s_left(s)               ((s)->size - ((s)->p - (s)->data))


@@ -164,6 +164,7 @@ RD_BOOL rdp_connect(char *server, uint32 flags, char *domain, char *password, ch
 		    char *directory, RD_BOOL reconnect);
 void rdp_reset_state(void);
 void rdp_disconnect(void);
+void rdp_protocol_error(const char *message, STREAM s);
 /* rdpdr.c */
 int get_device_index(RD_NTHANDLE handle);
 void convert_to_unix_filename(char *filename);
@@ -224,7 +225,7 @@ void tcp_run_ui(RD_BOOL run);
 /* asn.c */
 RD_BOOL ber_in_header(STREAM s, int *tagval, int *length);
 void ber_out_header(STREAM s, int tagval, int length);
-RD_BOOL ber_parse_header(STREAM s, int tagval, int *length);
+RD_BOOL ber_parse_header(STREAM s, int tagval, uint32 *length);
 void ber_out_integer(STREAM s, int value);
 void ber_out_sequence(STREAM s, STREAM contents);


@@ -118,6 +118,7 @@ cliprdr_process(STREAM s)
 	uint16 type, status;
 	uint32 length, format;
 	uint8 *data;
+	struct stream packet = *s;

 	in_uint16_le(s, type);
 	in_uint16_le(s, status);

@@ -127,6 +128,11 @@ cliprdr_process(STREAM s)
 	logger(Clipboard, Debug, "cliprdr_process(), type=%d, status=%d, length=%d", type, status,
 	       length);

+	if (!s_check_rem(s, length))
+	{
+		rdp_protocol_error("cliprdr_process(), consume of packet from stream would overrun", &packet);
+	}
+
 	if (status == CLIPRDR_ERROR)
 	{
 		switch (type)


@@ -168,6 +168,12 @@ seamless_process_line(const char *line, void *data)

 			icon_buf[len] = strtol(byte, NULL, 16);
 			len++;
+
+			if ((size_t)len >= sizeof(icon_buf))
+			{
+				logger(Protocol, Warning, "seamless_process_line(), icon data would overrun icon_buf");
+				break;
+			}
 		}

 		ui_seamless_seticon(id, tok5, width, height, chunk, icon_buf, len);

@@ -370,6 +376,12 @@ seamless_process(STREAM s)
 {
 	unsigned int pkglen;
 	char *buf;
+	struct stream packet = *s;
+
+	if (!s_check(s))
+	{
+		rdp_protocol_error("seamless_process(), stream is in unstable state", &packet);
+	}

 	pkglen = s->end - s->p;
 	/* str_handle_lines requires null terminated strings */


@@ -45,9 +45,16 @@ mcs_out_domain_params(STREAM s, int max_channels, int max_users, int max_tokens,
 static RD_BOOL
 mcs_parse_domain_params(STREAM s)
 {
-	int length;
+	uint32 length;
+	struct stream packet = *s;

 	ber_parse_header(s, MCS_TAG_DOMAIN_PARAMS, &length);
+
+	if (!s_check_rem(s, length))
+	{
+		rdp_protocol_error("mcs_parse_domain_params(), consume domain params from stream would overrun", &packet);
+	}
+
 	in_uint8s(s, length);

 	return s_check(s);

@@ -89,8 +96,9 @@ mcs_recv_connect_response(STREAM mcs_data)
 {
 	UNUSED(mcs_data);
 	uint8 result;
-	int length;
+	uint32 length;
 	STREAM s;
+	struct stream packet;
 	RD_BOOL is_fastpath;
 	uint8 fastpath_hdr;

@@ -99,6 +107,8 @@ mcs_recv_connect_response(STREAM mcs_data)

 	if (s == NULL)
 		return False;
+
+	packet = *s;

 	ber_parse_header(s, MCS_CONNECT_RESPONSE, &length);

@@ -112,6 +122,12 @@ mcs_recv_connect_response(STREAM mcs_data)

 	ber_parse_header(s, BER_TAG_INTEGER, &length);
 	in_uint8s(s, length);	/* connect id */
+
+	if (!s_check_rem(s, length))
+	{
+		rdp_protocol_error("mcs_recv_connect_response(), consume connect id from stream would overrun", &packet);
+	}
+
 	mcs_parse_domain_params(s);

 	ber_parse_header(s, BER_TAG_OCTET_STRING, &length);


@@ -854,6 +854,7 @@ rdpdr_process(STREAM s)
 	uint16 vmin;
 	uint16 component;
 	uint16 pakid;
+	struct stream packet = *s;

 	logger(Protocol, Debug, "rdpdr_process()");
 	/* hexdump(s->p, s->end - s->p); */

@@ -873,8 +874,18 @@ rdpdr_process(STREAM s)
 				/* DR_CORE_SERVER_ANNOUNCE_REQ */
 				in_uint8s(s, 2);	/* skip versionMajor */
 				in_uint16_le(s, vmin);	/* VersionMinor */
+
 				in_uint32_le(s, g_client_id);	/* ClientID */

+				/* g_client_id is sent back to server,
+				   so lets check that we actually got
+				   valid data from stream to prevent
+				   that we leak back data to server */
+				if (!s_check(s))
+				{
+					rdp_protocol_error("rdpdr_process(), consume of g_client_id from stream did overrun", &packet);
+				}
+
 				/* The RDP client is responsibility to provide a random client id
 				   if server version is < 12 */
 				if (vmin < 0x000c)


@@ -595,6 +595,7 @@ cssp_read_tsrequest(STREAM token, STREAM pubkey)
 	STREAM s;
 	int length;
 	int tagval;
+	struct stream packet;

 	s = tcp_recv(NULL, 4);

@@ -622,6 +623,7 @@ cssp_read_tsrequest(STREAM token, STREAM pubkey)

 	// receive the remainings of message
 	s = tcp_recv(s, length);
+	packet = *s;

 	// parse the response and into nego token
 	if (!ber_in_header(s, &tagval, &length) ||

@@ -632,6 +634,12 @@ cssp_read_tsrequest(STREAM token, STREAM pubkey)
 	if (!ber_in_header(s, &tagval, &length) ||
 	    tagval != (BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0))
 		return False;
+
+	if (!s_check_rem(s, length))
+	{
+		 rdp_protocol_error("cssp_read_tsrequest(), consume of version from stream would overrun",
+				    &packet);
+	}
 	in_uint8s(s, length);

 	// negoToken [1]

@@ -653,7 +661,14 @@ cssp_read_tsrequest(STREAM token, STREAM pubkey)
 		if (!ber_in_header(s, &tagval, &length) || tagval != BER_TAG_OCTET_STRING)
 			return False;

-		token->end = token->p = token->data;
+		if (!s_check_rem(s, length))
+		{
+			rdp_protocol_error("cssp_read_tsrequest(), consume of token from stream would overrun",
+					   &packet);
+		}
+
+		s_realloc(token, length);
+		s_reset(token);
 		out_uint8p(token, s->p, length);
 		s_mark_end(token);
 	}


@@ -2204,7 +2204,7 @@ static int format8BIM(Image *ifile, Image *ofile)
         return -1;
       }
     /* make a buffer to hold the data and snag it from the input stream */
-    str=(unsigned char *) AcquireQuantumMemory((size_t) count,sizeof(*str));
+    str=(unsigned char *) AcquireQuantumMemory((size_t) count+1,sizeof(*str));
     if (str == (unsigned char *) NULL)
       {
         PString=(unsigned char *) RelinquishMagickMemory(PString);


Merge branch 'page-refs' (page ref overflow)

Merge page ref overflow branch.

Jann Horn reported that he can overflow the page ref count with
sufficient memory (and a filesystem that is intentionally extremely
slow).

Admittedly it's not exactly easy.  To have more than four billion
references to a page requires a minimum of 32GB of kernel memory just
for the pointers to the pages, much less any metadata to keep track of
those pointers.  Jann needed a total of 140GB of memory and a specially
crafted filesystem that leaves all reads pending (in order to not ever
free the page references and just keep adding more).

Still, we have a fairly straightforward way to limit the two obvious
user-controllable sources of page references: direct-IO like page
references gotten through get_user_pages(), and the splice pipe page
duplication.  So let's just do that.

* branch page-refs:
  fs: prevent page refcount overflow in pipe_buf_get
  mm: prevent get_user_pages() from overflowing page refcount
  mm: add 'try_get_page()' helper function
  mm: make page ref count overflow check tighter and more explicit

@@ -2056,10 +2056,8 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe,
 		rem += pipe->bufs[(pipe->curbuf + idx) & (pipe->buffers - 1)].len;

 	ret = -EINVAL;
-	if (rem < len) {
-		pipe_unlock(pipe);
-		goto out;
-	}
+	if (rem < len)
+		goto out_free;

 	rem = len;
 	while (rem) {
@@ -2077,7 +2075,9 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe,
 			pipe->curbuf = (pipe->curbuf + 1) & (pipe->buffers - 1);
 			pipe->nrbufs--;
 		} else {
-			pipe_buf_get(pipe, ibuf);
+			if (!pipe_buf_get(pipe, ibuf))
+				goto out_free;
+
 			*obuf = *ibuf;
 			obuf->flags &= ~PIPE_BUF_FLAG_GIFT;
 			obuf->len = rem;
@@ -2100,11 +2100,11 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe,
 	ret = fuse_dev_do_write(fud, &cs, len);

 	pipe_lock(pipe);
+out_free:
 	for (idx = 0; idx < nbuf; idx++)
 		pipe_buf_release(pipe, &bufs[idx]);
 	pipe_unlock(pipe);

-out:
 	kvfree(bufs);
 	return ret;
 }


fs: prevent page refcount overflow in pipe_buf_get

Change pipe_buf_get() to return a bool indicating whether it succeeded
in raising the refcount of the page (if the thing in the pipe is a page).
This removes another mechanism for overflowing the page refcount.  All
callers converted to handle a failure.

Reported-by: Jann Horn <jannh@google.com>
Signed-off-by: Matthew Wilcox <willy@infradead.org>
Cc: stable@kernel.org
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

@@ -189,9 +189,9 @@ EXPORT_SYMBOL(generic_pipe_buf_steal);
  *	in the tee() system call, when we duplicate the buffers in one
  *	pipe into another.
  */
-void generic_pipe_buf_get(struct pipe_inode_info *pipe, struct pipe_buffer *buf)
+bool generic_pipe_buf_get(struct pipe_inode_info *pipe, struct pipe_buffer *buf)
 {
-	get_page(buf->page);
+	return try_get_page(buf->page);
 }
 EXPORT_SYMBOL(generic_pipe_buf_get);


Bug 700938: Fix stack overflow in numtostr as used by Number#toFixed().

32 is not enough to fit sprintf("%.20f", 1e20).
We need at least 43 bytes to fit that format.
Bump the static buffer size.

@@ -27,7 +27,7 @@ static void Np_valueOf(js_State *J)

 static void Np_toString(js_State *J)
 {
-	char buf[32];
+	char buf[100];
 	js_Object *self = js_toobject(J, 0);
 	int radix = js_isundefined(J, 1) ? 10 : js_tointeger(J, 1);
 	if (self->type != JS_CNUMBER)
@@ -42,7 +42,6 @@ static void Np_toString(js_State *J)
 	/* lame number to string conversion for any radix from 2 to 36 */
 	{
 		static const char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
-		char buf[100];
 		double number = self->u.number;
 		int sign = self->u.number < 0;
 		js_Buffer *sb = NULL;
@@ -115,7 +114,8 @@ static void Np_toString(js_State *J)
 /* Customized ToString() on a number */
 static void numtostr(js_State *J, const char *fmt, int w, double n)
 {
-	char buf[32], *e;
+	/* buf needs to fit printf("%.20f", 1e20) */
+	char buf[50], *e;
 	sprintf(buf, fmt, w, n);
 	e = strchr(buf, 'e');
 	if (e) {


fix buffer overrun in gf_bin128_parse

closes #1204
closes #1205

@@ -1988,8 +1988,14 @@ GF_Err gf_bin128_parse(const char *string, bin128 value)
 				break;
 			sprintf(szV, "%c%c", string[j], string[j+1]);
 			sscanf(szV, "%x", &v);
+			if (i > 15) {
+				// force error check below
+				i++;
+				break;
+			}
 			value[i] = v;
 			i++;
+
 		}
 	}
 	if (i != 16) {


Merge pull request #12378 from rbalint/vt-kbd-reset-check

VT kbd reset check

@@ -1249,12 +1249,36 @@ int vt_default_utf8(void) {
         return parse_boolean(b);
 }

+int vt_verify_kbmode(int fd) {
+        int curr_mode;
+
+        /*
+         * Make sure we only adjust consoles in K_XLATE or K_UNICODE mode.
+         * Otherwise we would (likely) interfere with X11's processing of the
+         * key events.
+         *
+         * http://lists.freedesktop.org/archives/systemd-devel/2013-February/008573.html
+         */
+
+        if (ioctl(fd, KDGKBMODE, &curr_mode) < 0)
+                return -errno;
+
+        return IN_SET(curr_mode, K_XLATE, K_UNICODE) ? 0 : -EBUSY;
+}
+
 int vt_reset_keyboard(int fd) {
-        int kb;
+        int kb, r;

         /* If we can't read the default, then default to unicode. It's 2017 after all. */
         kb = vt_default_utf8() != 0 ? K_UNICODE : K_XLATE;

+        r = vt_verify_kbmode(fd);
+        if (r == -EBUSY) {
+                log_debug_errno(r, "Keyboard is not in XLATE or UNICODE mode, not resetting: %m");
+                return 0;
+        } else if (r < 0)
+                return r;
+
         if (ioctl(fd, KDSKBMODE, kb) < 0)
                 return -errno;


fix error from commit 13585f15c7f7dc28bbbba1661efb280d530d114c

@@ -1850,7 +1850,7 @@ GetOutboundPinholeTimeout(struct upnphttp * h, const char * action, const char *
 	rem_port = GetValueFromNameValueList(&data, "RemotePort");
 	protocol = GetValueFromNameValueList(&data, "Protocol");

-	if (!int_port || !ext_port || !protocol)
+	if (!int_port || !rem_port || !protocol)
 	{
 		ClearNameValueList(&data);
 		SoapError(h, 402, "Invalid Args");


ipmi_si: fix use-after-free of resource->name

When we excute the following commands, we got oops
rmmod ipmi_si
cat /proc/ioports

[ 1623.482380] Unable to handle kernel paging request at virtual address ffff00000901d478
[ 1623.482382] Mem abort info:
[ 1623.482383]   ESR = 0x96000007
[ 1623.482385]   Exception class = DABT (current EL), IL = 32 bits
[ 1623.482386]   SET = 0, FnV = 0
[ 1623.482387]   EA = 0, S1PTW = 0
[ 1623.482388] Data abort info:
[ 1623.482389]   ISV = 0, ISS = 0x00000007
[ 1623.482390]   CM = 0, WnR = 0
[ 1623.482393] swapper pgtable: 4k pages, 48-bit VAs, pgdp = 00000000d7d94a66
[ 1623.482395] [ffff00000901d478] pgd=000000dffbfff003, pud=000000dffbffe003, pmd=0000003f5d06e003, pte=0000000000000000
[ 1623.482399] Internal error: Oops: 96000007 [#1] SMP
[ 1623.487407] Modules linked in: ipmi_si(E) nls_utf8 isofs rpcrdma ib_iser ib_srpt target_core_mod ib_srp scsi_transport_srp ib_ipoib rdma_ucm ib_umad rdma_cm ib_cm dm_mirror dm_region_hash dm_log iw_cm dm_mod aes_ce_blk crypto_simd cryptd aes_ce_cipher ses ghash_ce sha2_ce enclosure sha256_arm64 sg sha1_ce hisi_sas_v2_hw hibmc_drm sbsa_gwdt hisi_sas_main ip_tables mlx5_ib ib_uverbs marvell ib_core mlx5_core ixgbe mdio hns_dsaf ipmi_devintf hns_enet_drv ipmi_msghandler hns_mdio [last unloaded: ipmi_si]
[ 1623.532410] CPU: 30 PID: 11438 Comm: cat Kdump: loaded Tainted: G            E     5.0.0-rc3+ #168
[ 1623.541498] Hardware name: Huawei TaiShan 2280 /BC11SPCD, BIOS 1.37 11/21/2017
[ 1623.548822] pstate: a0000005 (NzCv daif -PAN -UAO)
[ 1623.553684] pc : string+0x28/0x98
[ 1623.557040] lr : vsnprintf+0x368/0x5e8
[ 1623.560837] sp : ffff000013213a80
[ 1623.564191] x29: ffff000013213a80 x28: ffff00001138abb5
[ 1623.569577] x27: ffff000013213c18 x26: ffff805f67d06049
[ 1623.574963] x25: 0000000000000000 x24: ffff00001138abb5
[ 1623.580349] x23: 0000000000000fb7 x22: ffff0000117ed000
[ 1623.585734] x21: ffff000011188fd8 x20: ffff805f67d07000
[ 1623.591119] x19: ffff805f67d06061 x18: ffffffffffffffff
[ 1623.596505] x17: 0000000000000200 x16: 0000000000000000
[ 1623.601890] x15: ffff0000117ed748 x14: ffff805f67d07000
[ 1623.607276] x13: ffff805f67d0605e x12: 0000000000000000
[ 1623.612661] x11: 0000000000000000 x10: 0000000000000000
[ 1623.618046] x9 : 0000000000000000 x8 : 000000000000000f
[ 1623.623432] x7 : ffff805f67d06061 x6 : fffffffffffffffe
[ 1623.628817] x5 : 0000000000000012 x4 : ffff00000901d478
[ 1623.634203] x3 : ffff0a00ffffff04 x2 : ffff805f67d07000
[ 1623.639588] x1 : ffff805f67d07000 x0 : ffffffffffffffff
[ 1623.644974] Process cat (pid: 11438, stack limit = 0x000000008d4cbc10)
[ 1623.651592] Call trace:
[ 1623.654068]  string+0x28/0x98
[ 1623.657071]  vsnprintf+0x368/0x5e8
[ 1623.660517]  seq_vprintf+0x70/0x98
[ 1623.668009]  seq_printf+0x7c/0xa0
[ 1623.675530]  r_show+0xc8/0xf8
[ 1623.682558]  seq_read+0x330/0x440
[ 1623.689877]  proc_reg_read+0x78/0xd0
[ 1623.697346]  __vfs_read+0x60/0x1a0
[ 1623.704564]  vfs_read+0x94/0x150
[ 1623.711339]  ksys_read+0x6c/0xd8
[ 1623.717939]  __arm64_sys_read+0x24/0x30
[ 1623.725077]  el0_svc_common+0x120/0x148
[ 1623.732035]  el0_svc_handler+0x30/0x40
[ 1623.738757]  el0_svc+0x8/0xc
[ 1623.744520] Code: d1000406 aa0103e2 54000149 b4000080 (39400085)
[ 1623.753441] ---[ end trace f91b6a4937de9835 ]---
[ 1623.760871] Kernel panic - not syncing: Fatal exception
[ 1623.768935] SMP: stopping secondary CPUs
[ 1623.775718] Kernel Offset: disabled
[ 1623.781998] CPU features: 0x002,21006008
[ 1623.788777] Memory Limit: none
[ 1623.798329] Starting crashdump kernel...
[ 1623.805202] Bye!

If io_setup is called successful in try_smi_init() but try_smi_init()
goes out_err before calling ipmi_register_smi(), so ipmi_unregister_smi()
will not be called while removing module. It leads to the resource that
allocated in io_setup() can not be freed, but the name(DEVICE_NAME) of
resource is freed while removing the module. It causes use-after-free
when cat /proc/ioports.

Fix this by calling io_cleanup() while try_smi_init() goes to out_err.
and don't call io_cleanup() until io_setup() returns successful to avoid
warning prints.

Fixes: 93c303d2045b ("ipmi_si: Clean up shutdown a bit")
Cc: stable@vger.kernel.org
Reported-by: NuoHan Qiao <qiaonuohan@huawei.com>
Suggested-by: Corey Minyard <cminyard@mvista.com>
Signed-off-by: Yang Yingliang <yangyingliang@huawei.com>
Signed-off-by: Corey Minyard <cminyard@mvista.com>

@@ -68,8 +68,6 @@ int ipmi_si_port_setup(struct si_sm_io *io)
 	if (!addr)
 		return -ENODEV;

-	io->io_cleanup = port_cleanup;
-
 	/*
 	 * Figure out the actual inb/inw/inl/etc routine to use based
 	 * upon the register size.
@@ -109,5 +107,8 @@ int ipmi_si_port_setup(struct si_sm_io *io)
 			return -EIO;
 		}
 	}
+
+	io->io_cleanup = port_cleanup;
+
 	return 0;
 }


[trunk] fixed a buffer overflow in opj_tcd_init_decode_tile

Update issue 431

@@ -701,10 +701,11 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no,
 	/*fprintf(stderr, "Tile coordinate = %d,%d\n", p, q);*/

 	/* 4 borders of the tile rescale on the image if necessary */
-	l_tile->x0 = opj_int_max((OPJ_INT32)(l_cp->tx0 + p * l_cp->tdx), (OPJ_INT32)l_image->x0);
-	l_tile->y0 = opj_int_max((OPJ_INT32)(l_cp->ty0 + q * l_cp->tdy), (OPJ_INT32)l_image->y0);
-	l_tile->x1 = opj_int_min((OPJ_INT32)(l_cp->tx0 + (p + 1) * l_cp->tdx), (OPJ_INT32)l_image->x1);
-	l_tile->y1 = opj_int_min((OPJ_INT32)(l_cp->ty0 + (q + 1) * l_cp->tdy), (OPJ_INT32)l_image->y1);
+	l_tile->x0 = (OPJ_INT32)opj_uint_max(l_cp->tx0 + p * l_cp->tdx, l_image->x0);
+	l_tile->y0 = (OPJ_INT32)opj_uint_max(l_cp->ty0 + q * l_cp->tdy, l_image->y0);
+	l_tile->x1 = (OPJ_INT32)opj_uint_min(l_cp->tx0 + (p + 1) * l_cp->tdx, l_image->x1);
+	l_tile->y1 = (OPJ_INT32)opj_uint_min(l_cp->ty0 + (q + 1) * l_cp->tdy, l_image->y1);
+
 	/* testcase 1888.pdf.asan.35.988 */
 	if (l_tccp->numresolutions == 0) {
 		fprintf(stderr, "tiles require at least one resolution\n");


fixed vulnerabilities identified by red4sec.com (#4521)

@@ -60,7 +60,9 @@ char *url_decode_r(char *to, char *url, size_t size) {
     while(*s && d < e) {
         if(unlikely(*s == '%')) {
             if(likely(s[1] && s[2])) {
-                *d++ = from_hex(s[1]) << 4 | from_hex(s[2]);
+                char t = from_hex(s[1]) << 4 | from_hex(s[2]);
+                // avoid HTTP header injection
+                *d++ = (char)((isprint(t))? t : ' ');
                 s += 2;
             }
         }


  *) mod_http2: Configuration directoves H2Push and H2Upgrade can now be specified per
     Location/Directory, e.g. disabling PUSH for a specific set of resources. [Stefan Eissing]

  *) mod_http2: HEAD requests to some module such as mod_cgid caused the stream to
     terminate improperly and cause a HTTP/2 PROTOCOL_ERROR.
     Fixes <https://github.com/icing/mod_h2/issues/167>. [Michael Kaufmann]

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1852339 13f79535-47bb-0310-9956-ffa450edef68

@@ -53,33 +53,6 @@ typedef struct h2_push_res {
     int critical;
 } h2_push_res;

-/* Apache httpd module configuration for h2. */
-typedef struct h2_config {
-    const char *name;
-    int h2_max_streams;           /* max concurrent # streams (http2) */
-    int h2_window_size;           /* stream window size (http2) */
-    int min_workers;              /* min # of worker threads/child */
-    int max_workers;              /* max # of worker threads/child */
-    int max_worker_idle_secs;     /* max # of idle seconds for worker */
-    int stream_max_mem_size;      /* max # bytes held in memory/stream */
-    apr_array_header_t *alt_svcs; /* h2_alt_svc specs for this server */
-    int alt_svc_max_age;          /* seconds clients can rely on alt-svc info*/
-    int serialize_headers;        /* Use serialized HTTP/1.1 headers for
-                                     processing, better compatibility */
-    int h2_direct;                /* if mod_h2 is active directly */
-    int modern_tls_only;          /* Accept only modern TLS in HTTP/2 connections */
-    int h2_upgrade;               /* Allow HTTP/1 upgrade to h2/h2c */
-    apr_int64_t tls_warmup_size;  /* Amount of TLS data to send before going full write size */
-    int tls_cooldown_secs;        /* Seconds of idle time before going back to small TLS records */
-    int h2_push;                  /* if HTTP/2 server push is enabled */
-    struct apr_hash_t *priorities;/* map of content-type to h2_priority records */
-
-    int push_diary_size;          /* # of entries in push diary */
-    int copy_files;               /* if files shall be copied vs setaside on output */
-    apr_array_header_t *push_list;/* list of h2_push_res configurations */
-    int early_hints;              /* support status code 103 */
-} h2_config;
-

 void *h2_config_create_dir(apr_pool_t *pool, char *x);
 void *h2_config_merge_dir(apr_pool_t *pool, void *basev, void *addv);
@@ -88,19 +61,37 @@ void *h2_config_merge_svr(apr_pool_t *pool, void *basev, void *addv);

 extern const command_rec h2_cmds[];

-const h2_config *h2_config_get(conn_rec *c);
-const h2_config *h2_config_sget(server_rec *s);
-const h2_config *h2_config_rget(request_rec *r);
+int h2_config_geti(request_rec *r, server_rec *s, h2_config_var_t var);
+apr_int64_t h2_config_geti64(request_rec *r, server_rec *s, h2_config_var_t var);

-int h2_config_geti(const h2_config *conf, h2_config_var_t var);
-apr_int64_t h2_config_geti64(const h2_config *conf, h2_config_var_t var);
+/**
+ * Get the configured value for variable <var> at the given connection.
+ */
+int h2_config_cgeti(conn_rec *c, h2_config_var_t var);
+apr_int64_t h2_config_cgeti64(conn_rec *c, h2_config_var_t var);

-void h2_get_num_workers(server_rec *s, int *minw, int *maxw);
+/**
+ * Get the configured value for variable <var> at the given server.
+ */
+int h2_config_sgeti(server_rec *s, h2_config_var_t var);
+apr_int64_t h2_config_sgeti64(server_rec *s, h2_config_var_t var);

+/**
+ * Get the configured value for variable <var> at the given request,
+ * if configured for the request location.
+ * Fallback to request server config otherwise.
+ */
+int h2_config_rgeti(request_rec *r, h2_config_var_t var);
+apr_int64_t h2_config_rgeti64(request_rec *r, h2_config_var_t var);
+
+apr_array_header_t *h2_config_push_list(request_rec *r);
+apr_array_header_t *h2_config_alt_svcs(request_rec *r);
+
+
+void h2_get_num_workers(server_rec *s, int *minw, int *maxw);
 void h2_config_init(apr_pool_t *pool);

-const struct h2_priority *h2_config_get_priority(const h2_config *conf,
-                                                 const char *content_type);
+const struct h2_priority *h2_cconfig_get_priority(conn_rec *c, const char *content_type);

 #endif /* __mod_h2__h2_config_h__ */


@@ -57,23 +57,15 @@ void h2_h2_register_hooks(void);
  *    the handshake is still ongoing.
  * @return != 0 iff connection requirements are met
  */
-int h2_is_acceptable_connection(conn_rec *c, int require_all);
-
-/**
- * Check if the "direct" HTTP/2 mode of protocol handling is enabled
- * for the given connection.
- * @param c the connection to check
- * @return != 0 iff direct mode is enabled
- */
-int h2_allows_h2_direct(conn_rec *c);
+int h2_is_acceptable_connection(conn_rec *c, request_rec *r, int require_all);

 /**
  * Check if the "Upgrade" HTTP/1.1 mode of protocol switching is enabled
- * for the given connection.
- * @param c the connection to check
+ * for the given request.
+ * @param r the request to check
  * @return != 0 iff Upgrade switching is enabled
  */
-int h2_allows_h2_upgrade(conn_rec *c);
+int h2_allows_h2_upgrade(request_rec *r);

 #endif /* defined(__mod_h2__h2_h2__) */


@@ -236,7 +236,7 @@ static apr_status_t h2_filter_slave_in(ap_filter_t* f,
     apr_size_t rmax = ((readbytes <= APR_SIZE_MAX)?
                        (apr_size_t)readbytes : APR_SIZE_MAX);

-    task = h2_ctx_cget_task(f->c);
+    task = h2_ctx_get_task(f->c);
     ap_assert(task);

     if (trace1) {
@@ -379,7 +379,7 @@ static apr_status_t h2_filter_slave_in(ap_filter_t* f,
 static apr_status_t h2_filter_slave_output(ap_filter_t* filter,
                                            apr_bucket_brigade* brigade)
 {
-    h2_task *task = h2_ctx_cget_task(filter->c);
+    h2_task *task = h2_ctx_get_task(filter->c);
     apr_status_t status;

     ap_assert(task);
@@ -392,7 +392,7 @@ static apr_status_t h2_filter_slave_output(ap_filter_t* filter,

 static apr_status_t h2_filter_parse_h1(ap_filter_t* f, apr_bucket_brigade* bb)
 {
-    h2_task *task = h2_ctx_cget_task(f->c);
+    h2_task *task = h2_ctx_get_task(f->c);
     apr_status_t status;

     ap_assert(task);
@@ -502,7 +502,7 @@ static int h2_task_pre_conn(conn_rec* c, void *arg)

     ctx = h2_ctx_get(c, 0);
     (void)arg;
-    if (h2_ctx_is_task(ctx)) {
+    if (ctx->task) {
         ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c,
                       "h2_slave(%s), pre_connection, adding filters", c->log_id);
         ap_add_input_filter("H2_SLAVE_IN", NULL, NULL, c);
@@ -545,6 +545,7 @@ h2_task *h2_task_create(conn_rec *slave, int stream_id,
 void h2_task_destroy(h2_task *task)
 {
     if (task->output.beam) {
+        h2_beam_log(task->output.beam, task->c, APLOG_TRACE2, "task_destroy");
         h2_beam_destroy(task->output.beam);
         task->output.beam = NULL;
     }
@@ -724,7 +725,7 @@ static int h2_task_process_conn(conn_rec* c)
     }

     ctx = h2_ctx_get(c, 0);
-    if (h2_ctx_is_task(ctx)) {
+    if (ctx->task) {
         if (!ctx->task->request->serialize) {
             ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c,
                           "h2_h2, processing request directly");


Do not leak file descriptor when doing exec

When opening a custom debug file, the descriptor would stay
open when calling exec and leak to the child process.

Make sure all files are opened with close-on-exec.

This fixes CVE-2019-12210.

Thanks to Matthias Gerstner of the SUSE Security Team for reporting
the issue.

@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014-2018 Yubico AB - See COPYING
+ * Copyright (C) 2014-2019 Yubico AB - See COPYING
  */

 #include "util.h"
@@ -36,7 +36,7 @@ int get_devices_from_authfile(const char *authfile, const char *username,
   /* Ensure we never return uninitialized count. */
   *n_devs = 0;

-  fd = open(authfile, O_RDONLY, 0);
+  fd = open(authfile, O_RDONLY | O_CLOEXEC | O_NOCTTY);
   if (fd < 0) {
     if (verbose)
       D(debug_file, "Cannot open file: %s (%s)", authfile, strerror(errno));
@@ -83,6 +83,8 @@ int get_devices_from_authfile(const char *authfile, const char *username,
     if (verbose)
       D(debug_file, "fdopen: %s", strerror(errno));
     goto err;
+  } else {
+    fd = -1; /* fd belongs to opwfile */
   }

   buf = malloc(sizeof(char) * (DEVSIZE * max_devs));
@@ -211,8 +213,10 @@ int get_devices_from_authfile(const char *authfile, const char *username,

   if (opwfile)
     fclose(opwfile);
-  else if (fd >= 0)
+
+  if (fd != -1)
     close(fd);
+
   return retval;
 }


CVE: net: fix unbounded memcpy of UDP packet

This patch adds a check to udp_len to fix unbounded memcpy for
CVE-2019-14192, CVE-2019-14193 and CVE-2019-14199.

Signed-off-by: Cheng Liu <liucheng32@huawei.com>
Reviewed-by: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com>
Reported-by: Fermín Serna <fermin@semmle.com>
Acked-by: Joe Hershberger <joe.hershberger@ni.com>

@@ -1264,6 +1264,9 @@ void net_process_received_packet(uchar *in_packet, int len)
 			return;
 		}

+		if (ntohs(ip->udp_len) < UDP_HDR_SIZE || ntohs(ip->udp_len) > ntohs(ip->ip_len))
+			return;
+
 		debug_cond(DEBUG_DEV_PKT,
 			   "received UDP (to=%pI4, from=%pI4, len=%d)\n",
 			   &dst_ip, &src_ip, len);


mtd: spi-nor: Off by one in cqspi_setup_flash()

There are CQSPI_MAX_CHIPSELECT elements in the ->f_pdata array so the >
should be >=.

Fixes: 140623410536 ('mtd: spi-nor: Add driver for Cadence Quad SPI Flash Controller')
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Reviewed-by: Marek Vasut <marex@denx.de>
Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>

@@ -1082,7 +1082,7 @@ static int cqspi_setup_flash(struct cqspi_st *cqspi, struct device_node *np)
 			goto err;
 		}

-		if (cs > CQSPI_MAX_CHIPSELECT) {
+		if (cs >= CQSPI_MAX_CHIPSELECT) {
 			dev_err(dev, "Chip select %d out of range.\n", cs);
 			goto err;
 		}