db-d2/primevul-codebert-embeddings huggingface dataset:
Commit message: Fixed a GIF decoding bug (divide by zero)

Fixes issue #15
CVE: CVE-2017-7962
CWE: CWE-369
Vulnerability description: The iwgif_read_image function in imagew-gif.c in libimageworsener.a in ImageWorsener 1.3.0 allows remote attackers to cause a denial of service (divide-by-zero error and application crash) via a crafted file.

Project: imageworsener

IW_IMPL(int) iw_read_gif_file(struct iw_context *ctx, struct iw_iodescr *iodescr)
{
	struct iw_image img;
	struct iwgifrcontext *rctx = NULL;
	int retval=0;

	iw_zeromem(&img,sizeof(struct iw_image));
	rctx = iw_mallocz(ctx,sizeof(struct iwgifrcontext));
	if(!rctx) goto done;

	rctx->ctx = ctx;
	rctx->iodescr = iodescr;
	rctx->img = &img;

	iw_make_srgb_csdescr_2(&rctx->csdescr);

	rctx->page = iw_get_value(ctx,IW_VAL_PAGE_TO_READ);
	if(rctx->page<1) rctx->page = 1;

	rctx->include_screen = iw_get_value(ctx,IW_VAL_INCLUDE_SCREEN);

	if(!iwgif_read_main(rctx))
		goto done;

	iw_set_input_image(ctx, &img);

	iw_set_input_colorspace(ctx,&rctx->csdescr);

	retval = 1;

done:
	if(!retval) {
		iw_set_error(ctx,"Failed to read GIF file");
	}

	if(rctx) {
		if(rctx->row_pointers) iw_free(ctx,rctx->row_pointers);
		iw_free(ctx,rctx);
	}

	return retval;
}

Project: imageworsener

static int iwgif_read_extension(struct iwgifrcontext *rctx)
{
	int retval=0;
	iw_byte ext_type;

	if(!iwgif_read(rctx,rctx->rbuf,1)) goto done;
	ext_type=rctx->rbuf[0];

	switch(ext_type) {
	case 0xf9:
		if(rctx->page == rctx->pages_seen+1) {
			if(!iwgif_read_graphic_control_ext(rctx)) goto done;
		}
		else {
			if(!iwgif_skip_subblocks(rctx)) goto done;
		}
		break;
	default:
		if(!iwgif_skip_subblocks(rctx)) goto done;
	}

	retval=1;
done:
	return retval;
}

Project: imageworsener

static int iwgif_read_screen_descriptor(struct iwgifrcontext *rctx)
{
	int has_global_ct;
	int global_ct_size;
	int aspect_ratio_code;

	if(!iwgif_read(rctx,rctx->rbuf,7)) return 0;
	rctx->screen_width = (int)iw_get_ui16le(&rctx->rbuf[0]);
	rctx->screen_height = (int)iw_get_ui16le(&rctx->rbuf[2]);

	has_global_ct = (int)((rctx->rbuf[4]>>7)&0x01);

	if(has_global_ct) {
		global_ct_size = (int)(rctx->rbuf[4]&0x07);
		rctx->colortable.num_entries = 1<<(1+global_ct_size);

		rctx->bg_color_index = (int)rctx->rbuf[5];
		if(rctx->bg_color_index < rctx->colortable.num_entries)
			rctx->has_bg_color = 1;
	}

	aspect_ratio_code = (int)rctx->rbuf[6];
	if(aspect_ratio_code!=0) {
		rctx->img->density_code = IW_DENSITY_UNITS_UNKNOWN;
		rctx->img->density_x = 64000.0/(double)(aspect_ratio_code + 15);
		rctx->img->density_y = 1000.0;
	}

	return 1;
}

Project: imageworsener

static int iwgif_skip_subblocks(struct iwgifrcontext *rctx)
{
	iw_byte subblock_size;

	while(1) {
		if(!iwgif_read(rctx,rctx->rbuf,1)) return 0;

		subblock_size = rctx->rbuf[0];
		if(subblock_size==0) return 1;

		if(!iwgif_read(rctx,rctx->rbuf,(size_t)subblock_size)) return 0;
	}
}
Commit message: mm: Tighten x86 /dev/mem with zeroing reads

