From 85609a232d4088b058f23f4922b9a993dea95199 Mon Sep 17 00:00:00 2001 From: Sebastian Keller Date: Tue, 23 Nov 2021 02:48:04 +0100 Subject: [PATCH] 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: --- js/misc/introspect.js | 8 ++++---- js/misc/util.js | 33 +++++++++++++++++++++++++++----- js/ui/screenshot.js | 18 +++++++++--------- js/ui/shellDBus.js | 44 +++++++++++++++++++++++-------------------- 4 files changed, 65 insertions(+), 38 deletions(-) diff --git a/js/misc/introspect.js b/js/misc/introspect.js index 22bd8319c..45eee81ce 100644 --- a/js/misc/introspect.js +++ b/js/misc/introspect.js @@ -117,9 +117,9 @@ var IntrospectService = class { type == Meta.WindowType.UTILITY; } - GetRunningApplicationsAsync(params, invocation) { + async GetRunningApplicationsAsync(params, invocation) { try { - this._senderChecker.checkInvocation(invocation); + await this._senderChecker.checkInvocation(invocation); } catch (e) { invocation.return_gerror(e); return; @@ -128,13 +128,13 @@ var IntrospectService = class { 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 apps = this._appSystem.get_running(); let windowsList = {}; try { - this._senderChecker.checkInvocation(invocation); + await this._senderChecker.checkInvocation(invocation); } catch (e) { invocation.return_gerror(e); return; diff --git a/js/misc/util.js b/js/misc/util.js index bd5718472..25a5748e9 100644 --- a/js/misc/util.js +++ b/js/misc/util.js @@ -486,20 +486,42 @@ var DBusSenderChecker = class { constructor(allowList) { this._allowlistMap = new Map(); + this._uninitializedNames = new Set(allowList); + this._initializedPromise = new Promise(resolve => { + this._resolveInitialized = resolve; + }); + this._watchList = allowList.map(name => { return Gio.DBus.watch_name(Gio.BusType.SESSION, name, Gio.BusNameWatcherFlags.NONE, - (conn_, name_, owner) => this._allowlistMap.set(name, owner), - () => this._allowlistMap.delete(name)); + (conn_, name_, owner) => { + 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 * @returns {bool} */ - _isSenderAllowed(sender) { + async _isSenderAllowed(sender) { + await this._initializedPromise; return [...this._allowlistMap.values()].includes(sender); } @@ -507,15 +529,16 @@ var DBusSenderChecker = class { * Check whether the bus name that invoked @invocation maps * to an entry in the allow list. * + * @async * @throws * @param {Gio.DBusMethodInvocation} invocation - the invocation * @returns {void} */ - checkInvocation(invocation) { + async checkInvocation(invocation) { if (global.context.unsafe_mode) return; - if (this._isSenderAllowed(invocation.get_sender())) + if (await this._isSenderAllowed(invocation.get_sender())) return; throw new GLib.Error(Gio.DBusError, diff --git a/js/ui/screenshot.js b/js/ui/screenshot.js index ae1156f47..97fcfacd0 100644 --- a/js/ui/screenshot.js +++ b/js/ui/screenshot.js @@ -37,7 +37,7 @@ var ScreenshotService = class { 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; if (needsDisk) lockedDown = this._lockdownSettings.get_boolean('disable-save-to-disk'); @@ -55,7 +55,7 @@ var ScreenshotService = class { return null; } else if (restrictCallers) { try { - this._senderChecker.checkInvocation(invocation); + await this._senderChecker.checkInvocation(invocation); } catch (e) { invocation.return_gerror(e); return null; @@ -200,7 +200,7 @@ var ScreenshotService = class { "Invalid params"); return; } - let screenshot = this._createScreenshot(invocation); + let screenshot = await this._createScreenshot(invocation); if (!screenshot) return; @@ -223,7 +223,7 @@ var ScreenshotService = class { async ScreenshotWindowAsync(params, invocation) { let [includeFrame, includeCursor, flash, filename] = params; - let screenshot = this._createScreenshot(invocation); + let screenshot = await this._createScreenshot(invocation); if (!screenshot) return; @@ -246,7 +246,7 @@ var ScreenshotService = class { async ScreenshotAsync(params, invocation) { let [includeCursor, flash, filename] = params; - let screenshot = this._createScreenshot(invocation); + let screenshot = await this._createScreenshot(invocation); if (!screenshot) return; @@ -269,7 +269,7 @@ var ScreenshotService = class { async SelectAreaAsync(params, invocation) { try { - this._senderChecker.checkInvocation(invocation); + await this._senderChecker.checkInvocation(invocation); } catch (e) { invocation.return_gerror(e); return; @@ -289,9 +289,9 @@ var ScreenshotService = class { } } - FlashAreaAsync(params, invocation) { + async FlashAreaAsync(params, invocation) { try { - this._senderChecker.checkInvocation(invocation); + await this._senderChecker.checkInvocation(invocation); } catch (e) { invocation.return_gerror(e); return; @@ -311,7 +311,7 @@ var ScreenshotService = class { } async PickColorAsync(params, invocation) { - const screenshot = this._createScreenshot(invocation, false, false); + const screenshot = await this._createScreenshot(invocation, false, false); if (!screenshot) return; diff --git a/js/ui/shellDBus.js b/js/ui/shellDBus.js index a8070eb92..aeabe6d81 100644 --- a/js/ui/shellDBus.js +++ b/js/ui/shellDBus.js @@ -81,13 +81,14 @@ var GnomeShell = class { /** * Focus the overview's search entry * + * @async * @param {...any} params - method parameters * @param {Gio.DBusMethodInvocation} invocation - the invocation * @returns {void} */ - FocusSearchAsync(params, invocation) { + async FocusSearchAsync(params, invocation) { try { - this._senderChecker.checkInvocation(invocation); + await this._senderChecker.checkInvocation(invocation); } catch (e) { invocation.return_gerror(e); return; @@ -100,13 +101,14 @@ var GnomeShell = class { /** * Show OSD with the specified parameters * + * @async * @param {...any} params - method parameters * @param {Gio.DBusMethodInvocation} invocation - the invocation * @returns {void} */ - ShowOSDAsync([params], invocation) { + async ShowOSDAsync([params], invocation) { try { - this._senderChecker.checkInvocation(invocation); + await this._senderChecker.checkInvocation(invocation); } catch (e) { invocation.return_gerror(e); return; @@ -138,13 +140,14 @@ var GnomeShell = class { /** * Focus specified app in the overview's app grid * + * @async * @param {string} id - an application ID * @param {Gio.DBusMethodInvocation} invocation - the invocation * @returns {void} */ - FocusAppAsync([id], invocation) { + async FocusAppAsync([id], invocation) { try { - this._senderChecker.checkInvocation(invocation); + await this._senderChecker.checkInvocation(invocation); } catch (e) { invocation.return_gerror(e); return; @@ -157,13 +160,14 @@ var GnomeShell = class { /** * Show the overview's app grid * + * @async * @param {...any} params - method parameters * @param {Gio.DBusMethodInvocation} invocation - the invocation * @returns {void} */ - ShowApplicationsAsync(params, invocation) { + async ShowApplicationsAsync(params, invocation) { try { - this._senderChecker.checkInvocation(invocation); + await this._senderChecker.checkInvocation(invocation); } catch (e) { invocation.return_gerror(e); return; @@ -173,9 +177,9 @@ var GnomeShell = class { invocation.return_value(null); } - GrabAcceleratorAsync(params, invocation) { + async GrabAcceleratorAsync(params, invocation) { try { - this._senderChecker.checkInvocation(invocation); + await this._senderChecker.checkInvocation(invocation); } catch (e) { invocation.return_gerror(e); return; @@ -187,9 +191,9 @@ var GnomeShell = class { invocation.return_value(GLib.Variant.new('(u)', [bindingAction])); } - GrabAcceleratorsAsync(params, invocation) { + async GrabAcceleratorsAsync(params, invocation) { try { - this._senderChecker.checkInvocation(invocation); + await this._senderChecker.checkInvocation(invocation); } catch (e) { invocation.return_gerror(e); return; @@ -205,9 +209,9 @@ var GnomeShell = class { invocation.return_value(GLib.Variant.new('(au)', [bindingActions])); } - UngrabAcceleratorAsync(params, invocation) { + async UngrabAcceleratorAsync(params, invocation) { try { - this._senderChecker.checkInvocation(invocation); + await this._senderChecker.checkInvocation(invocation); } catch (e) { invocation.return_gerror(e); return; @@ -220,9 +224,9 @@ var GnomeShell = class { invocation.return_value(GLib.Variant.new('(b)', [ungrabSucceeded])); } - UngrabAcceleratorsAsync(params, invocation) { + async UngrabAcceleratorsAsync(params, invocation) { try { - this._senderChecker.checkInvocation(invocation); + await this._senderChecker.checkInvocation(invocation); } catch (e) { invocation.return_gerror(e); return; @@ -307,9 +311,9 @@ var GnomeShell = class { this._grabbers.delete(name); } - ShowMonitorLabelsAsync(params, invocation) { + async ShowMonitorLabelsAsync(params, invocation) { try { - this._senderChecker.checkInvocation(invocation); + await this._senderChecker.checkInvocation(invocation); } catch (e) { invocation.return_gerror(e); return; @@ -321,9 +325,9 @@ var GnomeShell = class { invocation.return_value(null); } - HideMonitorLabelsAsync(params, invocation) { + async HideMonitorLabelsAsync(params, invocation) { try { - this._senderChecker.checkInvocation(invocation); + await this._senderChecker.checkInvocation(invocation); } catch (e) { invocation.return_gerror(e); return;