db-d2/primevul-codebert-embeddings huggingface dataset:
Commit message: tpm2: rev155: Add new RsaAdjustPrimeCandidate code but do not use

Add in the new RsaAdjustPrimeCandidate() function but do not use it
so far since it creates slightly different primes than the previous
code and we would get different derived keys if we were to use it with
'old' seeds.

Adjust the code to return the same results for 64 bit and 32 bit machines.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
CVE: CVE-2021-3505
CWE: CWE-331
Vulnerability description: A flaw was found in libtpms in versions before 0.8.0. The TPM 2 implementation returns 2048 bit keys with ~1984 bit strength due to a bug in the TCG specification. The bug is in the key creation algorithm in RsaAdjustPrimeCandidate(), which is called before the prime number check. The highest threat from this vulnerability is to data confidentiality.

Project: libtpms
File: CryptPrime.c

RsaAdjustPrimeCandidate(
			bigNum          prime
			)
{
    UINT16  highBytes;
    crypt_uword_t       *msw = &prime->d[prime->size - 1];
#define MASK (MAX_CRYPT_UWORD >> (RADIX_BITS - 16))
    highBytes = *msw >> (RADIX_BITS - 16);
    // This is fixed point arithmetic on 16-bit values
    highBytes = ((UINT32)highBytes * (UINT32)0x4AFB) >> 16;
    highBytes += 0xB505;
    *msw = ((crypt_uword_t)(highBytes) << (RADIX_BITS - 16)) + (*msw & MASK);
    prime->d[0] |= 1;
}
Commit message: net: qrtr: fix memort leak in qrtr_tun_write_iter

In qrtr_tun_write_iter the allocated kbuf should be release in case of
error or success return.

v2 Update: Thanks to David Miller for pointing out the release on success
path as well.

Signed-off-by: Navid Emamdoost <navid.emamdoost@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
CVE: CVE-2019-19079
CWE: CWE-703
Vulnerability description: A memory leak in the qrtr_tun_write_iter() function in net/qrtr/tun.c in the Linux kernel before 5.3 allows attackers to cause a denial of service (memory consumption), aka CID-a21b7f0cff19.

Project: linux
File: tun.c

static ssize_t qrtr_tun_write_iter(struct kiocb *iocb, struct iov_iter *from)
{
	struct file *filp = iocb->ki_filp;
	struct qrtr_tun *tun = filp->private_data;
	size_t len = iov_iter_count(from);
	ssize_t ret;
	void *kbuf;

	kbuf = kzalloc(len, GFP_KERNEL);
	if (!kbuf)
		return -ENOMEM;

	if (!copy_from_iter_full(kbuf, len, from))
		return -EFAULT;

	ret = qrtr_endpoint_post(&tun->ep, kbuf, len);

	return ret < 0 ? ret : len;
}
Commit message: ext4: always verify the magic number in xattr blocks

If there an inode points to a block which is also some other type of
metadata block (such as a block allocation bitmap), the
buffer_verified flag can be set when it was validated as that other
metadata block type; however, it would make a really terrible external
attribute block.  The reason why we use the verified flag is to avoid
constantly reverifying the block.  However, it doesn't take much
overhead to make sure the magic number of the xattr block is correct,
and this will avoid potential crashes.

This addresses CVE-2018-10879.

https://bugzilla.kernel.org/show_bug.cgi?id=200001

Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Reviewed-by: Andreas Dilger <adilger@dilger.ca>
Cc: stable@kernel.org
CVE: CVE-2018-10879
CWE: CWE-416
Vulnerability description: A flaw was found in the Linux kernel's ext4 filesystem. A local user can cause a use-after-free in ext4_xattr_set_entry function and a denial of service or unspecified other impact may occur by renaming a file in a crafted ext4 filesystem image.

Project: linux
File: xattr.c

__ext4_xattr_check_block(struct inode *inode, struct buffer_head *bh,
			 const char *function, unsigned int line)
{
	int error = -EFSCORRUPTED;

	if (buffer_verified(bh))
		return 0;

	if (BHDR(bh)->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC) ||
	    BHDR(bh)->h_blocks != cpu_to_le32(1))
		goto errout;
	error = -EFSBADCRC;
	if (!ext4_xattr_block_csum_verify(inode, bh))
		goto errout;
	error = ext4_xattr_check_entries(BFIRST(bh), bh->b_data + bh->b_size,
					 bh->b_data);
