Skip to content

Commit bac02fc

Browse files
committed
rgw_cksum: permit fallback to checksum-type from create-multipart, in upload-part
There appear to be workloads that provide a checksum algorithm in create-multipart-upload, but do not provide (what must be) the corresponding algorithm when uploading the parts. (complete-multipart-upload has no checksum argument, the value is implicit.) This behavior is inconsistent with at least some SDKs, but it is possibly accepted behavior in AWS S3, and is not logically necessary, since the originally supplied checksum type is already known. Therefore, change the behavior of upload-part to fall back to a checksum type that was sent with the corresponding create-multipart-upload request, if one is present, rather than failing with InvalidRequest. Fixes: https://tracker.ceph.com/issues/68513 Signed-off-by: Matt Benjamin <[email protected]> (cherry picked from commit 6b487a4)
1 parent 5c4d594 commit bac02fc

File tree

4 files changed

+58
-7
lines changed

4 files changed

+58
-7
lines changed

src/rgw/rgw_cksum_pipe.cc

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <string>
1919
#include <fmt/format.h>
2020
#include <boost/algorithm/string.hpp>
21+
#include "rgw_cksum.h"
2122
#include "rgw_common.h"
2223
#include "common/dout.h"
2324
#include "rgw_client_io.h"
@@ -34,7 +35,8 @@ namespace rgw::putobj {
3435
{}
3536

3637
std::unique_ptr<RGWPutObj_Cksum> RGWPutObj_Cksum::Factory(
37-
rgw::sal::DataProcessor* next, const RGWEnv& env)
38+
rgw::sal::DataProcessor* next, const RGWEnv& env,
39+
rgw::cksum::Type override_type)
3840
{
3941
/* look for matching headers */
4042
auto algo_header = cksum_algorithm_hdr(env);
@@ -49,6 +51,13 @@ namespace rgw::putobj {
4951
throw rgw::io::Exception(EINVAL, std::system_category());
5052
}
5153
/* no checksum header */
54+
if (override_type != rgw::cksum::Type::none) {
55+
/* XXXX safe? do we need to fixup env as well? */
56+
auto algo_header = cksum_algorithm_hdr(override_type);
57+
return
58+
std::make_unique<RGWPutObj_Cksum>(
59+
next, override_type, std::move(algo_header));
60+
}
5261
return std::unique_ptr<RGWPutObj_Cksum>();
5362
}
5463

