sync: Check values before applying changes

In SyncInitTrigger(), we would set the CheckTrigger function before
validating the counter value.

As a result, if the counter value overflowed, we would leave the
function SyncInitTrigger() with the CheckTrigger applied but without
updating the trigger object.

To avoid that issue, move the portion of code checking for the trigger
check value before updating the CheckTrigger function.

Related to CVE-2025-26601, ZDI-CAN-25870

Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1828>
This commit is contained in:
Olivier Fourdan 2025-01-20 16:54:30 +01:00
parent 16a1242d0f
commit f52cea2f93

View File

@ -381,6 +381,24 @@ SyncInitTrigger(ClientPtr client, SyncTrigger * pTrigger, XID syncObject,
}
}
if (changes & (XSyncCAValueType | XSyncCAValue)) {
if (pTrigger->value_type == XSyncAbsolute)
pTrigger->test_value = pTrigger->wait_value;
else { /* relative */
Bool overflow;
if (pCounter == NULL)
return BadMatch;
overflow = checked_int64_add(&pTrigger->test_value,
pCounter->value, pTrigger->wait_value);
if (overflow) {
client->errorValue = pTrigger->wait_value >> 32;
return BadValue;
}
}
}
if (changes & XSyncCATestType) {
if (pSync && SYNC_FENCE == pSync->type) {
@ -409,24 +427,6 @@ SyncInitTrigger(ClientPtr client, SyncTrigger * pTrigger, XID syncObject,
}
}
if (changes & (XSyncCAValueType | XSyncCAValue)) {
if (pTrigger->value_type == XSyncAbsolute)
pTrigger->test_value = pTrigger->wait_value;
else { /* relative */
Bool overflow;
if (pCounter == NULL)
return BadMatch;
overflow = checked_int64_add(&pTrigger->test_value,
pCounter->value, pTrigger->wait_value);
if (overflow) {
client->errorValue = pTrigger->wait_value >> 32;
return BadValue;
}
}
}
if (changes & XSyncCACounter) {
if (pSync != pTrigger->pSync) { /* new counter for trigger */
SyncDeleteTriggerFromSyncObject(pTrigger);