errout:
	if (error)
		__ext4_error_inode(inode, function, line, 0,
				   "corrupted xattr block %llu",
				   (unsigned long long) bh->b_blocknr);
	else
		set_buffer_verified(bh);
	return error;
}
Commit message: mumble: fix Mumble-SA-2014-001 (CVE-2014-0044).
CVE: CVE-2014-0044
CWE: CWE-119
Vulnerability description: The opus_packet_get_samples_per_frame function in client in Mumble 1.2.4 and the 1.2.3 pre-release snapshots allows remote attackers to cause a denial of service (crash) via a crafted length prefix value, which triggers a NULL pointer dereference or a heap-based buffer over-read (aka "out-of-bounds array access").

Project: mumble
File: AudioOutputSpeech.cpp

void AudioOutputSpeech::addFrameToBuffer(const QByteArray &qbaPacket, unsigned int iSeq) {
	QMutexLocker lock(&qmJitter);

	if (qbaPacket.size() < 2)
		return;

	PacketDataStream pds(qbaPacket);

	// skip flags
	pds.next();

	int samples = 0;
	if (umtType == MessageHandler::UDPVoiceOpus) {
		int size;
		pds >> size;
		size &= 0x1fff;

		const QByteArray &qba = pds.dataBlock(size);
		const unsigned char *packet = reinterpret_cast<const unsigned char*>(qba.constData());

#ifdef USE_OPUS
		int frames = opus_packet_get_nb_frames(packet, size);
		samples = frames * opus_packet_get_samples_per_frame(packet, SAMPLE_RATE);
#else
		return;
#endif

		// We can't handle frames which are not a multiple of 10ms.
		Q_ASSERT(samples % iFrameSize == 0);
	} else {
		unsigned int header = 0;

		do {
			header = static_cast<unsigned char>(pds.next());
			samples += iFrameSize;
			pds.skip(header & 0x7f);
		} while ((header & 0x80) && pds.isValid());
	}

	if (pds.isValid()) {
		JitterBufferPacket jbp;
		jbp.data = const_cast<char *>(qbaPacket.constData());
		jbp.len = qbaPacket.size();
		jbp.span = samples;
		jbp.timestamp = iFrameSize * iSeq;

#ifdef REPORT_JITTER
		if (g.s.bUsage && (umtType != MessageHandler::UDPVoiceSpeex) && p && ! p->qsHash.isEmpty() && (p->qlTiming.count() < 3000)) {
			QMutexLocker qml(& p->qmTiming);

			ClientUser::JitterRecord jr;
			jr.iSequence = iSeq;
			jr.iFrames = frames;
			jr.uiElapsed = p->tTiming.restart();

			if (! p->qlTiming.isEmpty()) {
				jr.iFrames -= p->iFrames;
				jr.iSequence -= p->iSequence + p->iFrames;
			}
			p->iFrames = frames;
			p->iSequence = iSeq;

			p->qlTiming.append(jr);
		}
#endif

		jitter_buffer_put(jbJitter, &jbp);
	}
}
Commit message: Map.c overflow fixes
CVE: CVE-2016-9189
CWE: CWE-190
Vulnerability description: Pillow before 3.3.2 allows context-dependent attackers to obtain sensitive information by using the "crafted image file" approach, related to an "Integer Overflow" issue affecting the Image.core.map_buffer in map.c component.

Project: Pillow
File: map.c

