Skip to content

Try 1 4 - #1

Open
FreddieAkeroyd wants to merge 2094 commits into
IBEXfrom
try_1_4
Open

Try 1 4#1
FreddieAkeroyd wants to merge 2094 commits into
IBEXfrom
try_1_4

Conversation

@FreddieAkeroyd

Copy link
Copy Markdown
Member

laroche and others added 30 commits January 2, 2025 20:49
Currently an IP 42.42.42.42 is set and the comment suggests that
the network stack resets this to 0.0.0.0 in server_multicast.c.
Just set 0.0.0.0 directly.

This is a backport of 253fc8a
to the 1.3 branch.

Signed-off-by: Florian La Roche <Florian.LaRoche@gmail.com>
Avoid spaces in mdnsServerName as this is used for mDNS records.

This is a backport of 711b032
into the 1.4 branch.

Signed-off-by: Florian La Roche <Florian.LaRoche@gmail.com>
If we publish mDNS records in src/server/ua_discovery_mdns.c,
always add a ".local." suffix for all entries.

Signed-off-by: Florian La Roche <f.laroche@pilz.de>
* refactor(core): Use recursive locks [93838cd] introduced recursive locking.

* PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP is not defined in musl libc
* use PTHREAD_MUTEX_INITIALIZER on musl libc systems

Signed-off-by: Goetz Goerisch <g.goerisch@vdw.de>
o6-jpfr and others added 30 commits June 27, 2026 10:08
…ents

Variant_setRange uses sizeof(elem_size) instead of elem_size in
the memset that zeros moved array elements. sizeof(elem_size)
always evaluates to sizeof(size_t), which is 8 on 64-bit. For
types with memSize > 8 (e.g. UA_String at 16 bytes), only half
the struct is zeroed, leaving heap pointers dangling. This causes
a double-free when both the source and the variant are cleared.
The default server configuration zero-initialises
maxPublishReqPerSession, which disables the per-session cap on
outstanding PublishRequest entries. A remote client that is allowed
to create a session and a subscription can therefore send an
unbounded number of PublishRequest messages, each of which allocates
a UA_PublishResponseEntry and appends it to the session's publish
queue. The resulting monotonic heap growth causes process memory
exhaustion and a denial of service.

Set a safe finite default of 512 outstanding PublishRequests per
session in setDefaultConfig() so that the cap is enforced out of the
box, while still allowing deployers to override it.

Internal Vulnerability Advisory: open62541-SA-2026-0010
Co-Authored-By: keyme <kmm2003@users.noreply.github.com>
… attached session

When an event subscription outlives the session that created it (e.g.
after CloseSession with deleteSubscriptions=false, or before a
TransferSubscriptions call), sub->session is NULL. The function then
passes a NULL session to filterEvent()/readWithSession(), which
dereferences the session when resolving SimpleAttributeOperands, leading
to a NULL pointer dereference and immediate process termination. A
subsequent TransferSubscriptions could also let a less-privileged
client inherit the queued event notifications.

Do not evaluate event fields while the subscription has no attached
session. The monitored item is effectively dormant and is skipped by
this guard; as soon as the subscription is re-bound to a session,
event evaluation resumes under that session's access rights.

Internal Vulnerability Advisory: open62541-SA-2026-0007
Co-Authored-By: keyme <kmm2003@users.noreply.github.com>
The default server configuration zero-initialises
maxPublishReqPerSession, which disables the per-session cap on
outstanding PublishRequest entries. A remote client that is allowed
to create a session and a subscription can therefore send an
unbounded number of PublishRequest messages, each of which allocates
a UA_PublishResponseEntry and appends it to the session's publish
queue. The resulting monotonic heap growth causes process memory
exhaustion and a denial of service.

Set a safe finite default of 512 outstanding PublishRequests per
session in setDefaultConfig() so that the cap enforced by
UA_Session_ensurePublishQueueSpace() is active in the default profile,
while still allowing deployers to override it.

Internal Vulnerability Advisory: open62541-SA-2026-0010
Co-Authored-By: keyme <kmm2003@users.noreply.github.com>
cj5_get_str() only wrote the terminating NUL on its success path. Every
error return (incomplete/invalid escape sequences, truncated \u
codepoints, invalid surrogate pairs) left the caller-supplied buffer
unterminated.