Under CONFIG_STRICT_DEVMEM, reading System RAM through /dev/mem is
disallowed. However, on x86, the first 1MB was always allowed for BIOS
and similar things, regardless of it actually being System RAM. It was
possible for heap to end up getting allocated in low 1MB RAM, and then
read by things like x86info or dd, which would trip hardened usercopy:

usercopy: kernel memory exposure attempt detected from ffff880000090000 (dma-kmalloc-256) (4096 bytes)

This changes the x86 exception for the low 1MB by reading back zeros for
System RAM areas instead of blindly allowing them. More work is needed to
extend this to mmap, but currently mmap doesn't go through usercopy, so
hardened usercopy won't Oops the kernel.

Reported-by: Tommi Rantala <tommi.t.rantala@nokia.com>
Tested-by: Tommi Rantala <tommi.t.rantala@nokia.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
CVE: CVE-2017-7889
CWE: CWE-732
Vulnerability description: The mm subsystem in the Linux kernel through 3.2 does not properly enforce the CONFIG_STRICT_DEVMEM protection mechanism, which allows local users to read or write to kernel memory locations in the first megabyte (and bypass slab-allocation access restrictions) via an application that opens the /dev/mem file, related to arch/x86/mm/init.c and drivers/char/mem.c.

Project: linux
File: init.c

unsigned long __ref init_memory_mapping(unsigned long start,
					       unsigned long end)
{
	struct map_range mr[NR_RANGE_MR];
	unsigned long ret = 0;
	int nr_range, i;

	pr_debug("init_memory_mapping: [mem %#010lx-%#010lx]\n",
	       start, end - 1);

	memset(mr, 0, sizeof(mr));
	nr_range = split_mem_range(mr, 0, start, end);

	for (i = 0; i < nr_range; i++)
		ret = kernel_physical_mapping_init(mr[i].start, mr[i].end,
						   mr[i].page_size_mask);

	add_pfn_range_mapped(start >> PAGE_SHIFT, ret >> PAGE_SHIFT);

	return ret >> PAGE_SHIFT;
}

Project: linux
File: init.c

static int __meminit save_mr(struct map_range *mr, int nr_range,
			     unsigned long start_pfn, unsigned long end_pfn,
			     unsigned long page_size_mask)
{
	if (start_pfn < end_pfn) {
		if (nr_range >= NR_RANGE_MR)
			panic("run out of range for init_memory_mapping\n");
		mr[nr_range].start = start_pfn<<PAGE_SHIFT;
		mr[nr_range].end   = end_pfn<<PAGE_SHIFT;
		mr[nr_range].page_size_mask = page_size_mask;
		nr_range++;
	}

	return nr_range;
}

Project: linux
File: mem.c

static int open_port(struct inode *inode, struct file *filp)
{
	return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
}

Project: linux
File: mem.c

static ssize_t splice_write_null(struct pipe_inode_info *pipe, struct file *out,
				 loff_t *ppos, size_t len, unsigned int flags)
{
	return splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_null);
}

Project: linux
File: mem.c

static ssize_t write_iter_null(struct kiocb *iocb, struct iov_iter *from)
{
	size_t count = iov_iter_count(from);
	iov_iter_advance(from, count);
	return count;
}
Commit message: avcodec/pngdec: Fix off by 1 size in decode_zbuf()

Fixes out of array access
Fixes: 444/fuzz-2-ffmpeg_VIDEO_AV_CODEC_ID_PNG_fuzzer

Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/targets/ffmpeg
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
CVE: CVE-2017-7866
CWE: CWE-787
Vulnerability description: FFmpeg before 2017-01-23 has an out-of-bounds write caused by a stack-based buffer overflow related to the decode_zbuf function in libavcodec/pngdec.c.

Project: FFmpeg
File: pngdec.c

