libiec61850: patch CVE-2026-19108

Details:
https://nvd.nist.gov/vuln/detail/cve-2026-19108

Signed-off-by: Ankur Tyagi <ankur.tyagi85@gmail.com>
Signed-off-by: Anuj Mittal <anuj.mittal@oss.qualcomm.com>
This commit is contained in:
Ankur Tyagi
2026-09-15 07:52:12 +05:30
committed by Anuj Mittal
parent 09f09c81ad
commit 91c41d12e2
2 changed files with 209 additions and 0 deletions
@@ -0,0 +1,208 @@
From 846bd407527061665a3c109eaa6ee7e870ae6bc1 Mon Sep 17 00:00:00 2001
From: Michael Zillgith <michael.zillgith@mz-automation.de>
Date: Tue, 21 Jul 2026 10:26:33 +0000
Subject: [PATCH] - MMS server: fixed - Update URCB that used an association
specific dataset of another connection can cause heap-use-after-free
(LIB61850-577)(#596) - fixed bitbucket sonarcloud pipeline
(cherry picked from commit 486fd57f3aed65bb9d636ff00f9ddce2e450b168)
CVE: CVE-2026-19108
Upstream-Status: Backport [https://github.com/mz-automation/libiec61850/commit/486fd57f3aed65bb9d636ff00f9ddce2e450b168]
Signed-off-by: Ankur Tyagi <ankur.tyagi85@gmail.com>
---
bitbucket-pipelines.yml | 11 +++----
src/iec61850/inc_private/reporting.h | 1 +
src/iec61850/server/mms_mapping/mms_mapping.c | 29 +++++++++++++++++--
src/iec61850/server/mms_mapping/reporting.c | 17 +++++++----
.../iso_mms/server/mms_server_connection.c | 19 ++++++++++++
5 files changed, 65 insertions(+), 12 deletions(-)
diff --git a/bitbucket-pipelines.yml b/bitbucket-pipelines.yml
index a7493663..30dce281 100644
--- a/bitbucket-pipelines.yml
+++ b/bitbucket-pipelines.yml
@@ -1,4 +1,4 @@
-image: atlassian/default-image:4
+image: atlassian/default-image:5
clone:
depth: full # SonarCloud scanner needs the full history to assign issues properly
@@ -12,12 +12,13 @@ definitions:
caches:
- sonar
script:
- - export SONAR_SCANNER_VERSION=5.0.1.3006
- - export SONAR_SCANNER_OPTS="-Dsonar.javaHome=/usr/lib/jvm/java-17-openjdk-amd64"
- - export SONAR_SCANNER_HOME=$HOME/.sonar/sonar-scanner-$SONAR_SCANNER_VERSION-linux
+ - export SONAR_SCANNER_VERSION=6.2.1.4610
+ - export SONAR_SCANNER_HOME=$HOME/.sonar/sonar-scanner-$SONAR_SCANNER_VERSION-linux-x64
- export BW_OUTPUT=$HOME/.sonar/bw-output
- mkdir -p $BW_OUTPUT
- - curl --create-dirs -sSLo $HOME/.sonar/sonar-scanner.zip https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-$SONAR_SCANNER_VERSION-linux.zip
+ - apt-get update -qq
+ - apt-get install openjdk-21-jre cmake -y
+ - curl --create-dirs -sSLo $HOME/.sonar/sonar-scanner.zip https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-$SONAR_SCANNER_VERSION-linux-x64.zip
- unzip -o $HOME/.sonar/sonar-scanner.zip -d $HOME/.sonar/
- export PATH=$SONAR_SCANNER_HOME/bin:$PATH
- curl --create-dirs -sSLo $HOME/.sonar/build-wrapper-linux-x86.zip https://sonarcloud.io/static/cpp/build-wrapper-linux-x86.zip
diff --git a/src/iec61850/inc_private/reporting.h b/src/iec61850/inc_private/reporting.h
index eddeb2d1..bc23f937 100644
--- a/src/iec61850/inc_private/reporting.h
+++ b/src/iec61850/inc_private/reporting.h
@@ -67,6 +67,7 @@ typedef struct {
bool buffered; /* true if report is a buffered report */
MmsValue** bufferedDataSetValues; /* used to buffer values during bufTm time */
+ int bufferedDataSetValuesSize; /* number of dataset entries */
MmsValue** valueReferences; /* array to store value references for fast access */
diff --git a/src/iec61850/server/mms_mapping/mms_mapping.c b/src/iec61850/server/mms_mapping/mms_mapping.c
index 5620f63f..ef6f3580 100644
--- a/src/iec61850/server/mms_mapping/mms_mapping.c
+++ b/src/iec61850/server/mms_mapping/mms_mapping.c
@@ -3912,6 +3912,10 @@ variableListAccessHandler (void* parameter, MmsVariableListAccessType accessType
{
ReportControl* rc = (ReportControl*) rcElement->data;
+#if (CONFIG_MMS_THREADLESS_STACK != 1)
+ Semaphore_wait(rc->rcbValuesLock);
+#endif
+
if (rc->isDynamicDataSet)
{
if (rc->dataSet != NULL)
@@ -3924,6 +3928,11 @@ variableListAccessHandler (void* parameter, MmsVariableListAccessType accessType
{
if (strcmp(rc->dataSet->logicalDeviceName, MmsDomain_getName(domain) + strlen(self->model->name)) == 0)
{
+#if (CONFIG_MMS_THREADLESS_STACK != 1)
+ Semaphore_post(rc->rcbValuesLock);
+#endif
+
+ /* dataset is in use and cannot be deleted */
allow = MMS_ERROR_SERVICE_OBJECT_CONSTRAINT_CONFLICT;
break;
}
@@ -3936,6 +3945,10 @@ variableListAccessHandler (void* parameter, MmsVariableListAccessType accessType
{
if (strcmp(rc->dataSet->name, listName) == 0)
{
+#if (CONFIG_MMS_THREADLESS_STACK != 1)
+ Semaphore_post(rc->rcbValuesLock);
+#endif
+ /* dataset is in use and cannot be deleted */
allow = MMS_ERROR_SERVICE_OBJECT_CONSTRAINT_CONFLICT;
break;
}
@@ -3947,13 +3960,22 @@ variableListAccessHandler (void* parameter, MmsVariableListAccessType accessType
{
if (strcmp(rc->dataSet->name, listName) == 0)
{
- allow = MMS_ERROR_SERVICE_OBJECT_CONSTRAINT_CONFLICT;
- break;
+ /* this is usually called when the connection is closed -> RCB has already been disabled by connection handler */
+
+ MmsMapping_freeDynamicallyCreatedDataSet(rc->dataSet);
+
+ /* cleanup dataset information in RCB instance */
+ rc->dataSet = NULL;
+ rc->isDynamicDataSet = false;
}
}
}
}
}
+
+#if (CONFIG_MMS_THREADLESS_STACK != 1)
+ Semaphore_post(rc->rcbValuesLock);
+#endif
}
#if (CONFIG_IEC61850_LOG_SERVICE == 1)
@@ -4729,6 +4751,9 @@ MmsMapping_getDomainSpecificDataSet(MmsMapping* self, const char* dataSetName)
void
MmsMapping_freeDynamicallyCreatedDataSet(DataSet* dataSet)
{
+ if (dataSet == NULL)
+ return;
+
DataSetEntry* dataSetEntry = dataSet->fcdas;
while (dataSetEntry)
diff --git a/src/iec61850/server/mms_mapping/reporting.c b/src/iec61850/server/mms_mapping/reporting.c
index a44f0583..03add555 100644
--- a/src/iec61850/server/mms_mapping/reporting.c
+++ b/src/iec61850/server/mms_mapping/reporting.c
@@ -193,13 +193,9 @@ deleteDataSetValuesShadowBuffer(ReportControl* self)
{
if (self->bufferedDataSetValues != NULL)
{
- assert(self->dataSet != NULL);
-
- int dataSetSize = DataSet_getSize(self->dataSet);
-
int i;
- for (i = 0; i < dataSetSize; i++)
+ for (i = 0; i < self->bufferedDataSetValuesSize; i++)
{
if (self->bufferedDataSetValues[i] != NULL)
MmsValue_delete(self->bufferedDataSetValues[i]);
@@ -698,13 +694,24 @@ static void
createDataSetValuesShadowBuffer(ReportControl* rc)
{
int dataSetSize = DataSet_getSize(rc->dataSet);
+ rc->bufferedDataSetValuesSize = dataSetSize;
MmsValue** dataSetValues = (MmsValue**)GLOBAL_CALLOC(dataSetSize, sizeof(MmsValue*));
+ if (dataSetValues == NULL)
+ return;
+
rc->bufferedDataSetValues = dataSetValues;
rc->valueReferences = (MmsValue**)GLOBAL_MALLOC(dataSetSize * sizeof(MmsValue*));
+ if (rc->valueReferences == NULL)
+ {
+ GLOBAL_FREEMEM(dataSetValues);
+ rc->bufferedDataSetValues = NULL;
+ return;
+ }
+
DataSetEntry* dataSetEntry = rc->dataSet->fcdas;
int i;
diff --git a/src/mms/iso_mms/server/mms_server_connection.c b/src/mms/iso_mms/server/mms_server_connection.c
index 644fcdb1..401ad40b 100644
--- a/src/mms/iso_mms/server/mms_server_connection.c
+++ b/src/mms/iso_mms/server/mms_server_connection.c
@@ -829,6 +829,25 @@ MmsServerConnection_destroy(MmsServerConnection self)
#endif
#if (MMS_DYNAMIC_DATA_SETS == 1)
+ /* notify IEC 61850 layer BEFORE destroying named variable lists */
+ if (self->namedVariableLists)
+ {
+ LinkedList element = LinkedList_getNext(self->namedVariableLists);
+
+ while (element)
+ {
+ MmsNamedVariableList variableList = (MmsNamedVariableList)element->data;
+
+ if (variableList && variableList->name)
+ {
+ mmsServer_callVariableListChangedHandler(MMS_VARLIST_DELETE, MMS_ASSOCIATION_SPECIFIC,
+ NULL, /* domain (NULL for aa-specific) */
+ variableList->name, self);
+ }
+ element = LinkedList_getNext(element);
+ }
+ }
+
LinkedList_destroyDeep(self->namedVariableLists, (LinkedListValueDeleteFunction) MmsNamedVariableList_destroy);
#endif
@@ -19,6 +19,7 @@ SRC_URI = "git://github.com/mz-automation/${BPN}.git;branch=v1.6;protocol=https;
file://0001-pyiec61850-Use-CMAKE_INSTALL_LIBDIR-from-GNUInstallD.patch \
file://CVE-2026-18582.patch \
file://CVE-2026-18583.patch \
file://CVE-2026-19108.patch \
"