From: Matthew N. Heler Date: Sun, 22 Mar 2026 16:41:00 +0000 (-0500) Subject: rgw: fix fixup_range cascade for compressed+encrypted objects X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=0378ee8febd48b6657830f9d5435714878f96e6a;p=ceph.git rgw: fix fixup_range cascade for compressed+encrypted objects When both decrypt and decompress filters are active, decrypt's fixup_range cascades into decompress via the next pointer and overwrites q_len with block-aligned encrypted offsets instead of plaintext offsets. This breaks GET and upload-part-copy reads. Fix by calling next->fixup_range() at the beginning of RGWGetObj_BlockDecrypt::fixup_range() so the next filter sees the original plaintext range before decrypt block-aligns it. Move the GET path's fixup_range call to after the full filter chain is built so a single call composes correctly. Signed-off-by: Matthew N. Heler --- diff --git a/src/rgw/rgw_crypt.cc b/src/rgw/rgw_crypt.cc index 8e8ffc2d8693..bef6a2eaeba9 100644 --- a/src/rgw/rgw_crypt.cc +++ b/src/rgw/rgw_crypt.cc @@ -710,6 +710,13 @@ int RGWGetObj_BlockDecrypt::read_manifest_parts(const DoutPrefixProvider *dpp, } int RGWGetObj_BlockDecrypt::fixup_range(off_t& bl_ofs, off_t& bl_end) { + /* + * Cascade to the next filter first so it sees the original + * plaintext range before we block-align for decryption. + */ + if (next) + next->fixup_range(bl_ofs, bl_end); + off_t inp_ofs = bl_ofs; off_t inp_end = bl_end; if (parts_len.size() > 0) { @@ -751,9 +758,6 @@ int RGWGetObj_BlockDecrypt::fixup_range(off_t& bl_ofs, off_t& bl_end) { ldpp_dout(this->dpp, 20) << "fixup_range [" << inp_ofs << "," << inp_end << "] => [" << bl_ofs << "," << bl_end << "]" << dendl; - if (next) - return next->fixup_range(bl_ofs, bl_end); - return 0; } diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index bd3cfe2a4e2d..17b72e885e98 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -2783,10 +2783,6 @@ void RGWGetObj::execute(optional_yield y) goto done_err; total_len = (ofs <= end ? end + 1 - ofs : 0); - ofs_x = ofs; - end_x = end; - filter->fixup_range(ofs_x, end_x); - /* Check whether the object has expired. Swift API documentation * stands that we should return 404 Not Found in such case. */ if (need_object_expiration() && s->object->is_expired()) { @@ -2804,12 +2800,15 @@ void RGWGetObj::execute(optional_yield y) attr_iter != attrs.end() ? &(attr_iter->second) : nullptr); if (decrypt != nullptr) { filter = decrypt.get(); - filter->fixup_range(ofs_x, end_x); } if (op_ret < 0) { goto done_err; } + ofs_x = ofs; + end_x = end; + filter->fixup_range(ofs_x, end_x); + if (!get_data || ofs > end) { send_response_data(bl, 0, 0);