diff --git a/bcachefs.8 b/bcachefs.8 index 8ff51a7da..7f1c89189 100644 --- a/bcachefs.8 +++ b/bcachefs.8 @@ -380,6 +380,12 @@ is the path where the filesystem should be mounted. If not set, then the filesys but all steps preceding mounting the filesystem (e.g. asking for passphrase) will still be performed. .Pp the options are as follows: .Bl -tag -width Ds +.It Fl f , Fl -passphrase-file Ns = Ns Ar passphrase_file +Path to passphrase/key file +.sp +Precedes key_location/unlock_policy: if the filesystem can be decrypted by the specified passphrase +file, it is decrypted. (i.e. Regardless if "fail" is specified for key_location/unlock_policy.) +.El .It Fl o Ar options Mount options provided as a comma-separated list. See user guide for complete list. .Bl -tag -width Ds -compact @@ -393,6 +399,8 @@ Run fsck during mount Fix errors without asking during fsck .It Cm read_only Mount in read only mode +.It Cm passphrase_file Ns = Ns Ar passphrase_file +Path to passphrase/key file .It Cm version_upgrade .El .It Fl k , Fl -key-location Ns = Ns ( Cm fail | wait | ask ) @@ -408,6 +416,7 @@ prompt the user for password. .El .It Fl c , Fl -colorize Ns = Ns ( Cm true | false ) Force color on/off. Default: auto-detect TTY +.El .It Fl v Be verbose. Can be specified more than once. .El diff --git a/src/commands/mount.rs b/src/commands/mount.rs index f8edf9bcd..25e702696 100644 --- a/src/commands/mount.rs +++ b/src/commands/mount.rs @@ -317,6 +317,16 @@ fn devs_str_sbs_from_device( } } +fn parse_passphrase_file_from_mount_options(options: impl AsRef) -> Option { + options + .as_ref() + .split(",") + .fold(None, |_, next| match next { + x if x.starts_with("passphrase_file") => Some(PathBuf::from(x.split("=").nth(1).unwrap().to_string())), + _ => None, + }) +} + fn cmd_mount_inner(opt: Cli) -> anyhow::Result<()> { // Grab the udev information once let udev_info = udev_bcachefs_info()?; @@ -361,21 +371,15 @@ fn cmd_mount_inner(opt: Cli) -> anyhow::Result<()> { && !key::check_for_key(&key_name)? { // First by password_file, if available - let fallback_to_unlock_policy = if let Some(passphrase_file) = &opt.passphrase_file { - match key::read_from_passphrase_file( - &block_devices_to_mount[0], - passphrase_file.as_path(), - ) { - Ok(()) => { - // Decryption succeeded - false - } - Err(err) => { - // Decryption failed, fall back to unlock_policy - error!("Failed to decrypt using passphrase_file: {}", err); - true - } - } + let fallback_to_unlock_policy = if let Some(passphrase_file) = opt.passphrase_file { + // Unlock by passphrase_file specified by cli + debug!("Attempting to unlock the master key with the passphrase file specified by cli"); + attempt_unlock_master_key_with_passphrase_file(&block_devices_to_mount[0], passphrase_file) + } else if let Some(passphrase_file) = parse_passphrase_file_from_mount_options(&opt.options) { + // Unlock by passphrase_file specified by mount options + debug!("Attempting to unlock the master key with the passphrase_file specified in the mount options"); + attempt_unlock_master_key_with_passphrase_file(&block_devices_to_mount[0], passphrase_file) + } else { // No passphrase_file specified, fall back to unlock_policy true @@ -405,6 +409,20 @@ fn cmd_mount_inner(opt: Cli) -> anyhow::Result<()> { Ok(()) } +fn attempt_unlock_master_key_with_passphrase_file(block_device: &bch_sb_handle, passphrase_file: PathBuf) -> bool { + match key::read_from_passphrase_file(block_device, passphrase_file.as_path()) { + Ok(()) => { + // Decryption succeeded + false + } + Err(err) => { + // Decryption failed, fall back to unlock_policy + error!("Failed to decrypt using passphrase_file: {}", err); + true + } + } +} + pub fn mount(mut argv: Vec, symlink_cmd: Option<&str>) -> i32 { // If the bcachefs tool is being called as "bcachefs mount dev ..." (as opposed to via a // symlink like "/usr/sbin/mount.bcachefs dev ...", then we need to pop the 0th argument