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;
}
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;

View File

@ -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,