PyImaging_MapBuffer(PyObject* self, PyObject* args)
{
    Py_ssize_t y, size;
    Imaging im;

    PyObject* target;
    Py_buffer view;
    char* mode;
    char* codec;
    PyObject* bbox;
    Py_ssize_t offset;
    int xsize, ysize;
    int stride;
    int ystep;

    if (!PyArg_ParseTuple(args, "O(ii)sOn(sii)", &target, &xsize, &ysize,
                          &codec, &bbox, &offset, &mode, &stride, &ystep))
        return NULL;

    if (!PyImaging_CheckBuffer(target)) {
        PyErr_SetString(PyExc_TypeError, "expected string or buffer");
        return NULL;
    }

    if (stride <= 0) {
        if (!strcmp(mode, "L") || !strcmp(mode, "P"))
            stride = xsize;
        else if (!strncmp(mode, "I;16", 4))
            stride = xsize * 2;
        else
            stride = xsize * 4;
    }

    size = (Py_ssize_t) ysize * stride;

    /* check buffer size */
    if (PyImaging_GetBuffer(target, &view) < 0)
        return NULL;

    if (view.len < 0) {
        PyErr_SetString(PyExc_ValueError, "buffer has negative size");
        return NULL;
    }
    if (offset + size > view.len) {
        PyErr_SetString(PyExc_ValueError, "buffer is not large enough");
        return NULL;
    }

    im = ImagingNewPrologueSubtype(
        mode, xsize, ysize, sizeof(ImagingBufferInstance)
        );
    if (!im)
        return NULL;

    /* setup file pointers */
    if (ystep > 0)
        for (y = 0; y < ysize; y++)
            im->image[y] = (char*)view.buf + offset + y * stride;
    else
        for (y = 0; y < ysize; y++)
            im->image[ysize-y-1] = (char*)view.buf + offset + y * stride;

    im->destroy = mapping_destroy_buffer;

    Py_INCREF(target);
    ((ImagingBufferInstance*) im)->target = target;
    ((ImagingBufferInstance*) im)->view = view;

    if (!ImagingNewEpilogue(im))
        return NULL;

    return PyImagingNew(im);
}
Commit message: fix bug 3584, 'After 3.13.1, characters in some Japanese codec are never correctly converted to internal ones'

Thanks to honda@math.sci.hokudai.ac.jp
CVE: CVE-2015-8614
CWE: CWE-119
Vulnerability description: Multiple stack-based buffer overflows in the (1) conv_jistoeuc, (2) conv_euctojis, and (3) conv_sjistoeuc functions in codeconv.c in Claws Mail before 3.13.1 allow remote attackers to have unspecified impact via a crafted email, involving Japanese character set conversion.

Project: claws
File: codeconv.c

static gint conv_jistoeuc(gchar *outbuf, gint outlen, const gchar *inbuf)
{
	const guchar *in = inbuf;
	gchar *out = outbuf;
	JISState state = JIS_ASCII;

	while (*in != '\0' && (out - outbuf) > outlen - 3) {
		if (*in == ESC) {
			in++;
			if (*in == '$') {
				if (*(in + 1) == '@' || *(in + 1) == 'B') {
					state = JIS_KANJI;
					in += 2;
				} else if (*(in + 1) == '(' &&
					   *(in + 2) == 'D') {
					state = JIS_AUXKANJI;
					in += 3;
				} else {
					/* unknown escape sequence */
					state = JIS_ASCII;
				}
			} else if (*in == '(') {
				if (*(in + 1) == 'B' || *(in + 1) == 'J') {
					state = JIS_ASCII;
					in += 2;
				} else if (*(in + 1) == 'I') {
					state = JIS_HWKANA;
					in += 2;
				} else {
					/* unknown escape sequence */
					state = JIS_ASCII;
				}
			} else {
				/* unknown escape sequence */
				state = JIS_ASCII;
			}
		} else if (*in == 0x0e) {
			state = JIS_HWKANA;
			in++;
		} else if (*in == 0x0f) {
			state = JIS_ASCII;
			in++;
		} else {
			switch (state) {
			case JIS_ASCII:
				*out++ = *in++;
				break;
			case JIS_KANJI:
				*out++ = *in++ | 0x80;
				if (*in == '\0') break;
				*out++ = *in++ | 0x80;
				break;
			case JIS_HWKANA:
				*out++ = 0x8e;
				*out++ = *in++ | 0x80;
				break;
			case JIS_AUXKANJI:
				*out++ = 0x8f;
				*out++ = *in++ | 0x80;
				if (*in == '\0') break;
				*out++ = *in++ | 0x80;
				break;
			}
		}
	}

	*out = '\0';
	return 0;
}
Commit message: Fix #77367: Negative size parameter in mb_split

When adding the last element to the result value of `mb_split`, the
`chunk_pos` may point beyond the end of the string, in which case the
unsigned `n` would underflow.  Therefore, we check whether this is the
case in the first place, and only calculate `n` otherwise.  Since `n`
is no longer used outside the block, we move its declaration inside.
CVE: CVE-2019-9025
CWE: CWE-125
Vulnerability description: An issue was discovered in PHP 7.3.x before 7.3.1. An invalid multibyte string supplied as an argument to the mb_split() function in ext/mbstring/php_mbregex.c can cause PHP to execute memcpy() with a negative argument, which could read and write past buffers allocated for the data.

Project: php-src
File: php_mbregex.c

