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

            Bug ID: 70299
           Summary: mod_dav_lock: dav_generic_load_lock_record() reads the
                    indirect-lock key length as a 4-byte int, but the save
                    path always writes it as a full apr_size_t
           Product: Apache httpd-2
           Version: 2.4-HEAD
          Hardware: PC
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P2
         Component: mod_dav_lock
          Assignee: [email protected]
          Reporter: [email protected]
  Target Milestone: ---

Found while reviewing the fix for BZ 70298 (dav_size_indirect() under-reserving
space, PR at https://github.com/apache/httpd/pull/905). This is a separate bug
in the same read/write pair, not touched by that PR.

modules/dav/lock/locks.c, dav_generic_save_lock_record() (the write path),
always writes the indirect-lock key length as a full-width field:

memcpy(ptr, &ip->key.dsize, sizeof(ip->key.dsize));

ip->key.dsize is apr_size_t, so this writes sizeof(apr_size_t) bytes (8 on a
typical LP64 build).

dav_generic_load_lock_record() (the read path), locks.c around line 670, reads
that same field back with a 4-byte int cast instead of matching the write
width:

ip->key.dsize = *((int *) (val.dptr + offset));
offset += sizeof(ip->key.dsize);

The read takes only the first 4 bytes of the 8-byte field, but offset is still
advanced by sizeof(ip->key.dsize) (8), matching the real field width. On a
little-endian LP64 system this happens to read the correct value for any
realistic (small, positive) key length, because the low-order 4 bytes of an
8-byte little-endian integer are exactly those bytes. On a big-endian system
the same cast would read the high-order 4 bytes, which are zero for any such
value, so every indirect lock's key would be read back with a length of 0.

For comparison, the equivalent code in modules/dav/fs/lock.c (a different lock
provider) reads this field correctly with a full-width memcpy:

memcpy(&ip->key.dsize, val.dptr + offset, sizeof(ip->key.dsize));

I have not reproduced this on an actual big-endian system or build; this is a
static read of the code, same as the sizing bug in BZ 70298. The generic lock
provider in modules/dav/lock/ is not wired into any module shipped with httpd
(confirmed by grepping the tree for dav_hooks_locks_generic /
ap_lookup_provider(..., "dav-lock", ...): only modules/dav/lock/ itself
references it), so this is low practical severity, same caveat as BZ 70298.

Suggested fix: read the field with a width-matching memcpy, as
modules/dav/fs/lock.c already does, instead of the int cast.

-- 
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