https://bz.apache.org/bugzilla/show_bug.cgi?id=70298

            Bug ID: 70298
           Summary: mod_dav_lock: dav_size_indirect() reserves sizeof(int)
                    for a field written as apr_size_t
           Product: Apache httpd-2
           Version: 2.4-HEAD
          Hardware: PC
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P2
         Component: mod_dav
          Assignee: [email protected]
          Reporter: [email protected]
  Target Milestone: ---

modules/dav/lock/locks.c (2.4.x tip c904033f65) sizes each serialized
indirect lock record with:

    #define dav_size_indirect(a) (1 + sizeof(apr_uuid_t) \
                                    + sizeof(time_t) \
                                    + sizeof(int) + (a)->key.dsize)

but dav_generic_save_lock_record() writes the key-length field as
sizeof(ip->key.dsize), and apr_datum_t.dsize is apr_size_t (8 bytes on
LP64):

    memcpy(ptr, &ip->key.dsize, sizeof(ip->key.dsize));      /* locks.c:544 */

Each indirect record is therefore written 4 bytes past the end of its
apr_pcalloc() buffer (locks.c:505). The loader reads the field as
`*((int *) ...)` (locks.c:670) but advances by sizeof(ip->key.dsize).

The copy of the same macro in modules/dav/fs/lock.c:163 already uses
sizeof((a)->key.dsize), so the fix is to make locks.c match:

    --- a/modules/dav/lock/locks.c
    +++ b/modules/dav/lock/locks.c
    @@ -155,5 +155,5 @@
     #define dav_size_indirect(a) (1 + sizeof(apr_uuid_t) \
                                     + sizeof(time_t) \
    -                                + sizeof(int) + (a)->key.dsize)
    +                                + sizeof((a)->key.dsize) + (a)->key.dsize)

This is NOT reproducible with the distributed modules alone. mod_dav_fs
uses its own lock code (modules/dav/fs/lock.c) and never calls
dav_hooks_locks_generic, so the generic provider is reached only through a
DAV repository provider that is wired to it, with DAVGenericLockDB set.
I reproduced it with a small test-only module that registers a clone of
the "filesystem" provider using the generic hooks; it is
test scaffolding, not evidence of an issue in a stock configuration.

With that module on a 64-bit build:

  1. LOCK with "Depth: infinity" on a collection with one member.
  2. LOCK on the member with an "If:" header naming the token from step 1.

Observed:
  - Non-instrumented build (httpd 2.4.6 distro package): step 2 returns
    HTTP 500 with "The lock database was found to be corrupt".
  - AddressSanitizer build of 2.4.x: heap-buffer-overflow READ in
    dav_generic_load_lock_record() (locks.c:672) via apr_pmemdup(). This
    is visible only under ASAN. I have not shown impact beyond the 500
    above in a non-instrumented build.

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to