PHP_FUNCTION(mb_split)
{
	char *arg_pattern;
	size_t arg_pattern_len;
	php_mb_regex_t *re;
	OnigRegion *regs = NULL;
	char *string;
	OnigUChar *pos, *chunk_pos;
	size_t string_len;

	int err;
	size_t n;
	zend_long count = -1;

	if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|l", &arg_pattern, &arg_pattern_len, &string, &string_len, &count) == FAILURE) {
		RETURN_FALSE;
	}

	if (count > 0) {
		count--;
	}

	/* create regex pattern buffer */
	if ((re = php_mbregex_compile_pattern(arg_pattern, arg_pattern_len, MBREX(regex_default_options), MBREX(current_mbctype), MBREX(regex_default_syntax))) == NULL) {
		RETURN_FALSE;
	}

	array_init(return_value);

	chunk_pos = pos = (OnigUChar *)string;
	err = 0;
	regs = onig_region_new();
	/* churn through str, generating array entries as we go */
	while (count != 0 && (size_t)(pos - (OnigUChar *)string) < string_len) {
		size_t beg, end;
		err = onig_search(re, (OnigUChar *)string, (OnigUChar *)(string + string_len), pos, (OnigUChar *)(string + string_len), regs, 0);
		if (err < 0) {
			break;
		}
		beg = regs->beg[0], end = regs->end[0];
		/* add it to the array */
		if ((size_t)(pos - (OnigUChar *)string) < end) {
			if (beg < string_len && beg >= (size_t)(chunk_pos - (OnigUChar *)string)) {
				add_next_index_stringl(return_value, (char *)chunk_pos, ((OnigUChar *)(string + beg) - chunk_pos));
				--count;
			} else {
				err = -2;
				break;
			}
			/* point at our new starting point */
			chunk_pos = pos = (OnigUChar *)string + end;
		} else {
			pos++;
		}
		onig_region_free(regs, 0);
	}

	onig_region_free(regs, 1);

	/* see if we encountered an error */
	if (err <= -2) {
		OnigUChar err_str[ONIG_MAX_ERROR_MESSAGE_LEN];
		onig_error_code_to_str(err_str, err);
		php_error_docref(NULL, E_WARNING, "mbregex search failure in mbsplit(): %s", err_str);
		zend_array_destroy(Z_ARR_P(return_value));
		RETURN_FALSE;
	}

	/* otherwise we just have one last element to add to the array */
	n = ((OnigUChar *)(string + string_len) - chunk_pos);
	if (n > 0) {
		add_next_index_stringl(return_value, (char *)chunk_pos, n);
	} else {
		add_next_index_stringl(return_value, "", 0);
	}
}
Commit message: RDS: validate the requested traces user input against max supported

Larger than supported value can lead to array read/write overflow.

Reported-by: Colin Ian King <colin.king@canonical.com>
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
CVE: CVE-2017-18552
CWE: CWE-787
Vulnerability description: An issue was discovered in net/rds/af_rds.c in the Linux kernel before 4.11. There is an out of bounds write and read in the function rds_recv_track_latency.

Project: linux
File: af_rds.c

static int rds_recv_track_latency(struct rds_sock *rs, char __user *optval,
				  int optlen)
{
	struct rds_rx_trace_so trace;
	int i;

	if (optlen != sizeof(struct rds_rx_trace_so))
		return -EFAULT;

	if (copy_from_user(&trace, optval, sizeof(trace)))
		return -EFAULT;

	rs->rs_rx_traces = trace.rx_traces;
	for (i = 0; i < rs->rs_rx_traces; i++) {
		if (trace.rx_trace_pos[i] > RDS_MSG_RX_DGRAM_TRACE_MAX) {
			rs->rs_rx_traces = 0;
			return -EFAULT;
		}
		rs->rs_rx_trace[i] = trace.rx_trace_pos[i];
	}

	return 0;
}
Commit message: usbredir: fix free call

data might point into the middle of a larger buffer, there is a separate
free_on_destroy pointer passed into bufp_alloc() to handle that.  It is
only used in the normal workflow though, not when dropping packets due
to the queue being full.  Fix that.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/491
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20210722072756.647673-1-kraxel@redhat.com>
CVE: CVE-2021-3682
CWE: CWE-763
Vulnerability description: A flaw was found in the USB redirector device emulation of QEMU in versions prior to 6.1.0-rc2. It occurs when dropping packets during a bulk transfer from a SPICE client due to the packet queue being full. A malicious SPICE client could use this flaw to make QEMU call free() with faked heap chunk metadata, resulting in a crash of QEMU or potential code execution with the privileges of the QEMU process on the host.