static int png_decode_idat(PNGDecContext *s, int length)
{
    int ret;
    s->zstream.avail_in = FFMIN(length, bytestream2_get_bytes_left(&s->gb));
    s->zstream.next_in  = (unsigned char *)s->gb.buffer;
    bytestream2_skip(&s->gb, length);

    /* decode one line if possible */
    while (s->zstream.avail_in > 0) {
        ret = inflate(&s->zstream, Z_PARTIAL_FLUSH);
        if (ret != Z_OK && ret != Z_STREAM_END) {
            av_log(s->avctx, AV_LOG_ERROR, "inflate returned error %d\n", ret);
            return AVERROR_EXTERNAL;
        }
        if (s->zstream.avail_out == 0) {
            if (!(s->state & PNG_ALLIMAGE)) {
                png_handle_row(s);
            }
            s->zstream.avail_out = s->crow_size;
            s->zstream.next_out  = s->crow_buf;
        }
        if (ret == Z_STREAM_END && s->zstream.avail_in > 0) {
            av_log(NULL, AV_LOG_WARNING,
                   "%d undecompressed bytes left in buffer\n", s->zstream.avail_in);
            return 0;
        }
    }
    return 0;
}
Commit message: Fix crash in fuzzed wasm r2_hoobr_consume_init_expr
CVE: CVE-2017-7854
CWE: CWE-125
Vulnerability description: The consume_init_expr function in wasm.c in radare2 1.3.0 allows remote attackers to cause a denial of service (heap-based buffer over-read and application crash) via a crafted Web Assembly file.

Project: radare2

RList *r_bin_wasm_get_elements (RBinWasmObj *bin) {
	RBinWasmSection *element = NULL;
	RList *elements = NULL;

	if (!bin || !bin->g_sections) {
		return NULL;
	}

	if (bin->g_elements) {
		return bin->g_elements;
	}

	if (!(elements = r_bin_wasm_get_sections_by_id (bin->g_sections,
						R_BIN_WASM_SECTION_ELEMENT))) {
		return r_list_new();
	}

	if (!(element = (RBinWasmSection*) r_list_first (elements))) {
		return r_list_new();
	}

	bin->g_elements = r_bin_wasm_get_element_entries (bin, element);

	return bin->g_elements;
}

Project: radare2

RList *r_bin_wasm_get_globals (RBinWasmObj *bin) {
	RBinWasmSection *global = NULL;
	RList *globals = NULL;

	if (!bin || !bin->g_sections) {
		return NULL;
	}

	if (bin->g_globals) {
		return bin->g_globals;
	}

	if (!(globals = r_bin_wasm_get_sections_by_id (bin->g_sections,
						R_BIN_WASM_SECTION_GLOBAL))) {
		return r_list_new();
	}

	if (!(global = (RBinWasmSection*) r_list_first (globals))) {
		return r_list_new();
	}

	bin->g_globals = r_bin_wasm_get_global_entries (bin, global);

	return bin->g_globals;
}
Commit message: src/flac.c: Improve error handling

Especially when dealing with corrupt or malicious files.
CVE: CVE-2017-7585
CWE: CWE-119
Vulnerability description: In libsndfile before 1.0.28, an error in the "flac_buffer_copy()" function (flac.c) can be exploited to cause a stack-based buffer overflow via a specially crafted FLAC file.

Project: libsndfile
File: flac.c

f2flac24_array (const float *src, int32_t *dest, int count, int normalize)
{	float normfact = normalize ? (1.0 * 0x7FFFFF) : 1.0 ;

	while (--count >= 0)
		dest [count] = lrintf (src [count] * normfact) ;
} /* f2flac24_array */

Project: libsndfile
File: flac.c

