Skip to content

Commit 3c90917

Browse files
committed
fix: Use registration token to prevent double meta node/target id use
This takes the previously ignored node_alias field on received heartbeats from meta nodes (only!) and stores it together with the meta target as a registration token. When the field is already filled, a mismatch will fail the heartbeat.
1 parent 0662a6a commit 3c90917

File tree

3 files changed

+48
-10
lines changed

3 files changed

+48
-10
lines changed

mgmtd/src/bee_msg/node.rs

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -195,10 +195,46 @@ async fn update_node(msg: RegisterNode, ctx: &Context) -> Result<NodeId> {
195195
}
196196
}
197197

198+
let new_alias_or_reg_token = String::from_utf8(msg.node_alias)?;
199+
198200
let (node, is_new) = if let Some(node) = node {
199201
// Existing node, update data
200202
db::node::update(tx, node.uid, msg.port, machine_uuid)?;
201203

204+
// If the updated node is a meta node, check if its corresponding target has a
205+
// registration token
206+
if msg.node_type == NodeType::Meta {
207+
let stored_reg_token: Option<String> = tx.query_row(
208+
sql!("SELECT reg_token FROM meta_targets WHERE node_id = ?1"),
209+
[node.num_id()],
210+
|row| row.get(0),
211+
)?;
212+
213+
if let Some(ref t) = stored_reg_token
214+
&& t != &new_alias_or_reg_token
215+
{
216+
bail!(
217+
"Meta node {} has already been registered and its \
218+
registration token ({}) does not match the stored token ({})",
219+
node,
220+
new_alias_or_reg_token,
221+
t
222+
);
223+
} else if stored_reg_token.is_none() {
224+
tx.execute(
225+
sql!(
226+
"UPDATE targets SET reg_token = ?1
227+
WHERE node_id = ?2 AND node_type = ?3"
228+
),
229+
rusqlite::params![
230+
new_alias_or_reg_token,
231+
node.num_id(),
232+
NodeType::Meta.sql_variant()
233+
],
234+
)?;
235+
}
236+
}
237+
202238
(node, false)
203239
} else {
204240
// New node, do additional checks and insert data
@@ -216,9 +252,7 @@ async fn update_node(msg: RegisterNode, ctx: &Context) -> Result<NodeId> {
216252
// updated to no longer start with a number, thus it is unlikely this
217253
// would happen unless BeeGFS 8 was mounted by a BeeGFS 7 client.
218254

219-
let new_alias = String::from_utf8(msg.node_alias)
220-
.ok()
221-
.and_then(|s| Alias::try_from(s).ok());
255+
let new_alias = Alias::try_from(new_alias_or_reg_token.clone()).ok();
222256

223257
if new_alias.is_none() {
224258
log::warn!(
@@ -246,7 +280,7 @@ client version < 8.0)"
246280
);
247281
};
248282

249-
db::target::insert_meta(tx, target_id)?;
283+
db::target::insert_meta(tx, target_id, Some(&new_alias_or_reg_token))?;
250284
}
251285

252286
(node, true)

mgmtd/src/db/import_v7.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ fn meta_nodes(tx: &Transaction, f: &Path) -> Result<(NodeId, bool)> {
144144
);
145145
};
146146

147-
target::insert_meta(tx, target_id)?;
147+
target::insert_meta(tx, target_id, None)?;
148148
}
149149

150150
if root_id == 0 {

mgmtd/src/db/target.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,11 @@ pub(crate) fn validate_ids(
3737
///
3838
/// BeeGFS doesn't really support meta targets at the moment, so there always must be exactly one
3939
/// meta target per meta node with their IDs being the same.
40-
pub(crate) fn insert_meta(tx: &Transaction, target_id: TargetId) -> Result<()> {
40+
pub(crate) fn insert_meta(
41+
tx: &Transaction,
42+
target_id: TargetId,
43+
reg_token: Option<&str>,
44+
) -> Result<()> {
4145
let target_id = if target_id == 0 {
4246
misc::find_new_id(tx, "targets", "target_id", NodeType::Meta, 1..=0xFFFF)?
4347
} else {
@@ -47,7 +51,7 @@ pub(crate) fn insert_meta(tx: &Transaction, target_id: TargetId) -> Result<()> {
4751
insert(
4852
tx,
4953
target_id,
50-
None,
54+
reg_token,
5155
NodeTypeServer::Meta,
5256
Some(target_id.into()),
5357
)?;
@@ -271,10 +275,10 @@ mod test {
271275
#[test]
272276
fn set_get_meta() {
273277
with_test_data(|tx| {
274-
super::insert_meta(tx, 1).unwrap_err();
275-
super::insert_meta(tx, 99).unwrap();
278+
super::insert_meta(tx, 1, None).unwrap_err();
279+
super::insert_meta(tx, 99, None).unwrap();
276280
// existing id
277-
super::insert_meta(tx, 99).unwrap_err();
281+
super::insert_meta(tx, 99, None).unwrap_err();
278282

279283
let targets: i64 = tx
280284
.query_row(sql!("SELECT COUNT(*) FROM meta_targets"), [], |row| {

0 commit comments

Comments
 (0)