Repository navigation
mod_dav: avoid signed overflow parsing the Timeout header - #853
arshsmith1 wants to merge 2 commits into
Conversation
dav_get_timeout_string() added an unbounded atol() of the Second- value to the current time, so a huge value overflowed time_t (undefined behaviour) and in practice wrapped to a lock which had already expired; a negative or malformed value likewise expired the lock immediately. Parse the seconds strictly, skip a value which is not understood, and cap it at the 2^32-1 maximum allowed by RFC 4918.
|
I think this still needs to account for the range of
expires = (time_t)secs;
now = time(NULL);
return now + expires;On a build with a signed 32-bit So I think the protocol limit ( |
Capping the Timeout at the RFC 4918 maximum of 2^32-1 is not enough when time_t is a signed 32-bit type: now + timeout can still overflow. Clamp the seconds so that the absolute expiry fits in time_t, and add boundary tests for 2^31-1, 2^32-1 and 2^32.
|
Agreed, the RFC cap alone doesn't cover a signed 32-bit Added boundary cases for |
dav_get_timeout_string() turns the LOCK
Timeout: Second-Nheader into an expiry withnow + atol(val), so a large N such asSecond-9223372036854775807overflows time_t (UBSan: signed integer overflow at util.c:586) and wraps into the past: the LOCK returns 200 with a lock token, but the lock has already expired and a second client can lock the resource straight away. Negative or malformed values (Second--100,Second-abc) give the same already-expired lock. The seconds are now parsed with apr_strtoi64(), a value that is not understood is skipped like any other unknown TimeType, and anything above the RFC 4918 maximum of 2^32-1 is capped; the new test_002_lock_timeout.py cases fail without the change.(see
SECURITY.mdandhttps://www.apache.org/security/#reporting-a-vulnerability).
APLOGNO()tag;numbers are assigned by a committer at merge time (see
docs/log-message-tags/README).changes-entries/*.txtfile is included,following the template in
README.CHANGES(not needed otherwise).test/modules/xxxdirectory matching themodules/xxxmodule source,or
test/modules/corefor core server changes. On Unix, verify thesepass locally with e.g.
make check-pytest PYTEST_DIRS=test/modules/xxx.