summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2025-05-22 15:43:29 +0200
committerDavid Lönnhager <david.l@mullvad.net>2025-05-22 15:43:29 +0200
commita9d8ce8abf4073f72fb94fb6a05fb6c1b43069c3 (patch)
treef19927be2235bd21948ae5184fa1c3194a6138f6
parent99eab53e5b238c0393a8460b08f358fcb12c242d (diff)
parent922f9c65a9a562685d38ec28ed37e79235c5adc7 (diff)
downloadmullvadvpn-a9d8ce8abf4073f72fb94fb6a05fb6c1b43069c3.tar.xz
mullvadvpn-a9d8ce8abf4073f72fb94fb6a05fb6c1b43069c3.zip
Merge branch 'fix-early-boot-settings'
-rw-r--r--CHANGELOG.md2
-rw-r--r--mullvad-daemon/src/early_boot_firewall.rs5
-rw-r--r--mullvad-daemon/src/settings/mod.rs38
3 files changed, 31 insertions, 14 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 16a59fb8b4..195235f446 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -45,6 +45,8 @@ supported.
#### Linux
- Fix syntax error in Apparmor profile.
+- Fix issue where settings were lost after an upgrade if `mullvad-daemon` was not restarted
+ before `mullvad-early-boot-blocking.service`. That is, before a reboot.
#### Windows
- Fix issue where daemon got stuck trying to connect only over IPv4 (or only IPv6).
diff --git a/mullvad-daemon/src/early_boot_firewall.rs b/mullvad-daemon/src/early_boot_firewall.rs
index 6195c15bb4..6bdfc62cbd 100644
--- a/mullvad-daemon/src/early_boot_firewall.rs
+++ b/mullvad-daemon/src/early_boot_firewall.rs
@@ -33,6 +33,9 @@ pub async fn initialize_firewall() -> Result<(), Error> {
async fn get_allow_lan() -> Result<bool, Error> {
let path = mullvad_paths::settings_dir()?;
- let settings = SettingsPersister::load(&path).await;
+ // NOTE: This may fail if the daemon has not been restarted after an upgrade.
+ // This will cause `allow_lan` to be disabled during early boot. This
+ // is probably acceptable.
+ let settings = SettingsPersister::read_only(&path).await;
Ok(settings.allow_lan)
}
diff --git a/mullvad-daemon/src/settings/mod.rs b/mullvad-daemon/src/settings/mod.rs
index 030bedebaa..03d027acb4 100644
--- a/mullvad-daemon/src/settings/mod.rs
+++ b/mullvad-daemon/src/settings/mod.rs
@@ -99,23 +99,15 @@ pub struct SettingsPersister {
pub type MadeChanges = bool;
impl SettingsPersister {
- /// Loads user settings from file. If it fails, it returns the defaults.
+ /// Loads user settings from file. If it fails, it returns the defaults, and overwrites the old
+ /// settings.
pub async fn load(settings_dir: &Path) -> Self {
let path = settings_dir.join(SETTINGS_FILE);
let LoadSettingsResult {
- mut settings,
- mut should_save,
+ settings,
+ should_save,
} = Self::load_inner(|| Self::load_from_file(&path)).await;
- if cfg!(target_os = "android") {
- // Auto-connect is managed by Android itself.
- settings.auto_connect = false;
- }
- if crate::version::is_beta_version() {
- should_save |= !settings.show_beta_releases;
- settings.show_beta_releases = true;
- }
-
let mut persister = SettingsPersister {
settings,
path,
@@ -134,6 +126,15 @@ impl SettingsPersister {
persister
}
+ /// Loads user settings from file. The only difference between this and [Self::load] is that
+ /// it is read-only.
+ pub async fn read_only(settings_dir: &Path) -> Settings {
+ let path = settings_dir.join(SETTINGS_FILE);
+ let LoadSettingsResult { settings, .. } =
+ Self::load_inner(|| Self::load_from_file(&path)).await;
+ settings
+ }
+
/// Loads user settings, returning default settings if it should fail.
///
/// `load_settings` allows the caller to decide how to load [`Settings`]
@@ -147,7 +148,7 @@ impl SettingsPersister {
F: FnOnce() -> R,
R: std::future::Future<Output = Result<Settings, Error>>,
{
- match load_settings().await {
+ let mut result = match load_settings().await {
Ok(settings) => LoadSettingsResult {
settings,
should_save: false,
@@ -180,7 +181,18 @@ impl SettingsPersister {
should_save: true,
}
}
+ };
+
+ if cfg!(target_os = "android") {
+ // Auto-connect is managed by Android itself.
+ result.settings.auto_connect = false;
}
+ if crate::version::is_beta_version() {
+ result.should_save |= !result.settings.show_beta_releases;
+ result.settings.show_beta_releases = true;
+ }
+
+ result
}
async fn load_from_file<P>(path: P) -> Result<Settings, Error>