Blame SOURCES/defend-against-corrupt-notifications.patch

6f08de
From 7bdd1962213a37f6218fe15ea1a4062dd318672a Mon Sep 17 00:00:00 2001
6f08de
From: Will Thompson <wjt@endlessm.com>
6f08de
Date: Wed, 28 Aug 2019 15:39:44 +0100
6f08de
Subject: [PATCH 1/2] global: Don't trust persistent/runtime state data
6f08de
6f08de
An Endless OS system was found in the wild with a malformed
6f08de
.local/share/gnome-shell/notifications. When deserialized in Python,
6f08de
after passing trusted=True to g_variant_new_from_bytes(), the first
6f08de
element of the first struct in the array looks like this:
6f08de
6f08de
    In [41]: _38.get_child_value(0).get_child_value(0)
6f08de
    Out[41]: GLib.Variant('s', '\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff')
6f08de
6f08de
When deserialised in GJS, we get:
6f08de
6f08de
    gjs> v.get_child_value(0).get_child_value(0)
6f08de
    [object variant of type "s"]
6f08de
    gjs> v.get_child_value(0).get_child_value(0).get_string()
6f08de
    typein:43:1 malformed UTF-8 character sequence at offset 0
6f08de
      @typein:43:1
6f08de
      @<stdin>:1:34
6f08de
6f08de
While g_variant_new_from_bytes() doesn't have much to say about its
6f08de
'trusted' parameter, g_variant_new_from_data() does:
6f08de
6f08de
> If data is trusted to be serialised data in normal form then trusted
6f08de
> should be TRUE. This applies to serialised data created within this
6f08de
> process or read from a trusted location on the disk (such as a file
6f08de
> installed in /usr/lib alongside your application). You should set
6f08de
> trusted to FALSE if data is read from the network, a file in the
6f08de
> user's home directory, etc.
6f08de
6f08de
Persistent state is read from the user's home directory, so it should
6f08de
not be trusted. With trusted=False, the string value above comes out as
6f08de
"".
6f08de
6f08de
I don't have an explanation for how this file ended up being malformed.
6f08de
I also don't have an explanation for when this started crashing: my
6f08de
guess is that recent GJS became stricter about validating UTF-8 but I
6f08de
could be wrong!
6f08de
6f08de
https://gitlab.gnome.org/GNOME/gnome-shell/issues/1552
6f08de
---
6f08de
 src/shell-global.c | 2 +-
6f08de
 1 file changed, 1 insertion(+), 1 deletion(-)
6f08de
6f08de
diff --git a/src/shell-global.c b/src/shell-global.c
6f08de
index 4b33778e0..33046f614 100644
6f08de
--- a/src/shell-global.c
6f08de
+++ b/src/shell-global.c
6f08de
@@ -1707,7 +1707,7 @@ load_variant (GFile      *dir,
6f08de
   else
6f08de
     {
6f08de
       GBytes *bytes = g_mapped_file_get_bytes (mfile);
6f08de
-      res = g_variant_new_from_bytes (G_VARIANT_TYPE (property_type), bytes, TRUE);
6f08de
+      res = g_variant_new_from_bytes (G_VARIANT_TYPE (property_type), bytes, FALSE);
6f08de
       g_bytes_unref (bytes);
6f08de
       g_mapped_file_unref (mfile);
6f08de
     }
6f08de
-- 
6f08de
2.35.1
6f08de
6f08de
6f08de
From 13dcb3e4400b92a0d2f548e88b70b358240d462c Mon Sep 17 00:00:00 2001
6f08de
From: Will Thompson <wjt@endlessm.com>
6f08de
Date: Wed, 28 Aug 2019 15:38:03 +0100
6f08de
Subject: [PATCH 2/2] notificationDaemon: Catch exceptions while loading
6f08de
 notifications
6f08de
6f08de
An Endless OS system was found in the wild with a malformed
6f08de
.local/share/gnome-shell/notifications which causes _loadNotifications()
6f08de
to raise an exception. This exception was not previously handled and
6f08de
bubbles all the way out to gnome_shell_plugin_start(), whereupon the
6f08de
shell exit(1)s. The user could no longer log into their computer.
6f08de
6f08de
Handle exceptions from _loadNotifications(), log them, and attempt to
6f08de
continue. Ensure that this._isLoading is set to 'false' even on error,
6f08de
so that future calls to _saveNotifications() can overwrite the (corrupt)
6f08de
state file.
6f08de
6f08de
https://gitlab.gnome.org/GNOME/gnome-shell/issues/1552
6f08de
---
6f08de
 js/ui/notificationDaemon.js | 42 ++++++++++++++++++++-----------------
6f08de
 1 file changed, 23 insertions(+), 19 deletions(-)
6f08de
6f08de
diff --git a/js/ui/notificationDaemon.js b/js/ui/notificationDaemon.js
6f08de
index 4bdede841..dbe673b88 100644
6f08de
--- a/js/ui/notificationDaemon.js
6f08de
+++ b/js/ui/notificationDaemon.js
6f08de
@@ -749,29 +749,33 @@ var GtkNotificationDaemon = class GtkNotificationDaemon {
6f08de
     _loadNotifications() {
6f08de
         this._isLoading = true;
6f08de
 
6f08de
-        let value = global.get_persistent_state('a(sa(sv))', 'notifications');
6f08de
-        if (value) {
6f08de
-            let sources = value.deep_unpack();
6f08de
-            sources.forEach(([appId, notifications]) => {
6f08de
-                if (notifications.length == 0)
6f08de
-                    return;
6f08de
-
6f08de
-                let source;
6f08de
-                try {
6f08de
-                    source = this._ensureAppSource(appId);
6f08de
-                } catch(e) {
6f08de
-                    if (e instanceof InvalidAppError)
6f08de
+        try {
6f08de
+            let value = global.get_persistent_state('a(sa(sv))', 'notifications');
6f08de
+            if (value) {
6f08de
+                let sources = value.deep_unpack();
6f08de
+                sources.forEach(([appId, notifications]) => {
6f08de
+                    if (notifications.length == 0)
6f08de
                         return;
6f08de
-                    throw e;
6f08de
-                }
6f08de
 
6f08de
-                notifications.forEach(([notificationId, notification]) => {
6f08de
-                    source.addNotification(notificationId, notification.deep_unpack(), false);
6f08de
+                    let source;
6f08de
+                    try {
6f08de
+                        source = this._ensureAppSource(appId);
6f08de
+                    } catch (e) {
6f08de
+                        if (e instanceof InvalidAppError)
6f08de
+                            return;
6f08de
+                        throw e;
6f08de
+                    }
6f08de
+
6f08de
+                    notifications.forEach(([notificationId, notification]) => {
6f08de
+                        source.addNotification(notificationId, notification.deep_unpack(), false);
6f08de
+                    });
6f08de
                 });
6f08de
-            });
6f08de
+            }
6f08de
+        } catch (e) {
6f08de
+            logError(e, 'Failed to load saved notifications');
6f08de
+        } finally {
6f08de
+            this._isLoading = false;
6f08de
         }
6f08de
-
6f08de
-        this._isLoading = false;
6f08de
     }
6f08de
 
6f08de
     _saveNotifications() {
6f08de
-- 
6f08de
2.35.1
6f08de