Project: qemu
File: redirect.c

static int bufp_alloc(USBRedirDevice *dev, uint8_t *data, uint16_t len,
    uint8_t status, uint8_t ep, void *free_on_destroy)
{
    struct buf_packet *bufp;

    if (!dev->endpoint[EP2I(ep)].bufpq_dropping_packets &&
        dev->endpoint[EP2I(ep)].bufpq_size >
            2 * dev->endpoint[EP2I(ep)].bufpq_target_size) {
        DPRINTF("bufpq overflow, dropping packets ep %02X\n", ep);
        dev->endpoint[EP2I(ep)].bufpq_dropping_packets = 1;
    }
    /* Since we're interupting the stream anyways, drop enough packets to get
       back to our target buffer size */
    if (dev->endpoint[EP2I(ep)].bufpq_dropping_packets) {
        if (dev->endpoint[EP2I(ep)].bufpq_size >
                dev->endpoint[EP2I(ep)].bufpq_target_size) {
            free(data);
            return -1;
        }
        dev->endpoint[EP2I(ep)].bufpq_dropping_packets = 0;
    }

    bufp = g_new(struct buf_packet, 1);
    bufp->data   = data;
    bufp->len    = len;
    bufp->offset = 0;
    bufp->status = status;
    bufp->free_on_destroy = free_on_destroy;
    QTAILQ_INSERT_TAIL(&dev->endpoint[EP2I(ep)].bufpq, bufp, next);
    dev->endpoint[EP2I(ep)].bufpq_size++;
    return 0;
}
Commit message: Use a standard buffer size for translating

I believe this fixes #591 (the second part of of it)
CVE: CVE-2018-11683
CWE: CWE-787
Vulnerability description: Liblouis 3.5.0 has a stack-based Buffer Overflow in the function parseChars in compileTranslationTable.c, a different vulnerability than CVE-2018-11440.

Project: liblouis
File: lou_translate.c

translate_input(int forward_translation, char *table_name) {
	char charbuf[BUFSIZE];
	uint8_t *outputbuf;
	size_t outlen;
	widechar inbuf[BUFSIZE];
	widechar transbuf[BUFSIZE];
	int inlen;
	int translen;
	int k;
	int ch = 0;
	int result;
	while (1) {
		translen = BUFSIZE;
		k = 0;
		while ((ch = fgetc(input)) != '\n' && ch != EOF && k < BUFSIZE - 1)
			charbuf[k++] = ch;
		if (ch == EOF && k == 0) break;
		charbuf[k] = 0;
		inlen = _lou_extParseChars(charbuf, inbuf);
		if (forward_translation)
			result = lou_translateString(
					table_name, inbuf, &inlen, transbuf, &translen, NULL, NULL, 0);
		else
			result = lou_backTranslateString(
					table_name, inbuf, &inlen, transbuf, &translen, NULL, NULL, 0);
		if (!result) break;
#ifdef WIDECHARS_ARE_UCS4
		outputbuf = u32_to_u8(transbuf, translen, NULL, &outlen);
#else
		outputbuf = u16_to_u8(transbuf, translen, NULL, &outlen);
#endif
		printf(ch == EOF ? "%.*s" : "%.*s\n", (int)outlen, outputbuf);
		free(outputbuf);
	}
	lou_free();
}
Commit message: BREAKING CHANGE: block local filesystem access by default

fixes #4536
CVE: CVE-2020-21365
CWE: CWE-22
Vulnerability description: Directory traversal vulnerability in wkhtmltopdf through 0.12.5 allows remote attackers to read local files and disclose sensitive information via a crafted html file running with the default configurations.

Project: wkhtmltopdf
File: loadsettings.cc

LoadPage::LoadPage():
	jsdelay(200),
	windowStatus(""),
	zoomFactor(1.0),
	repeatCustomHeaders(false),
	blockLocalFileAccess(false),
	stopSlowScripts(true),
	debugJavascript(false),
	loadErrorHandling(abort),
	mediaLoadErrorHandling(ignore),
	cacheDir(""),
	proxyHostNameLookup(false) {};
Commit message: gnutls_x509_ext_import_proxy: fix issue reading the policy language

If the language was set but the policy wasn't, that could lead to
a double free, as the value returned to the user was freed.
CVE: CVE-2017-5334
CWE: CWE-415
Vulnerability description: Double free vulnerability in the gnutls_x509_ext_import_proxy function in GnuTLS before 3.3.26 and 3.5.x before 3.5.8 allows remote attackers to have unspecified impact via crafted policy language information in an X.509 certificate with a Proxy Certificate Information extension.

