tape: improve catalog consistency checks

Try to check if we read the correct catalog by verifying uuid, media_set_uuid
and seq_nr.

Note: this changes the catalog format again.
This commit is contained in:
Dietmar Maurer 2021-03-18 08:43:55 +01:00
parent caf76ec592
commit 237314ad0d
4 changed files with 53 additions and 12 deletions

View File

@ -432,7 +432,7 @@ pub fn list_content(
.generate_media_set_name(&set.uuid, template)
.unwrap_or_else(|_| set.uuid.to_string());
let catalog = MediaCatalog::open(status_path, &media_id.label.uuid, false, false)?;
let catalog = MediaCatalog::open(status_path, &media_id, false, false)?;
for (store, content) in catalog.content() {
for snapshot in content.snapshot_index.keys() {

View File

@ -213,6 +213,17 @@ pub struct SnapshotArchiveHeader {
pub store: String,
}
#[derive(Deserialize, Serialize)]
/// Header for Catalog archives
pub struct CatalogArchiveHeader {
/// The uuid of the media the catalog is for
pub uuid: Uuid,
/// The media set uuid the catalog is for
pub media_set_uuid: Uuid,
/// Media sequence number
pub seq_nr: u64,
}
#[derive(Serialize,Deserialize,Clone,Debug)]
/// Media Label
///

View File

@ -26,6 +26,7 @@ use crate::{
backup::BackupDir,
tape::{
MediaId,
file_formats::MediaSetLabel,
},
};
@ -136,11 +137,13 @@ impl MediaCatalog {
/// Open a catalog database, load into memory
pub fn open(
base_path: &Path,
uuid: &Uuid,
media_id: &MediaId,
write: bool,
create: bool,
) -> Result<Self, Error> {
let uuid = &media_id.label.uuid;
let mut path = base_path.to_owned();
path.push(uuid.to_string());
path.set_extension("log");
@ -169,7 +172,7 @@ impl MediaCatalog {
pending: Vec::new(),
};
let found_magic_number = me.load_catalog(&mut file)?;
let found_magic_number = me.load_catalog(&mut file, media_id.media_set_label.as_ref())?;
if !found_magic_number {
me.pending.extend(&Self::PROXMOX_BACKUP_MEDIA_CATALOG_MAGIC_1_1);
@ -230,10 +233,10 @@ impl MediaCatalog {
me.pending.extend(&Self::PROXMOX_BACKUP_MEDIA_CATALOG_MAGIC_1_1);
me.register_label(&media_id.label.uuid, 0)?;
me.register_label(&media_id.label.uuid, 0, 0)?;
if let Some(ref set) = media_id.media_set_label {
me.register_label(&set.uuid, 1)?;
me.register_label(&set.uuid, set.seq_nr, 1)?;
}
me.commit()?;
@ -364,12 +367,16 @@ impl MediaCatalog {
}
}
fn check_register_label(&self, file_number: u64) -> Result<(), Error> {
fn check_register_label(&self, file_number: u64, uuid: &Uuid) -> Result<(), Error> {
if file_number >= 2 {
bail!("register label failed: got wrong file number ({} >= 2)", file_number);
}
if file_number == 0 && uuid != &self.uuid {
bail!("register label failed: uuid does not match");
}
if self.current_archive.is_some() {
bail!("register label failed: inside chunk archive");
}
@ -389,15 +396,21 @@ impl MediaCatalog {
/// Register media labels (file 0 and 1)
pub fn register_label(
&mut self,
uuid: &Uuid, // Uuid form MediaContentHeader
uuid: &Uuid, // Media/MediaSet Uuid
seq_nr: u64, // onyl used for media set labels
file_number: u64,
) -> Result<(), Error> {
self.check_register_label(file_number)?;
self.check_register_label(file_number, uuid)?;
if file_number == 0 && seq_nr != 0 {
bail!("register_label failed - seq_nr should be 0 - iternal error");
}
let entry = LabelEntry {
file_number,
uuid: *uuid.as_bytes(),
seq_nr,
};
if self.log_to_stdout {
@ -608,7 +621,11 @@ impl MediaCatalog {
Ok(())
}
fn load_catalog(&mut self, file: &mut File) -> Result<bool, Error> {
fn load_catalog(
&mut self,
file: &mut File,
media_set_label: Option<&MediaSetLabel>,
) -> Result<bool, Error> {
let mut file = BufReader::new(file);
let mut found_magic_number = false;
@ -713,7 +730,18 @@ impl MediaCatalog {
let file_number = entry.file_number;
let uuid = Uuid::from(entry.uuid);
self.check_register_label(file_number)?;
self.check_register_label(file_number, &uuid)?;
if file_number == 1 {
if let Some(set) = media_set_label {
if set.uuid != uuid {
bail!("got unexpected media set uuid");
}
if set.seq_nr != entry.seq_nr {
bail!("got unexpected media set sequence number");
}
}
}
self.last_entry = Some((uuid, file_number));
}
@ -789,6 +817,7 @@ impl MediaSetCatalog {
struct LabelEntry {
file_number: u64,
uuid: [u8;16],
seq_nr: u64, // only used for media set labels
}
#[derive(Endian)]

View File

@ -253,9 +253,10 @@ impl PoolWriter {
// load all catalogs read-only at start
for media_uuid in pool.current_media_list()? {
let media_info = pool.lookup_media(media_uuid).unwrap();
let media_catalog = MediaCatalog::open(
Path::new(TAPE_STATUS_DIR),
&media_uuid,
media_info.id(),
false,
false,
)?;
@ -655,7 +656,7 @@ fn update_media_set_label(
if new_set.encryption_key_fingerprint != media_set_label.encryption_key_fingerprint {
bail!("detected changed encryption fingerprint - internal error");
}
media_catalog = MediaCatalog::open(status_path, &media_id.label.uuid, true, false)?;
media_catalog = MediaCatalog::open(status_path, &media_id, true, false)?;
} else {
worker.log(
format!("wrinting new media set label (overwrite '{}/{}')",