]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
messages,mds: Fix decoding of enum types on big-endian systems
authorUlrich Weigand <ulrich.weigand@de.ibm.com>
Tue, 18 Aug 2020 07:51:22 +0000 (09:51 +0200)
committerNathan Cutler <ncutler@suse.com>
Fri, 25 Sep 2020 14:09:25 +0000 (16:09 +0200)
When a struct member that has enum type needs to be encoded or
decoded, we need to use an explicit integer type, since there
are no encode routines for the enum type.  (This is probably
to avoid introducing dependencies on implementation-defined
choices by the compiler to use a particular underlying type.)

This leads to code sequences along the lines of:
  encode((int32_t)state, bl);
and
  decode((int32_t&)(state), bl);

The encode line is actually fine, but the decode line is
incorrect on big-endian systems if the underlying type of
the enum differs from the explicitly chosen integer type.

This is because this performs in effect a pointer cast,
and will write the decoded int32_t value into the memory
backing the "state" member variable.  If the sizes differ,
the value is written into the wrong bytes of "state" on
big-endian systems.

This patch fixes the problem by decoding into an intermediate
variable of the integer type first, and then casting the result
while assigning to the struct member of enum type.

This bug showed up initially as invalid health-status values
causing Ceph daemon aborts on s390x.  I've tried to find and
fix all other instances of the same enum decode pattern as well.

Fixes: https://tracker.ceph.com/issues/47015
Signed-off-by: Ulrich Weigand <ulrich.weigand@de.ibm.com>
(cherry picked from commit 7ed716823fd02d84ea53cb61350bf14f248ebb8b)

Conflicts:
src/mds/PurgeQueue.cc
- nautilus has "p.advance(pad_size)", instead of "p += pad_size",
  in the line immediately preceding the first change

src/mds/MDSMap.cc
src/mds/PurgeQueue.cc
src/messages/MMDSBeacon.h
src/messages/MMgrReport.h

index 07fdbd318d61117be8c5b675e65e070046a58573..27753c6ec0af1de74fc3196f98a0ac7be9859964 100644 (file)
@@ -549,7 +549,9 @@ void MDSMap::mds_info_t::decode(bufferlist::const_iterator& bl)
   decode(name, bl);
   decode(rank, bl);
   decode(inc, bl);
-  decode((int32_t&)(state), bl);
+  int32_t raw_state;
+  decode(raw_state, bl);
+  state = (MDSMap::DaemonState)raw_state;
   decode(state_seq, bl);
   decode(addrs, bl);
   decode(laggy_since, bl);
index f730e4b076050e1925343998a195a651e5f51096..b7db57aa2b46d8787ab001ec4832bb8880978a22 100644 (file)
@@ -65,7 +65,9 @@ void PurgeItem::decode(bufferlist::const_iterator &p)
       decode(stamp, p);
       decode(pad_size, p);
       p.advance(pad_size);
-      decode((uint8_t&)action, p);
+      uint8_t raw_action;
+      decode(raw_action, p);
+      action = (Action)raw_action;
       decode(ino, p);
       decode(size, p);
       decode(layout, p);
@@ -80,7 +82,9 @@ void PurgeItem::decode(bufferlist::const_iterator &p)
     }
   }
   if (!done) {
-    decode((uint8_t&)action, p);
+    uint8_t raw_action;
+    decode(raw_action, p);
+    action = (Action)raw_action;
     decode(ino, p);
     decode(size, p);
     decode(layout, p);
index 24922ae333036930d1497dfda9843bc4bde7d81e..10b5ae46f3cae0023a9593056da20febcb010f2a 100644 (file)
@@ -131,9 +131,13 @@ struct MDSHealthMetric
 
   void decode(bufferlist::const_iterator& bl) {
     DECODE_START(1, bl);
-    decode((uint16_t&)type, bl);
+    uint16_t raw_type;
+    decode(raw_type, bl);
+    type = (mds_metric_t)raw_type;
     ceph_assert(type != MDS_HEALTH_NULL);
-    decode((uint8_t&)sev, bl);
+    uint8_t raw_sev;
+    decode(raw_sev, bl);
+    sev = (health_status_t)raw_sev;
     decode(message, bl);
     decode(metadata, bl);
     DECODE_FINISH(bl);
@@ -264,7 +268,9 @@ public:
     paxos_decode(p);
     decode(fsid, p);
     decode(global_id, p);
-    decode((__u32&)state, p);
+    __u32 raw_state;
+    decode(raw_state, p);
+    state = (MDSMap::DaemonState)raw_state;
     decode(seq, p);
     decode(name, p);
     {
index 84c96e7f200f3e711eef74f95b5d34a9faa9cb1a..e98871178d19dc50fa2a7d6575b90fe866c2ddfd 100644 (file)
@@ -59,12 +59,16 @@ public:
     decode(path, p);
     decode(description, p);
     decode(nick, p);
-    decode((uint8_t&)type, p);
+    uint8_t raw_type;
+    decode(raw_type, p);
+    type = (enum perfcounter_type_d)raw_type;
     if (struct_v >= 2) {
       decode(priority, p);
     }
     if (struct_v >= 3) {
-      decode((uint8_t&)unit, p);
+      uint8_t raw_unit;
+      decode(raw_unit, p);
+      unit = (enum unit_t)raw_unit;
     }
     DECODE_FINISH(p);
   }