freerdp/channels-audin-tighten-parameter-checks.patch
RHEL Packaging Agent c2efdf022e Backport several CVE fixes
It fixes CVE-2026-67289, CVE-2026-67299 and CVE-2026-68580.

Resolves: RHEL-222792, RHEL-222965, RHEL-223607

Co-authored-by: Ondrej Holy <oholy@redhat.com>
2026-08-17 13:20:29 +00:00

223 lines
7.9 KiB
Diff

From cc57fb28a27f8563375ac435a9f16985135a1789 Mon Sep 17 00:00:00 2001
From: Armin Novak <armin.novak@thincast.com>
Date: Wed, 15 Jul 2026 17:52:28 +0200
Subject: [PATCH] [channels,audin] tighten parameter checks
---
channels/audin/client/alsa/audin_alsa.c | 4 +--
channels/audin/client/opensles/opensl_io.c | 40 ++++++++++++++--------
channels/audin/client/opensles/opensl_io.h | 5 ++-
channels/audin/client/oss/audin_oss.c | 3 ++
channels/audin/client/sndio/audin_sndio.c | 9 +++--
channels/audin/client/winmm/audin_winmm.c | 17 ++++-----
6 files changed, 48 insertions(+), 30 deletions(-)
diff --git a/channels/audin/client/alsa/audin_alsa.c b/channels/audin/client/alsa/audin_alsa.c
index 20564dc04..3882b734f 100644
--- a/channels/audin/client/alsa/audin_alsa.c
+++ b/channels/audin/client/alsa/audin_alsa.c
@@ -139,8 +139,8 @@ static DWORD WINAPI audin_alsa_thread_func(LPVOID arg)
goto out;
}
- buffer =
- (BYTE*)calloc(alsa->frames_per_packet + alsa->aformat.nBlockAlign, alsa->bytes_per_frame);
+ buffer = (BYTE*)calloc(1ull * alsa->frames_per_packet + alsa->aformat.nBlockAlign,
+ alsa->bytes_per_frame);
if (!buffer)
{
diff --git a/channels/audin/client/opensles/opensl_io.c b/channels/audin/client/opensles/opensl_io.c
index a447dac34..c4598a634 100644
--- a/channels/audin/client/opensles/opensl_io.c
+++ b/channels/audin/client/opensles/opensl_io.c
@@ -54,10 +54,10 @@ struct opensl_stream
SLRecordItf recorderRecord;
SLAndroidSimpleBufferQueueItf recorderBufferQueue;
- unsigned int inchannels;
- unsigned int sr;
- unsigned int buffersize;
- unsigned int bits_per_sample;
+ size_t inchannels;
+ size_t sr;
+ size_t buffersize;
+ size_t bits_per_sample;
queue_element* prep;
queue_element* next;
@@ -108,8 +108,8 @@ engine_end:
static SLresult openSLRecOpen(OPENSL_STREAM* p)
{
SLresult result;
- SLuint32 sr = p->sr;
- SLuint32 channels = p->inchannels;
+ SLuint32 sr = WINPR_ASSERTING_INT_CAST(SLuint32, p->sr);
+ SLuint32 channels = WINPR_ASSERTING_INT_CAST(SLuint32, p->inchannels);
WINPR_ASSERT(!p->recorderObject);
if (channels)
@@ -202,7 +202,7 @@ static SLresult openSLRecOpen(OPENSL_STREAM* p)
}
else
{
- WLog_ERR(TAG, "bits_per_sample=%" PRIu32, p->bits_per_sample);
+ WLog_ERR(TAG, "bits_per_sample=%" PRIuz, p->bits_per_sample);
return -1;
}
@@ -314,24 +314,31 @@ static void opensles_queue_element_free(void* obj)
}
// open the android audio device for input
-OPENSL_STREAM* android_OpenRecDevice(void* context, opensl_receive_t receive, int sr,
- int inchannels, int bufferframes, int bits_per_sample)
+OPENSL_STREAM* android_OpenRecDevice(void* context, opensl_receive_t receive, size_t sr,
+ size_t inchannels, size_t bufferframes, size_t bits_per_sample)
{
- OPENSL_STREAM* p;
-
if (!context || !receive)
return nullptr;
- p = (OPENSL_STREAM*)calloc(1, sizeof(OPENSL_STREAM));
+ OPENSL_STREAM* p = (OPENSL_STREAM*)calloc(1, sizeof(OPENSL_STREAM));
if (!p)
return nullptr;
p->context = context;
p->receive = receive;
+ if (inchannels > INT32_MAX)
+ goto fail;
p->inchannels = inchannels;
+
+ if (sr > INT32_MAX)
+ goto fail;
p->sr = sr;
+
+ if (bufferframes > SIZE_MAX / 2)
+ goto fail;
p->buffersize = bufferframes;
+
p->bits_per_sample = bits_per_sample;
if ((p->bits_per_sample != 8) && (p->bits_per_sample != 16))
@@ -343,9 +350,14 @@ OPENSL_STREAM* android_OpenRecDevice(void* context, opensl_receive_t receive, in
if (openSLRecOpen(p) != SL_RESULT_SUCCESS)
goto fail;
+ const size_t bytesPerSample = p->bits_per_sample / 8ull;
+ if (p->buffersize >= SIZE_MAX / bytesPerSample)
+ goto fail;
+
+ const size_t queuesize = p->buffersize * bytesPerSample;
/* Create receive buffers, prepare them and start recording */
- p->prep = opensles_queue_element_new(p->buffersize * p->bits_per_sample / 8);
- p->next = opensles_queue_element_new(p->buffersize * p->bits_per_sample / 8);
+ p->prep = opensles_queue_element_new(queuesize);
+ p->next = opensles_queue_element_new(queuesize);
if (!p->prep || !p->next)
goto fail;
diff --git a/channels/audin/client/opensles/opensl_io.h b/channels/audin/client/opensles/opensl_io.h
index 4f9b2db4f..bdba57cab 100644
--- a/channels/audin/client/opensles/opensl_io.h
+++ b/channels/audin/client/opensles/opensl_io.h
@@ -56,10 +56,9 @@ extern "C"
size in frames. Returns a handle to the OpenSL stream
*/
WINPR_ATTR_MALLOC(android_CloseRecDevice, 1)
- WINPR_ATTR_NODISCARD
FREERDP_LOCAL OPENSL_STREAM* android_OpenRecDevice(void* context, opensl_receive_t receive,
- int sr, int inchannels, int bufferframes,
- int bits_per_sample);
+ size_t sr, size_t inchannels,
+ size_t bufferframes, size_t bits_per_sample);
#ifdef __cplusplus
};
#endif
diff --git a/channels/audin/client/oss/audin_oss.c b/channels/audin/client/oss/audin_oss.c
index f709130be..d2e10ef3d 100644
--- a/channels/audin/client/oss/audin_oss.c
+++ b/channels/audin/client/oss/audin_oss.c
@@ -190,6 +190,9 @@ static DWORD WINAPI audin_oss_thread_func(LPVOID arg)
buffer_size =
(1ull * oss->FramesPerPacket * oss->format.nChannels * (oss->format.wBitsPerSample / 8ull));
+ if (buffer_size > INT32_MAX)
+ goto err_out;
+
buffer = (BYTE*)calloc((buffer_size + sizeof(void*)), sizeof(BYTE));
if (nullptr == buffer)
diff --git a/channels/audin/client/sndio/audin_sndio.c b/channels/audin/client/sndio/audin_sndio.c
index d922855be..6da44e612 100644
--- a/channels/audin/client/sndio/audin_sndio.c
+++ b/channels/audin/client/sndio/audin_sndio.c
@@ -82,7 +82,7 @@ static void* audin_sndio_thread_func(void* arg)
struct sio_hdl* hdl;
struct sio_par par;
BYTE* buffer = nullptr;
- size_t n, nbytes;
+ size_t n;
AudinSndioDevice* sndio = (AudinSndioDevice*)arg;
UINT error = 0;
DWORD status;
@@ -125,8 +125,11 @@ static void* audin_sndio_thread_func(void* arg)
goto err_out;
}
- nbytes =
- (sndio->FramesPerPacket * sndio->format.nChannels * (sndio->format.wBitsPerSample / 8));
+ const size_t nbytes = (1ull * sndio->FramesPerPacket * sndio->format.nChannels *
+ (sndio->format.wBitsPerSample / 8));
+ if (nbytes > INT32_MAX)
+ goto err_out;
+
buffer = (BYTE*)calloc((nbytes + sizeof(void*)), sizeof(BYTE));
if (buffer == nullptr)
diff --git a/channels/audin/client/winmm/audin_winmm.c b/channels/audin/client/winmm/audin_winmm.c
index 0c1cd3867..573d1d6d1 100644
--- a/channels/audin/client/winmm/audin_winmm.c
+++ b/channels/audin/client/winmm/audin_winmm.c
@@ -169,8 +169,6 @@ static BOOL test_format_supported(const PWAVEFORMATEX pwfx)
static DWORD WINAPI audin_winmm_thread_func(LPVOID arg)
{
AudinWinmmDevice* winmm = (AudinWinmmDevice*)arg;
- char* buffer = nullptr;
- int size = 0;
WAVEHDR waveHdr[4] = WINPR_C_ARRAY_INIT;
DWORD status = 0;
MMRESULT rc = 0;
@@ -184,19 +182,22 @@ static DWORD WINAPI audin_winmm_thread_func(LPVOID arg)
return ERROR_INTERNAL_ERROR;
}
- size =
- (winmm->pwfx_cur->wBitsPerSample * winmm->pwfx_cur->nChannels * winmm->frames_per_packet +
- 7) /
- 8;
+ const size_t framesize =
+ 1ull * winmm->pwfx_cur->wBitsPerSample / 8ull * winmm->pwfx_cur->nChannels;
+ if (framesize > UINT32_MAX)
+ return ERROR_INTERNAL_ERROR;
+ const size_t size = framesize * winmm->frames_per_packet;
+ if (size > UINT32_MAX)
+ return ERROR_INTERNAL_ERROR;
for (int i = 0; i < 4; i++)
{
- buffer = (char*)malloc(size);
+ char* buffer = (char*)calloc(framesize, winmm->frames_per_packet);
if (!buffer)
return CHANNEL_RC_NO_MEMORY;
- waveHdr[i].dwBufferLength = size;
+ waveHdr[i].dwBufferLength = WINPR_ASSERTING_INT_CAST(DWORD, size);
waveHdr[i].dwFlags = 0;
waveHdr[i].lpData = buffer;
rc = waveInPrepareHeader(winmm->hWaveIn, &waveHdr[i], sizeof(waveHdr[i]));