Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Always restart daemon when full-disk access message has been shown #7189

Merged
merged 2 commits into from
Nov 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 22 additions & 5 deletions desktop/packages/mullvad-vpn/src/main/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
AccessMethodSetting,
DaemonEvent,
DeviceEvent,
ErrorStateCause,
IRelayListWithEndpointData,
ISettings,
TunnelState,
Expand Down Expand Up @@ -130,6 +131,10 @@ class ApplicationMain

private currentApiAccessMethod?: AccessMethodSetting;

// If set to true, the GUI should restart the daemon when it exits.
// This is to make sure that the daemon is granted full-disk access.
private needFullDiskAccess = false;

public constructor() {
this.daemonRpc = new DaemonRpc(
new ConnectionObserver(this.onDaemonConnected, this.onDaemonDisconnected),
Expand Down Expand Up @@ -324,7 +329,7 @@ class ApplicationMain
};

private onBeforeQuit = async (event: Electron.Event) => {
if (this.tunnelState.hasReceivedFullDiskAccessError) {
if (this.needFullDiskAccess) {
await this.daemonRpc.prepareRestart(true);
}

Expand Down Expand Up @@ -537,7 +542,7 @@ class ApplicationMain

// fetch the tunnel state
try {
this.tunnelState.handleNewTunnelState(await this.daemonRpc.getState());
this.handleNewTunnelState(await this.daemonRpc.getState());
} catch (e) {
const error = e as Error;
log.error(`Failed to fetch the tunnel state: ${error.message}`);
Expand Down Expand Up @@ -692,7 +697,7 @@ class ApplicationMain
const daemonEventListener = new SubscriptionListener(
(daemonEvent: DaemonEvent) => {
if ('tunnelState' in daemonEvent) {
this.tunnelState.handleNewTunnelState(daemonEvent.tunnelState);
this.handleNewTunnelState(daemonEvent.tunnelState);
} else if ('settings' in daemonEvent) {
this.setSettings(daemonEvent.settings);
} else if ('relayList' in daemonEvent) {
Expand Down Expand Up @@ -738,6 +743,16 @@ class ApplicationMain
void this.updateSplitTunnelingApplications(newSettings.splitTunnel.appsList);
}

private handleNewTunnelState(newState: TunnelState) {
this.tunnelState.handleNewTunnelState(newState);
if (
newState.state === 'error' &&
newState.details?.cause === ErrorStateCause.needFullDiskPermissions
) {
this.needFullDiskAccess = true;
}
}

private setRelayList(relayList: IRelayListWithEndpointData) {
this.relayList = relayList;
IpcMainEventChannel.relays.notify?.(relayList);
Expand Down Expand Up @@ -832,8 +847,10 @@ class ApplicationMain
splitTunneling!.removeApplicationFromCache(application);
return Promise.resolve();
});
IpcMainEventChannel.macOsSplitTunneling.handleNeedFullDiskPermissions(() => {
return this.daemonRpc.needFullDiskPermissions();
IpcMainEventChannel.macOsSplitTunneling.handleNeedFullDiskPermissions(async () => {
const fullDiskState = await this.daemonRpc.needFullDiskPermissions();
this.needFullDiskAccess = fullDiskState;
return fullDiskState;
});

IpcMainEventChannel.app.handleQuit(() => this.disconnectAndQuit());
Expand Down
13 changes: 1 addition & 12 deletions desktop/packages/mullvad-vpn/src/main/tunnel-state.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { connectEnabled, disconnectEnabled, reconnectEnabled } from '../shared/connect-helper';
import { ErrorStateCause, ILocation, TunnelState } from '../shared/daemon-rpc-types';
import { ILocation, TunnelState } from '../shared/daemon-rpc-types';
import { Scheduler } from '../shared/scheduler';

export interface TunnelStateProvider {
Expand All @@ -20,15 +20,10 @@ export default class TunnelStateHandler {
// Scheduler for discarding the assumed next state.
private tunnelStateFallbackScheduler = new Scheduler();

private receivedFullDiskAccessError = false;

private lastKnownDisconnectedLocation: Partial<ILocation> | undefined;

public constructor(private delegate: TunnelStateHandlerDelegate) {}

public get hasReceivedFullDiskAccessError() {
return this.receivedFullDiskAccessError;
}
public get tunnelState() {
return this.tunnelStateValue;
}
Expand Down Expand Up @@ -58,12 +53,6 @@ export default class TunnelStateHandler {
}

public handleNewTunnelState(newState: TunnelState) {
if (newState.state === 'error' && newState.details) {
if (newState.details.cause === ErrorStateCause.needFullDiskPermissions) {
this.receivedFullDiskAccessError = true;
}
}

// If there's a fallback state set then the app is in an assumed next state and need to check
// if it's now reached or if the current state should be ignored and set as the fallback state.
if (this.tunnelStateFallback) {
Expand Down
Loading