Details
-
Bug
-
Status: Closed (View Workflow)
-
Critical
-
Resolution: Fixed
-
None
-
None
-
None
-
2026-9
-
Can result in hang or crash
-
Fixed a potential SIGSEGV in MCSSETPARMS/CALSETPARMS processing
Description
Title
Stack Buffer Overflow in MariaDB ColumnStore MCSSETPARMS/CALSETPARMS UDFs
Summary
The `MCSSETPARMS` and `CALSETPARMS` User-Defined Functions (UDFs) in MariaDB ColumnStore contain stack buffer overflow vulnerabilities. The functions copy user-supplied string arguments into fixed-size 50-byte stack buffers without any length validation. Any authenticated MariaDB user can trigger these overflows by calling the UDFs with arguments longer than 50 bytes, crashing the server process.
Affected Versions
- MariaDB Server 11.4.13 (stable), 13.1.0 (alpha) with ColumnStore plugin enabled
- ColumnStore submodule (mariadb-columnstore-engine) commit 962e861
- Earlier ColumnStore versions (used in 11.2, 11.0, 10.11) do not contain the affected UDFs
Details
In `storage/columnstore/columnstore/dbcon/mysql/ha_mcs_client_udfs.cpp`, `MAXSTRINGLENGTH` is defined as 50 (line 52). Two functions copy user-controlled string arguments into local buffers of this size without bounds checking:
1. `setparms_init()` (line 75) — stack buffer overflow during validation
At lines 85-88, a 50-byte stack buffer `valuestr` is allocated, and `args->args[1]` is copied into it using the attacker-controlled length `args->lengths[1]` with no check against `MAXSTRINGLENGTH`:
char valuestr[MAXSTRINGLENGTH]; // 50 bytes |
size_t vlen = args->lengths[1]; // attacker-controlled |
memcpy(valuestr, args->args[1], vlen--); // unbounded copy |
2. `mcssetparms()` (line 118) — stack buffer overflow and out-of-bounds null write
At lines 121-130, two 50-byte stack buffers are populated from attacker-controlled arguments without length validation:
char parameter[MAXSTRINGLENGTH]; // 50 bytes |
char valuestr[MAXSTRINGLENGTH]; // 50 bytes |
size_t plen = args->lengths[0]; // attacker-controlled |
size_t vlen = args->lengths[1]; // attacker-controlled |
|
|
memcpy(parameter, args->args[0], plen); // stack BOF |
memcpy(valuestr, args->args[1], vlen); // stack BOF |
|
|
parameter[plen] = '\0'; // OOB null write |
valuestr[vlen] = '\0'; // OOB null write |
There is no upstream length validation in the UDF framework (`item_func.cc`) for string arguments, so the length values reach these functions unchecked.
The UDFs `MCSSETPARMS` and `CALSETPARMS` (which delegates to `mcssetparms` at lines 196-199) are registered by the `install_mcs_mysql.sh.in` installation script. ColumnStore is included in the MariaDB source tree and enabled by default when building RPM/DEB packages (disabled by default for standard source builds, supported on x86_64 and aarch64 only). Once registered, the UDFs are callable by any authenticated MariaDB user — MariaDB's UDF framework does not require EXECUTE privilege for UDF invocation.
Proof of Concept
Prerequisites: MariaDB with ColumnStore plugin installed and the UDFs registered (automatic for RPM/DEB package installations; manual `install_mcs_mysql.sh` execution required for source builds). Any authenticated user account is sufficient.
See attached PoC SQL file for the exact statements used to trigger the overflow via both arguments of `MCSSETPARMS` and via the `CALSETPARMS` alias.
Impact
This is a stack buffer overflow vulnerability exploitable by any authenticated MariaDB user. The attacker controls both the content and the length of the overflow data.
*Denial of Service:* MariaDB enables `-fstack-protector` and `-D_FORTIFY_SOURCE=2` by default for release builds. Either mitigation detects the overflow at runtime and terminates the process, crashing the MariaDB server. Any authenticated user can trigger this with a single SQL statement.
All users of MariaDB ColumnStore installations are impacted. No special privileges beyond basic database access are required to trigger the vulnerability.
Attachment
Referenced attachment "poc.sql" is the following code:
-- Trigger via second argument (setparms_init)
|
SELECT MCSSETPARMS('test', REPEAT('A', 100)); |
|
|
-- Trigger via first argument (mcssetparms)
|
SELECT MCSSETPARMS(REPEAT('B', 200), '123'); |
|
|
-- Same attacks via CALSETPARMS alias
|
SELECT CALSETPARMS(REPEAT('A', 200), REPEAT('B', 200)); |
Reported by uaaw