From: Patrick Donnelly Date: Thu, 13 Nov 2025 19:51:20 +0000 (-0500) Subject: include: detect corrupt frag from byteswap X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=cbd59f9afec32575efa3705e9e1eaaaa46dd7132;p=ceph-ci.git include: detect corrupt frag from byteswap Fixes: https://tracker.ceph.com/issues/73792 Signed-off-by: Patrick Donnelly (cherry picked from commit 59461534437ed0c422d42b265ab0f401053c8a7f) Resolves: rhbz#2414841 --- diff --git a/src/common/frag.cc b/src/common/frag.cc index 452f30ff5dc..0808e6bee12 100644 --- a/src/common/frag.cc +++ b/src/common/frag.cc @@ -16,7 +16,9 @@ #include "include/types.h" // for operator<<(std::set) #include "common/debug.h" #include "common/Formatter.h" +#include "common/StackStringStream.h" +#include #include #include @@ -38,6 +40,24 @@ void frag_t::encode(ceph::buffer::list& bl) const { void frag_t::decode(ceph::buffer::list::const_iterator& p) { ceph::decode(_enc, p); + if (!is_frag_valid()) { + /* Oops, did this get encoded as big-endian? + * See: https://tracker.ceph.com/issues/73792 + */ + auto nfg = frag_t(boost::endian::endian_reverse(_enc)); + if (nfg.is_frag_valid()) { + std::cerr << "correcting byte swapped frag_t(0x" << std::hex << std::setfill('0') << std::setw(8) << _enc + << ") to frag_t(0x" << std::hex << std::setfill('0') << std::setw(8) << nfg._enc << ")" + << " aka " << nfg + << std::endl; + _enc = nfg._enc; + } else { + CachedStackStringStream css; + *css << "Invalid frag_t(0x" << std::hex << std::setfill('0') << std::setw(8) << _enc << ")"; + throw ceph::buffer::malformed_input(css->str()); + } + } + } void frag_t::dump(ceph::Formatter *f) const { diff --git a/src/include/frag.h b/src/include/frag.h index 0ee481a9869..f30981c5818 100644 --- a/src/include/frag.h +++ b/src/include/frag.h @@ -100,6 +100,18 @@ public: operator _frag_t() const { return _enc; } + bool is_frag_valid() const { + if (bits() > 24) { + /* bits must be in range [0,24] */ + return false; + } else if ((value() & ~mask()) != 0) { + /* unused bits must be 0 */ + return false; + } else { + return true; + } + } + // tests bool contains(unsigned v) const { return ceph_frag_contains_value(_enc, v); } bool contains(frag_t sub) const { return ceph_frag_contains_frag(_enc, sub._enc); }