Project: gnutls
File: x509_ext.c

int gnutls_x509_ext_import_proxy(const gnutls_datum_t * ext, int *pathlen,
			      char **policyLanguage, char **policy,
			      size_t * sizeof_policy)
{
	ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
	int result;
	gnutls_datum_t value = { NULL, 0 };

	if ((result = asn1_create_element
	     (_gnutls_get_pkix(), "PKIX1.ProxyCertInfo",
	      &c2)) != ASN1_SUCCESS) {
		gnutls_assert();
		return _gnutls_asn2err(result);
	}

	result = _asn1_strict_der_decode(&c2, ext->data, ext->size, NULL);
	if (result != ASN1_SUCCESS) {
		gnutls_assert();
		result = _gnutls_asn2err(result);
		goto cleanup;
	}

	if (pathlen) {
		result = _gnutls_x509_read_uint(c2, "pCPathLenConstraint",
						(unsigned int *)
						pathlen);
		if (result == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND)
			*pathlen = -1;
		else if (result != GNUTLS_E_SUCCESS) {
			gnutls_assert();
			result = _gnutls_asn2err(result);
			goto cleanup;
		}
	}

	result = _gnutls_x509_read_value(c2, "proxyPolicy.policyLanguage",
					 &value);
	if (result < 0) {
		gnutls_assert();
		goto cleanup;
	}

	if (policyLanguage) {
		*policyLanguage = (char *)value.data;
	} else {
		gnutls_free(value.data);
		value.data = NULL;
	}

	result = _gnutls_x509_read_value(c2, "proxyPolicy.policy", &value);
	if (result == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND) {
		if (policy)
			*policy = NULL;
		if (sizeof_policy)
			*sizeof_policy = 0;
	} else if (result < 0) {
		gnutls_assert();
		goto cleanup;
	} else {
		if (policy) {
			*policy = (char *)value.data;
			value.data = NULL;
		}
		if (sizeof_policy)
			*sizeof_policy = value.size;
	}

	result = 0;
 cleanup:
	gnutls_free(value.data);
	asn1_delete_structure(&c2);

	return result;
}
Commit message: aarch64: Flush code mapping in addition to data mapping (#471)

This needs a new function, ffi_data_to_code_pointer, to translate
from data pointers to code pointers.

Fixes issue #470.
CVE: CVE-2020-9391
CWE: CWE-787
Vulnerability description: An issue was discovered in the Linux kernel 5.4 and 5.5 through 5.5.6 on the AArch64 architecture. It ignores the top byte in the address passed to the brk system call, potentially moving the memory break downwards when the application expects it to move upwards, aka CID-dcde237319e6. This has been observed to cause heap corruption with the GNU C Library malloc implementation.

Project: libffi
File: ffi.c

ffi_prep_closure_loc (ffi_closure *closure,
                      ffi_cif* cif,
                      void (*fun)(ffi_cif*,void*,void**,void*),
                      void *user_data,
                      void *codeloc)
{
  if (cif->abi != FFI_SYSV)
    return FFI_BAD_ABI;

  void (*start)(void);
  
  if (cif->flags & AARCH64_FLAG_ARG_V)
    start = ffi_closure_SYSV_V;
  else
    start = ffi_closure_SYSV;

#if FFI_EXEC_TRAMPOLINE_TABLE
#ifdef __MACH__
  void **config = (void **)((uint8_t *)codeloc - PAGE_MAX_SIZE);
  config[0] = closure;
  config[1] = start;
#endif
#else
  static const unsigned char trampoline[16] = {
    0x90, 0x00, 0x00, 0x58,	/* ldr	x16, tramp+16	*/
    0xf1, 0xff, 0xff, 0x10,	/* adr	x17, tramp+0	*/
    0x00, 0x02, 0x1f, 0xd6	/* br	x16		*/
  };
  char *tramp = closure->tramp;
  
  memcpy (tramp, trampoline, sizeof(trampoline));
  
  *(UINT64 *)(tramp + 16) = (uintptr_t)start;

  ffi_clear_cache(tramp, tramp + FFI_TRAMPOLINE_SIZE);
#endif

  closure->cif = cif;
  closure->fun = fun;
  closure->user_data = user_data;

  return FFI_OK;
}