flac_write_i2flac (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
{	FLAC_PRIVATE* pflac = (FLAC_PRIVATE*) psf->codec_data ;
	void (*convert) (const int *, int32_t *, int) ;
	int bufferlen, writecount, thiswrite ;
	sf_count_t	total = 0 ;
	int32_t* buffer = pflac->encbuffer ;

	switch (SF_CODEC (psf->sf.format))
	{	case SF_FORMAT_PCM_S8 :
			convert = i2flac8_array ;
			break ;
		case SF_FORMAT_PCM_16 :
			convert = i2flac16_array ;
			break ;
		case SF_FORMAT_PCM_24 :
			convert = i2flac24_array ;
			break ;
		default :
			return -1 ;
		} ;

	bufferlen = ENC_BUFFER_SIZE / (sizeof (int32_t) * psf->sf.channels) ;
	bufferlen *= psf->sf.channels ;

	while (len > 0)
	{	writecount = (len >= bufferlen) ? bufferlen : (int) len ;
		convert (ptr + total, buffer, writecount) ;
		if (FLAC__stream_encoder_process_interleaved (pflac->fse, buffer, writecount / psf->sf.channels))
			thiswrite = writecount ;
		else
			break ;
		total += thiswrite ;
		if (thiswrite < writecount)
			break ;

		len -= thiswrite ;
		} ;

	return total ;
} /* flac_write_i2flac */

Project: libsndfile
File: flac.c

i2flac24_array (const int *src, int32_t *dest, int count)
{	while (--count >= 0)
		dest [count] = src [count] >> 8 ;
} /* i2flac24_array */

Project: libsndfile
File: flac.c

sf_flac_meta_get_vorbiscomments (SF_PRIVATE *psf, const FLAC__StreamMetadata *metadata)
{	static FLAC_TAG tags [] =
	{ 	{ "title", SF_STR_TITLE },
		{ "copyright", SF_STR_COPYRIGHT },
		{ "software", SF_STR_SOFTWARE },
		{ "artist", SF_STR_ARTIST },
		{ "comment", SF_STR_COMMENT },
		{ "date", SF_STR_DATE },
		{ "album", SF_STR_ALBUM },
		{ "license", SF_STR_LICENSE },
		{ "tracknumber", SF_STR_TRACKNUMBER },
		{ "genre", SF_STR_GENRE }
		} ;

	const char *value, *cptr ;
	int k, tag_num ;

	for (k = 0 ; k < ARRAY_LEN (tags) ; k++)
	{	tag_num = FLAC__metadata_object_vorbiscomment_find_entry_from (metadata, 0, tags [k].tag) ;

		if (tag_num < 0)
			continue ;

		value = (const char*) metadata->data.vorbis_comment.comments [tag_num].entry ;
		if ((cptr = strchr (value, '=')) != NULL)
			value = cptr + 1 ;

		psf_log_printf (psf, "  %-12s : %s\n", tags [k].tag, value) ;
		psf_store_string (psf, tags [k].type, value) ;
		} ;

	return ;
} /* sf_flac_meta_get_vorbiscomments */
Commit message: nfsd: check for oversized NFSv2/v3 arguments

A client can append random data to the end of an NFSv2 or NFSv3 RPC call
without our complaining; we'll just stop parsing at the end of the
expected data and ignore the rest.

Encoded arguments and replies are stored together in an array of pages,
and if a call is too large it could leave inadequate space for the
reply.  This is normally OK because NFS RPC's typically have either
short arguments and long replies (like READ) or long arguments and short
replies (like WRITE).  But a client that sends an incorrectly long reply
can violate those assumptions.  This was observed to cause crashes.

Also, several operations increment rq_next_page in the decode routine
before checking the argument size, which can leave rq_next_page pointing
well past the end of the page array, causing trouble later in
svc_free_pages.

So, following a suggestion from Neil Brown, add a central check to
enforce our expectation that no NFSv2/v3 call has both a large call and
a large reply.

As followup we may also want to rewrite the encoding routines to check
more carefully that they aren't running off the end of the page array.

We may also consider rejecting calls that have any extra garbage
appended.  That would be safer, and within our rights by spec, but given
the age of our server and the NFS protocol, and the fact that we've
never enforced this before, we may need to balance that against the
possibility of breaking some oddball client.

Reported-by: Tuomas Haanpää <thaan@synopsys.com>
Reported-by: Ari Kauppi <ari@synopsys.com>
Cc: stable@vger.kernel.org
Reviewed-by: NeilBrown <neilb@suse.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
CVE: CVE-2017-7645
CWE: CWE-20
Vulnerability description: The NFSv2/NFSv3 server in the nfsd subsystem in the Linux kernel through 4.10.11 allows remote attackers to cause a denial of service (system crash) via a long RPC reply, related to net/sunrpc/svc.c, fs/nfsd/nfs3xdr.c, and fs/nfsd/nfsxdr.c.

Project: linux
File: nfssvc.c

static __be32 map_new_errors(u32 vers, __be32 nfserr)
{
	if (nfserr == nfserr_jukebox && vers == 2)
		return nfserr_dropit;
	if (nfserr == nfserr_wrongsec && vers < 4)
		return nfserr_acces;
 	return nfserr;
 }

Project: linux
File: nfssvc.c

static int nfsd_get_default_max_blksize(void)
{
	struct sysinfo i;
	unsigned long long target;
	unsigned long ret;

	si_meminfo(&i);
	target = (i.totalram - i.totalhigh) << PAGE_SHIFT;
	/*
	 * Aim for 1/4096 of memory per thread This gives 1MB on 4Gig
	 * machines, but only uses 32K on 128M machines.  Bottom out at
	 * 8K on 32M and smaller.  Of course, this is only a default.
	 */
	target >>= 12;

	ret = NFSSVC_MAXBLKSIZE;
	while (ret > target && ret >= 8*1024*2)
		ret /= 2;
	return ret;
}

Project: linux
File: nfssvc.c

static bool nfsd_needs_lockd(void)
{
#if defined(CONFIG_NFSD_V3)
	return (nfsd_versions[2] != NULL) || (nfsd_versions[3] != NULL);
#else
	return (nfsd_versions[2] != NULL);
#endif
}
Commit message: Fix #7152 - Null deref in cms
CVE: CVE-2017-7274
CWE: CWE-476
Vulnerability description: The r_pkcs7_parse_cms function in libr/util/r_pkcs7.c in radare2 1.3.0 allows remote attackers to cause a denial of service (NULL pointer dereference and application crash) via a crafted PE file.

Project: radare2
File: r_pkcs7.c

char* r_pkcs7_signerinfos_dump (RX509CertificateRevocationList *crl, char* buffer, ut32 length, const char* pad) {
	RASN1String *algo = NULL, *last = NULL, *next = NULL;
	ut32 i, p;
	int r;
	char *tmp, *pad2, *pad3;
	if (!crl || !buffer || !length) {
		return NULL;
	}
	if (!pad) {
		pad = "";
	}
	pad3 = r_str_newf ("%s    ", pad);
	if (!pad3) return NULL;

	pad2 = pad3 + 2;
	algo = crl->signature.algorithm;
	last = crl->lastUpdate;
	next = crl->nextUpdate;
	r = snprintf (buffer, length, "%sCRL:\n%sSignature:\n%s%s\n%sIssuer\n",
				pad, pad2, pad3, algo ? algo->string : "", pad2);
	p = (ut32) r;
	if (r < 0 || !(tmp = r_x509_name_dump (&crl->issuer, buffer + p, length - p, pad3))) {
		free (pad3);
		return NULL;
	}
	p = tmp - buffer;
	if (length <= p) {
		free (pad3);
		return NULL;
	}
	r = snprintf (buffer + p, length - p, "%sLast Update: %s\n%sNext Update: %s\n%sRevoked Certificates:\n",
				pad2, last ? last->string : "Missing",
				pad2, next ? next->string : "Missing", pad2);
	p += (ut32) r;
	if (r < 0) {
		free (pad3);
		return NULL;
	}
	for (i = 0; i < crl->length; ++i) {
		if (length <= p || !(tmp = r_x509_crlentry_dump (crl->revokedCertificates[i], buffer + p, length - p, pad3))) {
			free (pad3);
			return NULL;
		}
		p = tmp - buffer;
	}

	free (pad3);
	return buffer + p;
}
Commit message: HID: hid-cypress: validate length of report

Make sure we have enough of a report structure to validate before
looking at it.

Reported-by: Benoit Camredon <benoit.camredon@airbus.com>
Tested-by: Benoit Camredon <benoit.camredon@airbus.com>
Cc: stable <stable@vger.kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
CVE: CVE-2017-7273
CWE: CWE-703
Vulnerability description: The cp_report_fixup function in drivers/hid/hid-cypress.c in the Linux kernel 3.2 and 4.x before 4.9.4 allows physically proximate attackers to cause a denial of service (integer underflow) or possibly have unspecified other impact via a crafted HID report.

Project: linux
File: hid-cypress.c

static int cp_event(struct hid_device *hdev, struct hid_field *field,
		struct hid_usage *usage, __s32 value)
{
	unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);

	if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput ||
			!usage->type || !(quirks & CP_2WHEEL_MOUSE_HACK))
		return 0;

	if (usage->hid == 0x00090005) {
		if (value)
			quirks |=  CP_2WHEEL_MOUSE_HACK_ON;
		else
			quirks &= ~CP_2WHEEL_MOUSE_HACK_ON;
		hid_set_drvdata(hdev, (void *)quirks);
		return 1;
	}

	if (usage->code == REL_WHEEL && (quirks & CP_2WHEEL_MOUSE_HACK_ON)) {
		struct input_dev *input = field->hidinput->input;

		input_event(input, usage->type, REL_HWHEEL, value);
		return 1;
	}

	return 0;
}
Commit message: Detect invalid port in xp_socket parse ip address

