Skip to content

Commit

Permalink
mon: validate states transmitted in beacons
Browse files Browse the repository at this point in the history
Since FSMap was added, the state of a daemon can lead
to an entirely invalid map, but we were letting daemons
send any state they wanted.

Especially, we must not allow standby daemons to set
any state other than STANDBY.

Fixes: http://tracker.ceph.com/issues/16592
Signed-off-by: John Spray <john.spray@redhat.com>
  • Loading branch information
John Spray committed Jul 28, 2016
1 parent 1194331 commit 8a8c26b
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 22 deletions.
26 changes: 26 additions & 0 deletions src/mds/MDSMap.cc
Expand Up @@ -727,3 +727,29 @@ MDSMap::availability_t MDSMap::is_cluster_available() const
return STUCK_UNAVAILABLE;
}
}

bool MDSMap::state_transition_valid(DaemonState prev, DaemonState next)
{
bool state_valid = true;
if (next != prev) {
if (prev == MDSMap::STATE_REPLAY) {
if (next != MDSMap::STATE_RESOLVE && next != MDSMap::STATE_RECONNECT) {
state_valid = false;
}
} else if (prev == MDSMap::STATE_REJOIN) {
if (next != MDSMap::STATE_ACTIVE
&& next != MDSMap::STATE_CLIENTREPLAY
&& next != MDSMap::STATE_STOPPED) {
state_valid = false;
}
} else if (prev >= MDSMap::STATE_RECONNECT && prev < MDSMap::STATE_ACTIVE) {
// Once I have entered replay, the only allowable transitions are to
// the next next along in the sequence.
if (next != prev + 1) {
state_valid = false;
}
}
}

return state_valid;
}
2 changes: 2 additions & 0 deletions src/mds/MDSMap.h
Expand Up @@ -628,6 +628,8 @@ class MDSMap {

void dump(Formatter *f) const;
static void generate_test_instances(list<MDSMap*>& ls);

static bool state_transition_valid(DaemonState prev, DaemonState next);
};
WRITE_CLASS_ENCODER_FEATURES(MDSMap::mds_info_t)
WRITE_CLASS_ENCODER_FEATURES(MDSMap)
Expand Down
23 changes: 1 addition & 22 deletions src/mds/MDSRank.cc
Expand Up @@ -1409,28 +1409,7 @@ void MDSRankDispatcher::handle_mds_map(
}

// Validate state transitions while I hold a rank
bool state_valid = true;
if (state != oldstate) {
if (oldstate == MDSMap::STATE_REPLAY) {
if (state != MDSMap::STATE_RESOLVE && state != MDSMap::STATE_RECONNECT) {
state_valid = false;
}
} else if (oldstate == MDSMap::STATE_REJOIN) {
if (state != MDSMap::STATE_ACTIVE
&& state != MDSMap::STATE_CLIENTREPLAY
&& state != MDSMap::STATE_STOPPED) {
state_valid = false;
}
} else if (oldstate >= MDSMap::STATE_RECONNECT && oldstate < MDSMap::STATE_ACTIVE) {
// Once I have entered replay, the only allowable transitions are to
// the next state along in the sequence.
if (state != oldstate + 1) {
state_valid = false;
}
}
}

if (!state_valid) {
if (!MDSMap::state_transition_valid(oldstate, state)) {
derr << "Invalid state transition " << ceph_mds_state_name(oldstate)
<< "->" << ceph_mds_state_name(state) << dendl;
respawn();
Expand Down
16 changes: 16 additions & 0 deletions src/mon/MDSMonitor.cc
Expand Up @@ -645,7 +645,23 @@ bool MDSMonitor::prepare_beacon(MonOpRequestRef op)
mon->monmap->fsid, m->get_global_id(),
m->get_name(), fsmap.get_epoch(), state, seq,
CEPH_FEATURES_SUPPORTED_DEFAULT));
} else if (info.state == MDSMap::STATE_STANDBY && state != info.state) {
// Standby daemons should never modify their own
// state. Reject any attempts to do so.
derr << "standby " << gid << " attempted to change state to "
<< ceph_mds_state_name(state) << ", rejecting" << dendl;
return true;
} else if (info.state != MDSMap::STATE_STANDBY && state != info.state &&
!MDSMap::state_transition_valid(info.state, state)) {
// Validate state transitions for daemons that hold a rank
derr << "daemon " << gid << " (rank " << info.rank << ") "
<< "reported invalid state transition "
<< ceph_mds_state_name(info.state) << " -> "
<< ceph_mds_state_name(state) << dendl;
return true;
} else {
// Made it through special cases and validations, record the
// daemon's reported state to the FSMap.
pending_fsmap.modify_daemon(gid, [state, seq](MDSMap::mds_info_t *info) {
info->state = state;
info->state_seq = seq;
Expand Down

0 comments on commit 8a8c26b

Please sign in to comment.