src/rgw/rgw_cksum_pipe.h

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <tuple>
2121
#include <cstring>
2222
#include <boost/algorithm/string/case_conv.hpp>
23+
#include "rgw_cksum.h"
2324
#include "rgw_cksum_digest.h"
2425
#include "rgw_common.h"
2526
#include "rgw_putobj.h"
@@ -29,6 +30,38 @@ namespace rgw::putobj {
2930
namespace cksum = rgw::cksum;
3031
using cksum_hdr_t = std::pair<const char*, const char*>;
3132

33+
static inline const cksum_hdr_t cksum_algorithm_hdr(rgw::cksum::Type t) {
34+
static constexpr std::string_view hdr =
35+
"HTTP_X_AMZ_SDK_CHECKSUM_ALGORITHM";
36+
using rgw::cksum::Type;
37+
switch (t) {
38+
case Type::sha256:
39+
return cksum_hdr_t(hdr.data(), "SHA256");
40+
break;
41+
case Type::crc32:
42+
return cksum_hdr_t(hdr.data(), "CRC32");
43+
break;
44+
case Type::crc32c:
45+
return cksum_hdr_t(hdr.data(), "CRC32C");
46+
break;
47+
case Type::xxh3:
48+
return cksum_hdr_t(hdr.data(), "XX3");
49+
break;
50+
case Type::sha1:
51+
return cksum_hdr_t(hdr.data(), "SHA1");
52+
break;
53+
case Type::sha512:
54+
return cksum_hdr_t(hdr.data(), "SHA512");
55+
break;
56+
case Type::blake3:
57+
return cksum_hdr_t(hdr.data(), "BLAKE3");
58+
break;
59+
default:
60+
break;
61+
};
62+
return cksum_hdr_t(nullptr, nullptr);;
63+
}
64+
3265
static inline const cksum_hdr_t cksum_algorithm_hdr(const RGWEnv& env) {
3366
/* If the individual checksum value you provide through
3467
x-amz-checksum-algorithm doesn't match the checksum algorithm
@@ -102,7 +135,8 @@ namespace rgw::putobj {
102135
using VerifyResult = std::tuple<bool, const cksum::Cksum&>;
103136

104137
static std::unique_ptr<RGWPutObj_Cksum> Factory(
105-
rgw::sal::DataProcessor* next, const RGWEnv&);
138+
rgw::sal::DataProcessor* next, const RGWEnv&,
139+
rgw::cksum::Type override_type);
106140

107141
RGWPutObj_Cksum(rgw::sal::DataProcessor* next, rgw::cksum::Type _type,
108142
cksum_hdr_t&& _hdr);

src/rgw/rgw_op.cc

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "common/ceph_json.h"
2626
#include "common/static_ptr.h"
2727
#include "common/perf_counters_key.h"
28+
#include "rgw_cksum.h"
2829
#include "rgw_cksum_digest.h"
2930
#include "rgw_common.h"
3031
#include "common/split.h"
@@ -4333,6 +4334,9 @@ void RGWPutObj::execute(optional_yield y)
43334334
}
43344335
return;
43354336
}
4337+
4338+
multipart_cksum_type = upload->cksum_type;
4339+
43364340
/* upload will go out of scope, so copy the dest placement for later use */
43374341
s->dest_placement = *pdest_placement;
43384342
pdest_placement = &s->dest_placement;
@@ -4463,11 +4467,12 @@ void RGWPutObj::execute(optional_yield y)
44634467
/* optional streaming checksum */
44644468
try {
44654469
cksum_filter =
4466-
rgw::putobj::RGWPutObj_Cksum::Factory(filter, *s->info.env);
4470+
rgw::putobj::RGWPutObj_Cksum::Factory(filter, *s->info.env, multipart_cksum_type);
44674471
} catch (const rgw::io::Exception& e) {
44684472
op_ret = -e.code().value();
44694473
return;
44704474
}
4475+
44714476
if (cksum_filter) {
44724477
filter = &*cksum_filter;
44734478
}
@@ -4614,25 +4619,26 @@ void RGWPutObj::execute(optional_yield y)
46144619

46154620
if (cksum_filter) {
46164621
const auto& hdr = cksum_filter->header();
4622+
auto expected_ck = cksum_filter->expected(*s->info.env);
46174623
auto cksum_verify =
46184624
cksum_filter->verify(*s->info.env); // valid or no supplied cksum
46194625
cksum = get<1>(cksum_verify);
4620-
if (std::get<0>(cksum_verify)) {
4626+
if ((!expected_ck) ||
4627+
std::get<0>(cksum_verify)) {
46214628
buffer::list cksum_bl;
46224629

46234630
ldpp_dout_fmt(this, 16,
46244631
"{} checksum verified "
46254632
"\n\tcomputed={} == \n\texpected={}",
46264633
hdr.second,
46274634
cksum->to_armor(),
4628-
cksum_filter->expected(*s->info.env));
4635+
(!!expected_ck) ? expected_ck : "(checksum unavailable)");
46294636

46304637
cksum->encode(cksum_bl);
46314638
emplace_attr(RGW_ATTR_CKSUM, std::move(cksum_bl));
46324639
} else {
46334640
/* content checksum mismatch */
46344641
auto computed_ck = cksum->to_armor();
4635-
auto expected_ck = cksum_filter->expected(*s->info.env);
46364642

46374643
ldpp_dout_fmt(this, 4,
46384644
"{} content checksum mismatch"
@@ -4835,7 +4841,8 @@ void RGWPostObj::execute(optional_yield y)
48354841
/* optional streaming checksum */
48364842
try {
48374843
cksum_filter =
4838-
rgw::putobj::RGWPutObj_Cksum::Factory(filter, *s->info.env);
4844+
rgw::putobj::RGWPutObj_Cksum::Factory(
4845+
filter, *s->info.env, rgw::cksum::Type::none /* no override */);
48394846
} catch (const rgw::io::Exception& e) {
48404847
op_ret = -e.code().value();
48414848
return;

src/rgw/rgw_op.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1238,6 +1238,7 @@ class RGWPutObj : public RGWOp {
12381238
std::string multipart_upload_id;
12391239
std::string multipart_part_str;
12401240
int multipart_part_num = 0;
1241+
rgw::cksum::Type multipart_cksum_type{rgw::cksum::Type::none};
12411242
jspan_ptr multipart_trace;
12421243

12431244
boost::optional<ceph::real_time> delete_at;

0 commit comments

Comments
 (0)