]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: fix fixup_range cascade for compressed+encrypted objects 67966/head
authorMatthew N. Heler <matthew.heler@hotmail.com>
Sun, 22 Mar 2026 16:41:00 +0000 (11:41 -0500)
committerMatthew N. Heler <matthew.heler@hotmail.com>
Tue, 24 Mar 2026 19:45:58 +0000 (14:45 -0500)
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 <matthew.heler@hotmail.com>
src/rgw/rgw_crypt.cc
src/rgw/rgw_op.cc

index 8e8ffc2d8693a800827e2a66773320a045eda8ab..bef6a2eaeba9a4535e2c0c08ee9049b36ebf95ce 100644 (file)
@@ -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;
 }
 
index bd3cfe2a4e2d60b8f198d4d033b2761140cc8125..17b72e885e98da59253b0fb76bf9c89eb92a67ec 100644 (file)
@@ -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);