util: Wait for initial name owners in DBusSenderCheck before checking

Otherwise an allowed caller might get rejected if the call is right
after a gnome-shell restart and the watchers have not finished running
their callbacks yet.

Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/4813
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2048>
This commit is contained in:
Sebastian Keller 2021-11-23 02:48:04 +01:00 committed by Marge Bot
parent 37271ffe70
commit 85609a232d
4 changed files with 65 additions and 38 deletions

View File

@ -117,9 +117,9 @@ var IntrospectService = class {
type == Meta.WindowType.UTILITY; type == Meta.WindowType.UTILITY;
} }
GetRunningApplicationsAsync(params, invocation) { async GetRunningApplicationsAsync(params, invocation) {
try { try {
this._senderChecker.checkInvocation(invocation); await this._senderChecker.checkInvocation(invocation);
} catch (e) { } catch (e) {
invocation.return_gerror(e); invocation.return_gerror(e);
return; return;
@ -128,13 +128,13 @@ var IntrospectService = class {
invocation.return_value(new GLib.Variant('(a{sa{sv}})', [this._runningApplications])); invocation.return_value(new GLib.Variant('(a{sa{sv}})', [this._runningApplications]));
} }
GetWindowsAsync(params, invocation) { async GetWindowsAsync(params, invocation) {
let focusWindow = global.display.get_focus_window(); let focusWindow = global.display.get_focus_window();
let apps = this._appSystem.get_running(); let apps = this._appSystem.get_running();
let windowsList = {}; let windowsList = {};
try { try {
this._senderChecker.checkInvocation(invocation); await this._senderChecker.checkInvocation(invocation);
} catch (e) { } catch (e) {
invocation.return_gerror(e); invocation.return_gerror(e);
return; return;

View File

@ -486,20 +486,42 @@ var DBusSenderChecker = class {
constructor(allowList) { constructor(allowList) {
this._allowlistMap = new Map(); this._allowlistMap = new Map();
this._uninitializedNames = new Set(allowList);
this._initializedPromise = new Promise(resolve => {
this._resolveInitialized = resolve;
});
this._watchList = allowList.map(name => { this._watchList = allowList.map(name => {
return Gio.DBus.watch_name(Gio.BusType.SESSION, return Gio.DBus.watch_name(Gio.BusType.SESSION,
name, name,
Gio.BusNameWatcherFlags.NONE, Gio.BusNameWatcherFlags.NONE,
(conn_, name_, owner) => this._allowlistMap.set(name, owner), (conn_, name_, owner) => {
() => this._allowlistMap.delete(name)); this._allowlistMap.set(name, owner);
this._checkAndResolveInitialized(name);
},
() => {
this._allowlistMap.delete(name);
this._checkAndResolveInitialized(name);
});
}); });
} }
/** /**
* @param {string} name - bus name for which the watcher got initialized
*/
_checkAndResolveInitialized(name) {
if (this._uninitializedNames.delete(name) &&
this._uninitializedNames.size === 0)
this._resolveInitialized();
}
/**
* @async
* @param {string} sender - the bus name that invoked the checked method * @param {string} sender - the bus name that invoked the checked method
* @returns {bool} * @returns {bool}
*/ */
_isSenderAllowed(sender) { async _isSenderAllowed(sender) {
await this._initializedPromise;
return [...this._allowlistMap.values()].includes(sender); return [...this._allowlistMap.values()].includes(sender);
} }
@ -507,15 +529,16 @@ var DBusSenderChecker = class {
* Check whether the bus name that invoked @invocation maps * Check whether the bus name that invoked @invocation maps
* to an entry in the allow list. * to an entry in the allow list.
* *
* @async
* @throws * @throws
* @param {Gio.DBusMethodInvocation} invocation - the invocation * @param {Gio.DBusMethodInvocation} invocation - the invocation
* @returns {void} * @returns {void}
*/ */
checkInvocation(invocation) { async checkInvocation(invocation) {
if (global.context.unsafe_mode) if (global.context.unsafe_mode)
return; return;
if (this._isSenderAllowed(invocation.get_sender())) if (await this._isSenderAllowed(invocation.get_sender()))
return; return;
throw new GLib.Error(Gio.DBusError, throw new GLib.Error(Gio.DBusError,

View File

@ -37,7 +37,7 @@ var ScreenshotService = class {
Gio.DBus.session.own_name('org.gnome.Shell.Screenshot', Gio.BusNameOwnerFlags.REPLACE, null, null); Gio.DBus.session.own_name('org.gnome.Shell.Screenshot', Gio.BusNameOwnerFlags.REPLACE, null, null);
} }
_createScreenshot(invocation, needsDisk = true, restrictCallers = true) { async _createScreenshot(invocation, needsDisk = true, restrictCallers = true) {
let lockedDown = false; let lockedDown = false;
if (needsDisk) if (needsDisk)
lockedDown = this._lockdownSettings.get_boolean('disable-save-to-disk'); lockedDown = this._lockdownSettings.get_boolean('disable-save-to-disk');
@ -55,7 +55,7 @@ var ScreenshotService = class {
return null; return null;
} else if (restrictCallers) { } else if (restrictCallers) {
try { try {
this._senderChecker.checkInvocation(invocation); await this._senderChecker.checkInvocation(invocation);
} catch (e) { } catch (e) {
invocation.return_gerror(e); invocation.return_gerror(e);
return null; return null;
@ -200,7 +200,7 @@ var ScreenshotService = class {
"Invalid params"); "Invalid params");
return; return;
} }
let screenshot = this._createScreenshot(invocation); let screenshot = await this._createScreenshot(invocation);
if (!screenshot) if (!screenshot)
return; return;
@ -223,7 +223,7 @@ var ScreenshotService = class {
async ScreenshotWindowAsync(params, invocation) { async ScreenshotWindowAsync(params, invocation) {
let [includeFrame, includeCursor, flash, filename] = params; let [includeFrame, includeCursor, flash, filename] = params;
let screenshot = this._createScreenshot(invocation); let screenshot = await this._createScreenshot(invocation);
if (!screenshot) if (!screenshot)
return; return;
@ -246,7 +246,7 @@ var ScreenshotService = class {
async ScreenshotAsync(params, invocation) { async ScreenshotAsync(params, invocation) {
let [includeCursor, flash, filename] = params; let [includeCursor, flash, filename] = params;
let screenshot = this._createScreenshot(invocation); let screenshot = await this._createScreenshot(invocation);
if (!screenshot) if (!screenshot)
return; return;
@ -269,7 +269,7 @@ var ScreenshotService = class {
async SelectAreaAsync(params, invocation) { async SelectAreaAsync(params, invocation) {
try { try {
this._senderChecker.checkInvocation(invocation); await this._senderChecker.checkInvocation(invocation);
} catch (e) { } catch (e) {
invocation.return_gerror(e); invocation.return_gerror(e);
return; return;
@ -289,9 +289,9 @@ var ScreenshotService = class {
} }
} }
FlashAreaAsync(params, invocation) { async FlashAreaAsync(params, invocation) {
try { try {
this._senderChecker.checkInvocation(invocation); await this._senderChecker.checkInvocation(invocation);
} catch (e) { } catch (e) {
invocation.return_gerror(e); invocation.return_gerror(e);
return; return;
@ -311,7 +311,7 @@ var ScreenshotService = class {
} }
async PickColorAsync(params, invocation) { async PickColorAsync(params, invocation) {
const screenshot = this._createScreenshot(invocation, false, false); const screenshot = await this._createScreenshot(invocation, false, false);
if (!screenshot) if (!screenshot)
return; return;

View File

@ -81,13 +81,14 @@ var GnomeShell = class {
/** /**
* Focus the overview's search entry * Focus the overview's search entry
* *
* @async
* @param {...any} params - method parameters * @param {...any} params - method parameters
* @param {Gio.DBusMethodInvocation} invocation - the invocation * @param {Gio.DBusMethodInvocation} invocation - the invocation
* @returns {void} * @returns {void}
*/ */
FocusSearchAsync(params, invocation) { async FocusSearchAsync(params, invocation) {
try { try {
this._senderChecker.checkInvocation(invocation); await this._senderChecker.checkInvocation(invocation);
} catch (e) { } catch (e) {
invocation.return_gerror(e); invocation.return_gerror(e);
return; return;
@ -100,13 +101,14 @@ var GnomeShell = class {
/** /**
* Show OSD with the specified parameters * Show OSD with the specified parameters
* *
* @async
* @param {...any} params - method parameters * @param {...any} params - method parameters
* @param {Gio.DBusMethodInvocation} invocation - the invocation * @param {Gio.DBusMethodInvocation} invocation - the invocation
* @returns {void} * @returns {void}
*/ */
ShowOSDAsync([params], invocation) { async ShowOSDAsync([params], invocation) {
try { try {
this._senderChecker.checkInvocation(invocation); await this._senderChecker.checkInvocation(invocation);
} catch (e) { } catch (e) {
invocation.return_gerror(e); invocation.return_gerror(e);
return; return;
@ -138,13 +140,14 @@ var GnomeShell = class {
/** /**
* Focus specified app in the overview's app grid * Focus specified app in the overview's app grid
* *
* @async
* @param {string} id - an application ID * @param {string} id - an application ID
* @param {Gio.DBusMethodInvocation} invocation - the invocation * @param {Gio.DBusMethodInvocation} invocation - the invocation
* @returns {void} * @returns {void}
*/ */
FocusAppAsync([id], invocation) { async FocusAppAsync([id], invocation) {
try { try {
this._senderChecker.checkInvocation(invocation); await this._senderChecker.checkInvocation(invocation);
} catch (e) { } catch (e) {
invocation.return_gerror(e); invocation.return_gerror(e);
return; return;
@ -157,13 +160,14 @@ var GnomeShell = class {
/** /**
* Show the overview's app grid * Show the overview's app grid
* *
* @async
* @param {...any} params - method parameters * @param {...any} params - method parameters
* @param {Gio.DBusMethodInvocation} invocation - the invocation * @param {Gio.DBusMethodInvocation} invocation - the invocation
* @returns {void} * @returns {void}
*/ */
ShowApplicationsAsync(params, invocation) { async ShowApplicationsAsync(params, invocation) {
try { try {
this._senderChecker.checkInvocation(invocation); await this._senderChecker.checkInvocation(invocation);
} catch (e) { } catch (e) {
invocation.return_gerror(e); invocation.return_gerror(e);
return; return;
@ -173,9 +177,9 @@ var GnomeShell = class {
invocation.return_value(null); invocation.return_value(null);
} }
GrabAcceleratorAsync(params, invocation) { async GrabAcceleratorAsync(params, invocation) {
try { try {
this._senderChecker.checkInvocation(invocation); await this._senderChecker.checkInvocation(invocation);
} catch (e) { } catch (e) {
invocation.return_gerror(e); invocation.return_gerror(e);
return; return;
@ -187,9 +191,9 @@ var GnomeShell = class {
invocation.return_value(GLib.Variant.new('(u)', [bindingAction])); invocation.return_value(GLib.Variant.new('(u)', [bindingAction]));
} }
GrabAcceleratorsAsync(params, invocation) { async GrabAcceleratorsAsync(params, invocation) {
try { try {
this._senderChecker.checkInvocation(invocation); await this._senderChecker.checkInvocation(invocation);
} catch (e) { } catch (e) {
invocation.return_gerror(e); invocation.return_gerror(e);
return; return;
@ -205,9 +209,9 @@ var GnomeShell = class {
invocation.return_value(GLib.Variant.new('(au)', [bindingActions])); invocation.return_value(GLib.Variant.new('(au)', [bindingActions]));
} }
UngrabAcceleratorAsync(params, invocation) { async UngrabAcceleratorAsync(params, invocation) {
try { try {
this._senderChecker.checkInvocation(invocation); await this._senderChecker.checkInvocation(invocation);
} catch (e) { } catch (e) {
invocation.return_gerror(e); invocation.return_gerror(e);
return; return;
@ -220,9 +224,9 @@ var GnomeShell = class {
invocation.return_value(GLib.Variant.new('(b)', [ungrabSucceeded])); invocation.return_value(GLib.Variant.new('(b)', [ungrabSucceeded]));
} }
UngrabAcceleratorsAsync(params, invocation) { async UngrabAcceleratorsAsync(params, invocation) {
try { try {
this._senderChecker.checkInvocation(invocation); await this._senderChecker.checkInvocation(invocation);
} catch (e) { } catch (e) {
invocation.return_gerror(e); invocation.return_gerror(e);
return; return;
@ -307,9 +311,9 @@ var GnomeShell = class {
this._grabbers.delete(name); this._grabbers.delete(name);
} }
ShowMonitorLabelsAsync(params, invocation) { async ShowMonitorLabelsAsync(params, invocation) {
try { try {
this._senderChecker.checkInvocation(invocation); await this._senderChecker.checkInvocation(invocation);
} catch (e) { } catch (e) {
invocation.return_gerror(e); invocation.return_gerror(e);
return; return;
@ -321,9 +325,9 @@ var GnomeShell = class {
invocation.return_value(null); invocation.return_value(null);
} }
HideMonitorLabelsAsync(params, invocation) { async HideMonitorLabelsAsync(params, invocation) {
try { try {
this._senderChecker.checkInvocation(invocation); await this._senderChecker.checkInvocation(invocation);
} catch (e) { } catch (e) {
invocation.return_gerror(e); invocation.return_gerror(e);
return; return;