Callers in ua_config_json.c (e.g. BuildInfo_parseJson()) allocate the
buffer with UA_malloc() and pass it to strcmp()/UA_LOG_ERROR("%s", ...)
without checking cj5_get_str()'s return code, so a malformed escape in
a JSON5 config field name (e.g. "\u12") causes a heap out-of-bounds read
past the allocation.

Restructure cj5_get_str() around a single exit point so buf[outpos] = 0
is written unconditionally, before every return -- success or error.
Callers should still check the returned error code, but can no longer
read past the buffer if they don't.

Co-authored-by: Martin Mohl <Whit3rose@users.noreply.github.com>
Add unit tests to check_cj5.c that call cj5_get_str() directly with
unpaired/truncated UTF-16 surrogate escapes -- the actual reachable
trigger for the bug, since cj5_parse()'s tokenizer already rejects
most other malformed \u escapes before cj5_get_str() runs. These are
the deterministic regression guard: they fail under ASan on the
pre-fix cj5_get_str() and pass cleanly after.

Add check_server_config_json.c as an API-level smoke test through
UA_ServerConfig_updateFromFile()/UA_Server_newFromFile(), and
fuzz_config_json.cc since no fuzz target previously exercised the
config-file JSON parser at all.
Every PARSE_JSON() function in ua_config_json.c indexed into the
tokens[MAX_TOKENS] array via ctx->tokens[++ctx->index] without checking
ctx->index against the actual number of parsed tokens. A field's
declared child count (cj5_token.size) can desync from the real token
count, e.g. an unrecognized field name whose value is skipped without
consuming its tokens, letting that walk run past the end of the
stack-allocated token array.

Add a nextToken() helper that advances ctx->index and returns a zeroed
size-0 sentinel once the stream is exhausted instead of reading out of
bounds, and route all 36 call sites through it (plus the equivalent
check at the top-level parseJSONConfig loop). Every call site already
handles an empty/mismatched token gracefully, so this only changes
behavior for malformed input.
…ecoding

Multiplying attacker-controlled arrayDimensions values into a size_t
accumulator without an overflow check allows the product to wrap and
match a small arrayLength. Subsequent ranged read or write operations
then access memory outside the allocated array bounds.

Add checked multiplication at all sites where the dimension product is
computed: Variant binary decode, Variant binary encode, checkAdjustRange,
and computeStrides (as a defence-in-depth measure).

Internal Vulnerability Advisory: open62541-SA-2026-0012 and open62541-SA-2026-0013
Co-authored-by: Asher Davila <AsherDLL@users.noreply.github.com>
Co-authored-by: Malav Vyas <MalavVyas@users.noreply.github.com>
Add bounds check in verifyAndDecrypt() to prevent unsigned integer
underflow when buffer->length is smaller than the expected signature
size. Without this check, the subtraction wraps around producing a
large size_t that causes mbedtls to read unmapped memory.

Internal Vulnerability Advisory: open62541-SA-2026-0014
Co-authored-by: Abhinav Agarwal <abhinavagarwal1996@gmail.com>
Operation_TransferSubscription() copies the UA_Subscription struct with
memcpy but only migrates monitoredItems, notificationQueue, and
retransmissionQueue. The samplingMonitoredItems list was not re-initialized
in the new subscription, leaving stale le_prev backpointers from items
with samplingType==PUBLISH pointing into the freed old subscription struct.
When UA_MonitoredItem_unregisterSampling() calls LIST_REMOVE, it writes
to freed memory (heap-use-after-free).

Add migration of samplingMonitoredItems to the new subscription after
the point of no return, matching the pattern used for monitoredItems.

Internal Vulnerability Advisory: open62541-SA-2026-0015
Co-authored-by: Abhinav Agarwal <abhinavagarwal1996@gmail.com>
Operation_TransferSubscription() copies the UA_Subscription struct with
memcpy but only migrates monitoredItems, notificationQueue, and
retransmissionQueue. The samplingMonitoredItems list was not re-initialized
in the new subscription, leaving stale le_prev backpointers from items
with samplingType==PUBLISH pointing into the freed old subscription struct.
When UA_MonitoredItem_unregisterSampling() calls LIST_REMOVE, it writes
to freed memory (heap-use-after-free).

Add migration of samplingMonitoredItems to the new subscription after
the point of no return, matching the pattern used for monitoredItems.

Internal Vulnerability Advisory: open62541-SA-2026-0015
Co-authored-by: Abhinav Agarwal <abhinavagarwal1996@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.