For historical reasons, fsockopen() accepts the port and hostname
separately: fsockopen('127.0.0.1', 80)

However, with the introdcution of stream transports in PHP 4.3,
it became possible to include the port in the hostname specifier:

fsockopen('127.0.0.1:80')
Or more formally: fsockopen('tcp://127.0.0.1:80')

Confusing results when these two forms are combined, however.
fsockopen('127.0.0.1:80', 443) results in fsockopen() attempting
to connect to '127.0.0.1:80:443' which any reasonable stack would
consider invalid.

Unfortunately, PHP parses the address looking for the first colon
(with special handling for IPv6, don't worry) and calls atoi()
from there.  atoi() in turn, simply stops parsing at the first
non-numeric character and returns the value so far.

The end result is that the explicitly supplied port is treated
as ignored garbage, rather than producing an error.

This diff replaces atoi() with strtol() and inspects the
stop character.  If additional "garbage" of any kind is found,
it fails and returns an error.
CVE: CVE-2017-7189
CWE: CWE-918
Vulnerability description: main/streams/xp_socket.c in PHP 7.x before 2017-03-07 misparses fsockopen calls, such as by interpreting fsockopen('127.0.0.1:80', 443) as if the address/port were 127.0.0.1:80:443, which is later truncated to 127.0.0.1:80. This behavior has a security risk if the explicitly provided port number (i.e., 443 in this example) is hardcoded into an application as a security policy, but the hostname argument (i.e., 127.0.0.1:80 in this example) is obtained from untrusted input.

Project: php-src
File: xp_socket.c

static int php_sockop_close(php_stream *stream, int close_handle)
{
	php_netstream_data_t *sock = (php_netstream_data_t*)stream->abstract;
#ifdef PHP_WIN32
	int n;
#endif

	if (!sock) {
		return 0;
	}

	if (close_handle) {

#ifdef PHP_WIN32
		if (sock->socket == -1)
			sock->socket = SOCK_ERR;
#endif
		if (sock->socket != SOCK_ERR) {
#ifdef PHP_WIN32
			/* prevent more data from coming in */
			shutdown(sock->socket, SHUT_RD);

			/* try to make sure that the OS sends all data before we close the connection.
			 * Essentially, we are waiting for the socket to become writeable, which means
			 * that all pending data has been sent.
			 * We use a small timeout which should encourage the OS to send the data,
			 * but at the same time avoid hanging indefinitely.
			 * */
			do {
				n = php_pollfd_for_ms(sock->socket, POLLOUT, 500);
			} while (n == -1 && php_socket_errno() == EINTR);
#endif
			closesocket(sock->socket);
			sock->socket = SOCK_ERR;
		}

	}

	pefree(sock, php_stream_is_persistent(stream));

	return 0;
}

Project: php-src
File: xp_socket.c

static int php_sockop_stat(php_stream *stream, php_stream_statbuf *ssb)
{
#if ZEND_WIN32
	return 0;
#else
	php_netstream_data_t *sock = (php_netstream_data_t*)stream->abstract;

	return zend_fstat(sock->socket, &ssb->sb);
#endif
}
Commit message: xfrm_user: validate XFRM_MSG_NEWAE incoming ESN size harder

Kees Cook has pointed out that xfrm_replay_state_esn_len() is subject to
wrapping issues.  To ensure we are correctly ensuring that the two ESN
structures are the same size compare both the overall size as reported
by xfrm_replay_state_esn_len() and the internal length are the same.

CVE-2017-7184
Signed-off-by: Andy Whitcroft <apw@canonical.com>
Acked-by: Steffen Klassert <steffen.klassert@secunet.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
CVE: CVE-2017-7184
CWE: CWE-284
Vulnerability description: The xfrm_replay_verify_len function in net/xfrm/xfrm_user.c in the Linux kernel through 4.10.6 does not validate certain size data after an XFRM_MSG_NEWAE update, which allows local users to obtain root privileges or cause a denial of service (heap-based out-of-bounds access) by leveraging the CAP_NET_ADMIN capability, as demonstrated during a Pwn2Own competition at CanSecWest 2017 for the Ubuntu 16.10 linux-image-* package 4.8.0.41.52.

Project: linux
File: xfrm_user.c

static int copy_to_user_state_extra(struct xfrm_state *x,
				    struct xfrm_usersa_info *p,
				    struct sk_buff *skb)
{
	int ret = 0;

	copy_to_user_state(x, p);

	if (x->props.extra_flags) {
		ret = nla_put_u32(skb, XFRMA_SA_EXTRA_FLAGS,
				  x->props.extra_flags);
		if (ret)
			goto out;
	}

	if (x->coaddr) {
		ret = nla_put(skb, XFRMA_COADDR, sizeof(*x->coaddr), x->coaddr);
		if (ret)
			goto out;
	}
	if (x->lastused) {
		ret = nla_put_u64_64bit(skb, XFRMA_LASTUSED, x->lastused,
					XFRMA_PAD);
		if (ret)
			goto out;
	}
	if (x->aead) {
		ret = nla_put(skb, XFRMA_ALG_AEAD, aead_len(x->aead), x->aead);
		if (ret)
			goto out;
	}
	if (x->aalg) {
		ret = copy_to_user_auth(x->aalg, skb);
		if (!ret)
			ret = nla_put(skb, XFRMA_ALG_AUTH_TRUNC,
				      xfrm_alg_auth_len(x->aalg), x->aalg);
		if (ret)
			goto out;
	}
	if (x->ealg) {
		ret = nla_put(skb, XFRMA_ALG_CRYPT, xfrm_alg_len(x->ealg), x->ealg);
		if (ret)
			goto out;
	}
	if (x->calg) {
		ret = nla_put(skb, XFRMA_ALG_COMP, sizeof(*(x->calg)), x->calg);
		if (ret)
			goto out;
	}
	if (x->encap) {
		ret = nla_put(skb, XFRMA_ENCAP, sizeof(*x->encap), x->encap);
		if (ret)
			goto out;
	}
	if (x->tfcpad) {
		ret = nla_put_u32(skb, XFRMA_TFCPAD, x->tfcpad);
		if (ret)
			goto out;
	}
	ret = xfrm_mark_put(skb, &x->mark);
	if (ret)
		goto out;
	if (x->replay_esn)
		ret = nla_put(skb, XFRMA_REPLAY_ESN_VAL,
			      xfrm_replay_state_esn_len(x->replay_esn),
			      x->replay_esn);
	else
		ret = nla_put(skb, XFRMA_REPLAY_VAL, sizeof(x->replay),
			      &x->replay);
	if (ret)
		goto out;
	if (x->security)
		ret = copy_sec_ctx(x->security, skb);
out:
	return ret;
}