mystifyingyouth / rpms / polkit

Forked from rpms/polkit 2 years ago
Clone

Blame SOURCES/polkit-0.112-CVE-2015-3256.patch

dc3ed5
commit 983e8ec37b0ec1cc5114cb9ca49cf558dedfb31e
dc3ed5
Author: Miloslav Trmač <mitr@redhat.com>
dc3ed5
Date:   Tue Jul 1 20:00:48 2014 +0200
dc3ed5
dc3ed5
    Don't pass an uninitialized JS parameter
dc3ed5
    
dc3ed5
    Don't pass argc==3 when using a 2-member array in
dc3ed5
    polkit_backend_js_authority_check_authorization_sync .  To avoid such
dc3ed5
    problems in the future, use G_N_ELEMENTS in both similar callers.
dc3ed5
    
dc3ed5
    https://bugs.freedesktop.org/show_bug.cgi?id=69501
dc3ed5
dc3ed5
diff --git a/src/polkitbackend/polkitbackendjsauthority.c b/src/polkitbackend/polkitbackendjsauthority.c
dc3ed5
index c232573..c7a29e0 100644
dc3ed5
--- a/src/polkitbackend/polkitbackendjsauthority.c
dc3ed5
+++ b/src/polkitbackend/polkitbackendjsauthority.c
dc3ed5
@@ -1074,7 +1074,7 @@ polkit_backend_js_authority_get_admin_auth_identities (PolkitBackendInteractiveA
dc3ed5
 
dc3ed5
   if (!call_js_function_with_runaway_killer (authority,
dc3ed5
                                              "_runAdminRules",
dc3ed5
-                                             2,
dc3ed5
+                                             G_N_ELEMENTS (argv),
dc3ed5
                                              argv,
dc3ed5
                                              &rval))
dc3ed5
     {
dc3ed5
@@ -1179,7 +1179,7 @@ polkit_backend_js_authority_check_authorization_sync (PolkitBackendInteractiveAu
dc3ed5
 
dc3ed5
   if (!call_js_function_with_runaway_killer (authority,
dc3ed5
                                              "_runRules",
dc3ed5
-                                             3,
dc3ed5
+                                             G_N_ELEMENTS (argv),
dc3ed5
                                              argv,
dc3ed5
                                              &rval))
dc3ed5
     {
dc3ed5
dc3ed5
commit a97672540c66c03ed392fc072f0c682281f08989
dc3ed5
Author: Miloslav Trmač <mitr@redhat.com>
dc3ed5
Date:   Tue Jul 1 20:00:48 2014 +0200
dc3ed5
dc3ed5
    Don't add extra NULL group to subject.groups
dc3ed5
    
dc3ed5
    The NULL “terminator” of ‘groups’ was being passed to JavaScript.  Drop
dc3ed5
    it, and simplify by leting set_property_strv use the GPtrArray directly
dc3ed5
    instead of the extra conversions “into” a strv and a completely dead
dc3ed5
    g_strv_length().
dc3ed5
    
dc3ed5
    https://bugs.freedesktop.org/show_bug.cgi?id=69501
dc3ed5
dc3ed5
diff --git a/src/polkitbackend/polkitbackendjsauthority.c b/src/polkitbackend/polkitbackendjsauthority.c
dc3ed5
index c7a29e0..efb07a9 100644
dc3ed5
--- a/src/polkitbackend/polkitbackendjsauthority.c
dc3ed5
+++ b/src/polkitbackend/polkitbackendjsauthority.c
dc3ed5
@@ -659,26 +659,22 @@ static void
dc3ed5
 set_property_strv (PolkitBackendJsAuthority  *authority,
dc3ed5
                    JSObject                  *obj,
dc3ed5
                    const gchar               *name,
dc3ed5
-                   const gchar *const        *value,
dc3ed5
-                   gssize                     len)
dc3ed5
+                   GPtrArray                 *value)
dc3ed5
 {
dc3ed5
   jsval value_jsval;
dc3ed5
   JSObject *array_object;
dc3ed5
   jsval *jsvals;
dc3ed5
   guint n;
dc3ed5
 
dc3ed5
-  if (len < 0)
dc3ed5
-    len = g_strv_length ((gchar **) value);
dc3ed5
-
dc3ed5
-  jsvals = g_new0 (jsval, len);
dc3ed5
-  for (n = 0; n < len; n++)
dc3ed5
+  jsvals = g_new0 (jsval, value->len);
dc3ed5
+  for (n = 0; n < value->len; n++)
dc3ed5
     {
dc3ed5
       JSString *jsstr;
dc3ed5
-      jsstr = JS_NewStringCopyZ (authority->priv->cx, value[n]);
dc3ed5
+      jsstr = JS_NewStringCopyZ (authority->priv->cx, g_ptr_array_index(value, n));
dc3ed5
       jsvals[n] = STRING_TO_JSVAL (jsstr);
dc3ed5
     }
dc3ed5
 
dc3ed5
-  array_object = JS_NewArrayObject (authority->priv->cx, (gint32) len, jsvals);
dc3ed5
+  array_object = JS_NewArrayObject (authority->priv->cx, value->len, jsvals);
dc3ed5
 
dc3ed5
   value_jsval = OBJECT_TO_JSVAL (array_object);
dc3ed5
   JS_SetProperty (authority->priv->cx, obj, name, &value_jsval);
dc3ed5
@@ -818,11 +814,9 @@ subject_to_jsval (PolkitBackendJsAuthority  *authority,
dc3ed5
         }
dc3ed5
     }
dc3ed5
 
dc3ed5
-  g_ptr_array_add (groups, NULL);
dc3ed5
-
dc3ed5
   set_property_int32 (authority, obj, "pid", pid);
dc3ed5
   set_property_str (authority, obj, "user", user_name);
dc3ed5
-  set_property_strv (authority, obj, "groups", (const gchar* const *) groups->pdata, groups->len);
dc3ed5
+  set_property_strv (authority, obj, "groups", groups);
dc3ed5
   set_property_str (authority, obj, "seat", seat_str);
dc3ed5
   set_property_str (authority, obj, "session", session_str);
dc3ed5
   set_property_bool (authority, obj, "local", subject_is_local);
dc3ed5
dc3ed5
commit cbad0d5721804a4b7c2d998b00da9e70dc623820
dc3ed5
Author: Miloslav Trmač <mitr@redhat.com>
dc3ed5
Date:   Tue Jul 1 20:00:48 2014 +0200
dc3ed5
dc3ed5
    Don't store unrooted jsvals on heap
dc3ed5
    
dc3ed5
    Don't create a temporary array of jsvals on heap; the GC is not looking
dc3ed5
    for GC roots there.
dc3ed5
    
dc3ed5
    Compare
dc3ed5
    https://developer.mozilla.org/en-US/docs/SpiderMonkey/GC_Rooting_Guide
dc3ed5
    and
dc3ed5
    https://web.archive.org/web/20140305233124/https://developer.mozilla.org/en-US/docs/SpiderMonkey_Garbage_Collection_Tips
dc3ed5
    .
dc3ed5
    
dc3ed5
    https://bugs.freedesktop.org/show_bug.cgi?id=69501
dc3ed5
dc3ed5
diff --git a/src/polkitbackend/polkitbackendjsauthority.c b/src/polkitbackend/polkitbackendjsauthority.c
dc3ed5
index efb07a9..d02e5e3 100644
dc3ed5
--- a/src/polkitbackend/polkitbackendjsauthority.c
dc3ed5
+++ b/src/polkitbackend/polkitbackendjsauthority.c
dc3ed5
@@ -663,23 +663,22 @@ set_property_strv (PolkitBackendJsAuthority  *authority,
dc3ed5
 {
dc3ed5
   jsval value_jsval;
dc3ed5
   JSObject *array_object;
dc3ed5
-  jsval *jsvals;
dc3ed5
   guint n;
dc3ed5
 
dc3ed5
-  jsvals = g_new0 (jsval, value->len);
dc3ed5
+  array_object = JS_NewArrayObject (authority->priv->cx, 0, NULL);
dc3ed5
+
dc3ed5
   for (n = 0; n < value->len; n++)
dc3ed5
     {
dc3ed5
       JSString *jsstr;
dc3ed5
+      jsval val;
dc3ed5
+
dc3ed5
       jsstr = JS_NewStringCopyZ (authority->priv->cx, g_ptr_array_index(value, n));
dc3ed5
-      jsvals[n] = STRING_TO_JSVAL (jsstr);
dc3ed5
+      val = STRING_TO_JSVAL (jsstr);
dc3ed5
+      JS_SetElement (authority->priv->cx, array_object, n, &val;;
dc3ed5
     }
dc3ed5
 
dc3ed5
-  array_object = JS_NewArrayObject (authority->priv->cx, value->len, jsvals);
dc3ed5
-
dc3ed5
   value_jsval = OBJECT_TO_JSVAL (array_object);
dc3ed5
   JS_SetProperty (authority->priv->cx, obj, name, &value_jsval);
dc3ed5
-
dc3ed5
-  g_free (jsvals);
dc3ed5
 }
dc3ed5
 
dc3ed5
 
dc3ed5
dc3ed5
commit 0f5852a4bdabe377ddcdbed09a0c1f95710e17fe
dc3ed5
Author: Miloslav Trmač <mitr@redhat.com>
dc3ed5
Date:   Tue Jul 1 20:00:48 2014 +0200
dc3ed5
dc3ed5
    Fix a per-authorization memory leak
dc3ed5
    
dc3ed5
    We were leaking PolkitAuthorizationResult on every request, primarily on
dc3ed5
    the success path, but also on various error paths as well.
dc3ed5
    
dc3ed5
    https://bugs.freedesktop.org/show_bug.cgi?id=69501
dc3ed5
dc3ed5
diff --git a/src/polkitbackend/polkitbackendauthority.c b/src/polkitbackend/polkitbackendauthority.c
dc3ed5
index a09d667..14eea99 100644
dc3ed5
--- a/src/polkitbackend/polkitbackendauthority.c
dc3ed5
+++ b/src/polkitbackend/polkitbackendauthority.c
dc3ed5
@@ -714,6 +714,7 @@ check_auth_cb (GObject      *source_object,
dc3ed5
       g_variant_ref_sink (value);
dc3ed5
       g_dbus_method_invocation_return_value (data->invocation, g_variant_new ("(@(bba{ss}))", value));
dc3ed5
       g_variant_unref (value);
dc3ed5
+      g_object_unref (result);
dc3ed5
     }
dc3ed5
 
dc3ed5
   check_auth_data_free (data);
dc3ed5
diff --git a/src/polkitbackend/polkitbackendinteractiveauthority.c b/src/polkitbackend/polkitbackendinteractiveauthority.c
dc3ed5
index 96725f7..7019356 100644
dc3ed5
--- a/src/polkitbackend/polkitbackendinteractiveauthority.c
dc3ed5
+++ b/src/polkitbackend/polkitbackendinteractiveauthority.c
dc3ed5
@@ -1022,7 +1022,7 @@ polkit_backend_interactive_authority_check_authorization (PolkitBackendAuthority
dc3ed5
 
dc3ed5
   /* Otherwise just return the result */
dc3ed5
   g_simple_async_result_set_op_res_gpointer (simple,
dc3ed5
-                                             result,
dc3ed5
+                                             g_object_ref (result),
dc3ed5
                                              g_object_unref);
dc3ed5
   g_simple_async_result_complete (simple);
dc3ed5
   g_object_unref (simple);
dc3ed5
@@ -1039,6 +1039,9 @@ polkit_backend_interactive_authority_check_authorization (PolkitBackendAuthority
dc3ed5
   g_free (subject_str);
dc3ed5
   g_free (user_of_caller_str);
dc3ed5
   g_free (user_of_subject_str);
dc3ed5
+
dc3ed5
+  if (result != NULL)
dc3ed5
+    g_object_unref (result);
dc3ed5
 }
dc3ed5
 
dc3ed5
 /* ---------------------------------------------------------------------------------------------------- */
dc3ed5
dc3ed5
commit ec039f9d7ede5b839f5511e26d5cd6ae9107cb2e
dc3ed5
Author: Miloslav Trmač <mitr@redhat.com>
dc3ed5
Date:   Tue Jul 1 20:00:48 2014 +0200
dc3ed5
dc3ed5
    Fix a memory leak when registering an authentication agent
dc3ed5
    
dc3ed5
    https://bugs.freedesktop.org/show_bug.cgi?id=69501
dc3ed5
dc3ed5
diff --git a/src/polkitbackend/polkitbackendauthority.c b/src/polkitbackend/polkitbackendauthority.c
dc3ed5
index 14eea99..64560e1 100644
dc3ed5
--- a/src/polkitbackend/polkitbackendauthority.c
dc3ed5
+++ b/src/polkitbackend/polkitbackendauthority.c
dc3ed5
@@ -900,6 +900,7 @@ server_handle_register_authentication_agent (Server                 *server,
dc3ed5
   g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
dc3ed5
 
dc3ed5
  out:
dc3ed5
+  g_variant_unref (subject_gvariant);
dc3ed5
   if (subject != NULL)
dc3ed5
     g_object_unref (subject);
dc3ed5
 }
dc3ed5
dc3ed5
commit 57e2d86edc2630cac1812a3285715dad795a4bd6
dc3ed5
Author: Miloslav Trmač <mitr@redhat.com>
dc3ed5
Date:   Tue Jul 1 20:00:48 2014 +0200
dc3ed5
dc3ed5
    Wrap all JS usage within “requests”
dc3ed5
    
dc3ed5
    Required by
dc3ed5
    https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/JSAPI_reference/JS_THREADSAFE
dc3ed5
    ; lack of requests causes assertion failures with a debug build of
dc3ed5
    mozjs17.
dc3ed5
    
dc3ed5
    https://bugs.freedesktop.org/show_bug.cgi?id=69501
dc3ed5
dc3ed5
diff --git a/src/polkitbackend/polkitbackendjsauthority.c b/src/polkitbackend/polkitbackendjsauthority.c
dc3ed5
index d02e5e3..88f31bd 100644
dc3ed5
--- a/src/polkitbackend/polkitbackendjsauthority.c
dc3ed5
+++ b/src/polkitbackend/polkitbackendjsauthority.c
dc3ed5
@@ -239,6 +239,7 @@ rules_file_name_cmp (const gchar *a,
dc3ed5
   return ret;
dc3ed5
 }
dc3ed5
 
dc3ed5
+/* authority->priv->cx must be within a request */
dc3ed5
 static void
dc3ed5
 load_scripts (PolkitBackendJsAuthority  *authority)
dc3ed5
 {
dc3ed5
@@ -339,6 +340,8 @@ reload_scripts (PolkitBackendJsAuthority *authority)
dc3ed5
   jsval argv[1] = {JSVAL_NULL};
dc3ed5
   jsval rval = JSVAL_NULL;
dc3ed5
 
dc3ed5
+  JS_BeginRequest (authority->priv->cx);
dc3ed5
+
dc3ed5
   if (!JS_CallFunctionName(authority->priv->cx,
dc3ed5
                            authority->priv->js_polkit,
dc3ed5
                            "_deleteRules",
dc3ed5
@@ -364,7 +367,7 @@ reload_scripts (PolkitBackendJsAuthority *authority)
dc3ed5
   /* Let applications know we have new rules... */
dc3ed5
   g_signal_emit_by_name (authority, "changed");
dc3ed5
  out:
dc3ed5
-  ;
dc3ed5
+  JS_EndRequest (authority->priv->cx);
dc3ed5
 }
dc3ed5
 
dc3ed5
 static void
dc3ed5
@@ -447,6 +450,7 @@ static void
dc3ed5
 polkit_backend_js_authority_constructed (GObject *object)
dc3ed5
 {
dc3ed5
   PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (object);
dc3ed5
+  gboolean entered_request = FALSE;
dc3ed5
 
dc3ed5
   authority->priv->rt = JS_NewRuntime (8L * 1024L * 1024L);
dc3ed5
   if (authority->priv->rt == NULL)
dc3ed5
@@ -466,6 +470,9 @@ polkit_backend_js_authority_constructed (GObject *object)
dc3ed5
   JS_SetErrorReporter(authority->priv->cx, report_error);
dc3ed5
   JS_SetContextPrivate (authority->priv->cx, authority);
dc3ed5
 
dc3ed5
+  JS_BeginRequest(authority->priv->cx);
dc3ed5
+  entered_request = TRUE;
dc3ed5
+
dc3ed5
   authority->priv->js_global =
dc3ed5
 #if JS_VERSION == 186
dc3ed5
     JS_NewGlobalObject (authority->priv->cx, &js_global_class, NULL);
dc3ed5
@@ -526,10 +533,15 @@ polkit_backend_js_authority_constructed (GObject *object)
dc3ed5
   setup_file_monitors (authority);
dc3ed5
   load_scripts (authority);
dc3ed5
 
dc3ed5
+  JS_EndRequest (authority->priv->cx);
dc3ed5
+  entered_request = FALSE;
dc3ed5
+
dc3ed5
   G_OBJECT_CLASS (polkit_backend_js_authority_parent_class)->constructed (object);
dc3ed5
   return;
dc3ed5
 
dc3ed5
  fail:
dc3ed5
+  if (entered_request)
dc3ed5
+    JS_EndRequest (authority->priv->cx);
dc3ed5
   g_critical ("Error initializing JavaScript environment");
dc3ed5
   g_assert_not_reached ();
dc3ed5
 }
dc3ed5
@@ -642,6 +654,7 @@ polkit_backend_js_authority_class_init (PolkitBackendJsAuthorityClass *klass)
dc3ed5
 
dc3ed5
 /* ---------------------------------------------------------------------------------------------------- */
dc3ed5
 
dc3ed5
+/* authority->priv->cx must be within a request */
dc3ed5
 static void
dc3ed5
 set_property_str (PolkitBackendJsAuthority  *authority,
dc3ed5
                   JSObject                  *obj,
dc3ed5
@@ -655,6 +668,7 @@ set_property_str (PolkitBackendJsAuthority  *authority,
dc3ed5
   JS_SetProperty (authority->priv->cx, obj, name, &value_jsval);
dc3ed5
 }
dc3ed5
 
dc3ed5
+/* authority->priv->cx must be within a request */
dc3ed5
 static void
dc3ed5
 set_property_strv (PolkitBackendJsAuthority  *authority,
dc3ed5
                    JSObject                  *obj,
dc3ed5
@@ -681,7 +695,7 @@ set_property_strv (PolkitBackendJsAuthority  *authority,
dc3ed5
   JS_SetProperty (authority->priv->cx, obj, name, &value_jsval);
dc3ed5
 }
dc3ed5
 
dc3ed5
-
dc3ed5
+/* authority->priv->cx must be within a request */
dc3ed5
 static void
dc3ed5
 set_property_int32 (PolkitBackendJsAuthority  *authority,
dc3ed5
                     JSObject                  *obj,
dc3ed5
@@ -693,6 +707,7 @@ set_property_int32 (PolkitBackendJsAuthority  *authority,
dc3ed5
   JS_SetProperty (authority->priv->cx, obj, name, &value_jsval);
dc3ed5
 }
dc3ed5
 
dc3ed5
+/* authority->priv->cx must be within a request */
dc3ed5
 static void
dc3ed5
 set_property_bool (PolkitBackendJsAuthority  *authority,
dc3ed5
                    JSObject                  *obj,
dc3ed5
@@ -706,6 +721,7 @@ set_property_bool (PolkitBackendJsAuthority  *authority,
dc3ed5
 
dc3ed5
 /* ---------------------------------------------------------------------------------------------------- */
dc3ed5
 
dc3ed5
+/* authority->priv->cx must be within a request */
dc3ed5
 static gboolean
dc3ed5
 subject_to_jsval (PolkitBackendJsAuthority  *authority,
dc3ed5
                   PolkitSubject             *subject,
dc3ed5
@@ -838,6 +854,7 @@ subject_to_jsval (PolkitBackendJsAuthority  *authority,
dc3ed5
 
dc3ed5
 /* ---------------------------------------------------------------------------------------------------- */
dc3ed5
 
dc3ed5
+/* authority->priv->cx must be within a request */
dc3ed5
 static gboolean
dc3ed5
 action_and_details_to_jsval (PolkitBackendJsAuthority  *authority,
dc3ed5
                              const gchar               *action_id,
dc3ed5
@@ -1041,6 +1058,8 @@ polkit_backend_js_authority_get_admin_auth_identities (PolkitBackendInteractiveA
dc3ed5
   gchar *ret_str = NULL;
dc3ed5
   gchar **ret_strs = NULL;
dc3ed5
 
dc3ed5
+  JS_BeginRequest (authority->priv->cx);
dc3ed5
+
dc3ed5
   if (!action_and_details_to_jsval (authority, action_id, details, &argv[0], &error))
dc3ed5
     {
dc3ed5
       polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
dc3ed5
@@ -1120,6 +1139,8 @@ polkit_backend_js_authority_get_admin_auth_identities (PolkitBackendInteractiveA
dc3ed5
 
dc3ed5
   JS_MaybeGC (authority->priv->cx);
dc3ed5
 
dc3ed5
+  JS_EndRequest (authority->priv->cx);
dc3ed5
+
dc3ed5
   return ret;
dc3ed5
 }
dc3ed5
 
dc3ed5
@@ -1146,6 +1167,8 @@ polkit_backend_js_authority_check_authorization_sync (PolkitBackendInteractiveAu
dc3ed5
   gchar *ret_str = NULL;
dc3ed5
   gboolean good = FALSE;
dc3ed5
 
dc3ed5
+  JS_BeginRequest (authority->priv->cx);
dc3ed5
+
dc3ed5
   if (!action_and_details_to_jsval (authority, action_id, details, &argv[0], &error))
dc3ed5
     {
dc3ed5
       polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
dc3ed5
@@ -1222,6 +1245,8 @@ polkit_backend_js_authority_check_authorization_sync (PolkitBackendInteractiveAu
dc3ed5
 
dc3ed5
   JS_MaybeGC (authority->priv->cx);
dc3ed5
 
dc3ed5
+  JS_EndRequest (authority->priv->cx);
dc3ed5
+
dc3ed5
   return ret;
dc3ed5
 }
dc3ed5
 
dc3ed5
dc3ed5
commit 5c668722320eb363f713a0998934aa48fecd56cb
dc3ed5
Author: Miloslav Trmač <mitr@redhat.com>
dc3ed5
Date:   Tue Jul 1 20:00:48 2014 +0200
dc3ed5
dc3ed5
    Register heap-based JSObject pointers to GC
dc3ed5
    
dc3ed5
    This is necessary so that the GC can move the objects (though I haven't
dc3ed5
    so far encountered this in testing).
dc3ed5
    
dc3ed5
    https://bugs.freedesktop.org/show_bug.cgi?id=69501
dc3ed5
dc3ed5
diff --git a/src/polkitbackend/polkitbackendjsauthority.c b/src/polkitbackend/polkitbackendjsauthority.c
dc3ed5
index 88f31bd..39f7060 100644
dc3ed5
--- a/src/polkitbackend/polkitbackendjsauthority.c
dc3ed5
+++ b/src/polkitbackend/polkitbackendjsauthority.c
dc3ed5
@@ -482,6 +482,7 @@ polkit_backend_js_authority_constructed (GObject *object)
dc3ed5
 
dc3ed5
   if (authority->priv->js_global == NULL)
dc3ed5
     goto fail;
dc3ed5
+  JS_AddObjectRoot (authority->priv->cx, &authority->priv->js_global);
dc3ed5
 
dc3ed5
   if (!JS_InitStandardClasses (authority->priv->cx, authority->priv->js_global))
dc3ed5
     goto fail;
dc3ed5
@@ -494,6 +495,7 @@ polkit_backend_js_authority_constructed (GObject *object)
dc3ed5
                                                 JSPROP_ENUMERATE);
dc3ed5
   if (authority->priv->js_polkit == NULL)
dc3ed5
     goto fail;
dc3ed5
+  JS_AddObjectRoot (authority->priv->cx, &authority->priv->js_polkit);
dc3ed5
 
dc3ed5
   if (!JS_DefineFunctions (authority->priv->cx,
dc3ed5
                            authority->priv->js_polkit,
dc3ed5
@@ -572,6 +574,11 @@ polkit_backend_js_authority_finalize (GObject *object)
dc3ed5
   g_free (authority->priv->dir_monitors);
dc3ed5
   g_strfreev (authority->priv->rules_dirs);
dc3ed5
 
dc3ed5
+  JS_BeginRequest (authority->priv->cx);
dc3ed5
+  JS_RemoveObjectRoot (authority->priv->cx, &authority->priv->js_polkit);
dc3ed5
+  JS_RemoveObjectRoot (authority->priv->cx, &authority->priv->js_global);
dc3ed5
+  JS_EndRequest (authority->priv->cx);
dc3ed5
+
dc3ed5
   JS_DestroyContext (authority->priv->cx);
dc3ed5
   JS_DestroyRuntime (authority->priv->rt);
dc3ed5
   /* JS_ShutDown (); */
dc3ed5
dc3ed5
commit 2881f8b260c03df29afb0e35e6d1707240f95ad7
dc3ed5
Author: Miloslav Trmač <mitr@redhat.com>
dc3ed5
Date:   Tue Jul 1 20:00:48 2014 +0200
dc3ed5
dc3ed5
    Prevent builds against SpiderMonkey with exact stack rooting
dc3ed5
    
dc3ed5
    “Exact stack rooting” means that every on-stack pointer to a JavaScript
dc3ed5
    value needs to be registered with the runtime.  The current code doesn't
dc3ed5
    do this, so it is not safe to use against a runtime with this
dc3ed5
    configuration.  Luckily this configuration is not default.
dc3ed5
    
dc3ed5
    See
dc3ed5
    https://developer.mozilla.org/en-US/docs/SpiderMonkey/Internals/GC/Exact_Stack_Rooting
dc3ed5
    and other pages in the wiki for what the conversion would require.
dc3ed5
    
dc3ed5
    https://bugs.freedesktop.org/show_bug.cgi?id=69501
dc3ed5
dc3ed5
diff --git a/src/polkitbackend/polkitbackendjsauthority.c b/src/polkitbackend/polkitbackendjsauthority.c
dc3ed5
index 39f7060..22812a6 100644
dc3ed5
--- a/src/polkitbackend/polkitbackendjsauthority.c
dc3ed5
+++ b/src/polkitbackend/polkitbackendjsauthority.c
dc3ed5
@@ -43,6 +43,13 @@
dc3ed5
 
dc3ed5
 #include "initjs.h" /* init.js */
dc3ed5
 
dc3ed5
+#ifdef JSGC_USE_EXACT_ROOTING
dc3ed5
+/* See https://developer.mozilla.org/en-US/docs/SpiderMonkey/Internals/GC/Exact_Stack_Rooting
dc3ed5
+ * for more information about exact stack rooting.
dc3ed5
+ */
dc3ed5
+#error "This code is not safe in SpiderMonkey exact stack rooting configurations"
dc3ed5
+#endif
dc3ed5
+
dc3ed5
 /**
dc3ed5
  * SECTION:polkitbackendjsauthority
dc3ed5
  * @title: PolkitBackendJsAuthority
dc3ed5
dc3ed5
commit b544f10dd469ae3cfedc026db71ee76e9ef511a2
dc3ed5
Author: Miloslav Trmač <mitr@redhat.com>
dc3ed5
Date:   Tue Jul 1 20:00:48 2014 +0200
dc3ed5
dc3ed5
    Clear the JS operation callback before invoking JS in the callback
dc3ed5
    
dc3ed5
    Setting the callback to NULL is required by
dc3ed5
    https://developer.mozilla.org/en-US/docs/SpiderMonkey/JSAPI_Reference/JS_SetOperationCallback
dc3ed5
    to avoid the possibility of recursion.
dc3ed5
    
dc3ed5
    https://bugs.freedesktop.org/show_bug.cgi?id=69501
dc3ed5
dc3ed5
diff --git a/src/polkitbackend/polkitbackendjsauthority.c b/src/polkitbackend/polkitbackendjsauthority.c
dc3ed5
index 22812a6..8a0a097 100644
dc3ed5
--- a/src/polkitbackend/polkitbackendjsauthority.c
dc3ed5
+++ b/src/polkitbackend/polkitbackendjsauthority.c
dc3ed5
@@ -961,9 +961,11 @@ js_operation_callback (JSContext *cx)
dc3ed5
   polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority), "Terminating runaway script");
dc3ed5
 
dc3ed5
   /* Throw an exception - this way the JS code can ignore the runaway script handling */
dc3ed5
+  JS_SetOperationCallback (authority->priv->cx, NULL);
dc3ed5
   val_str = JS_NewStringCopyZ (cx, "Terminating runaway script");
dc3ed5
   val = STRING_TO_JSVAL (val_str);
dc3ed5
   JS_SetPendingException (authority->priv->cx, val);
dc3ed5
+  JS_SetOperationCallback (authority->priv->cx, js_operation_callback);
dc3ed5
   return JS_FALSE;
dc3ed5
 }
dc3ed5
 
dc3ed5
dc3ed5
commit d7da6a23766e9c95fa333a0a9c742f7397c0ad22
dc3ed5
Author: Miloslav Trmač <mitr@redhat.com>
dc3ed5
Date:   Tue Jul 1 20:00:48 2014 +0200
dc3ed5
dc3ed5
    Fix spurious timeout exceptions on GC
dc3ed5
    
dc3ed5
    The JS “Operation callback” can be called by the runtime for other
dc3ed5
    reasons, not only when we trigger it by a timeout—notably as part of GC.
dc3ed5
    So, make sure to only raise an exception if there actually was a
dc3ed5
    timeout.
dc3ed5
    
dc3ed5
    Adding a whole extra mutex to protect a single boolean is somewhat of an
dc3ed5
    overkill, but better than worrying about “subtle bugs and occasionally
dc3ed5
    undefined behaviour” the g_atomic_* API is warning about.
dc3ed5
    
dc3ed5
    https://bugs.freedesktop.org/show_bug.cgi?id=69501
dc3ed5
    also
dc3ed5
    https://bugs.freedesktop.org/show_bug.cgi?id=77524
dc3ed5
dc3ed5
diff --git a/src/polkitbackend/polkitbackendjsauthority.c b/src/polkitbackend/polkitbackendjsauthority.c
dc3ed5
index 8a0a097..097dcc5 100644
dc3ed5
--- a/src/polkitbackend/polkitbackendjsauthority.c
dc3ed5
+++ b/src/polkitbackend/polkitbackendjsauthority.c
dc3ed5
@@ -80,6 +80,8 @@ struct _PolkitBackendJsAuthorityPrivate
dc3ed5
   GMainContext *rkt_context;
dc3ed5
   GMainLoop *rkt_loop;
dc3ed5
   GSource *rkt_source;
dc3ed5
+  GMutex rkt_timeout_pending_mutex;
dc3ed5
+  gboolean rkt_timeout_pending;
dc3ed5
 
dc3ed5
   /* A list of JSObject instances */
dc3ed5
   GList *scripts;
dc3ed5
@@ -528,6 +530,7 @@ polkit_backend_js_authority_constructed (GObject *object)
dc3ed5
 
dc3ed5
   g_mutex_init (&authority->priv->rkt_init_mutex);
dc3ed5
   g_cond_init (&authority->priv->rkt_init_cond);
dc3ed5
+  g_mutex_init (&authority->priv->rkt_timeout_pending_mutex);
dc3ed5
 
dc3ed5
   authority->priv->runaway_killer_thread = g_thread_new ("runaway-killer-thread",
dc3ed5
                                                          runaway_killer_thread_func,
dc3ed5
@@ -563,6 +566,7 @@ polkit_backend_js_authority_finalize (GObject *object)
dc3ed5
 
dc3ed5
   g_mutex_clear (&authority->priv->rkt_init_mutex);
dc3ed5
   g_cond_clear (&authority->priv->rkt_init_cond);
dc3ed5
+  g_mutex_clear (&authority->priv->rkt_timeout_pending_mutex);
dc3ed5
 
dc3ed5
   /* shut down the killer thread */
dc3ed5
   g_assert (authority->priv->rkt_loop != NULL);
dc3ed5
@@ -957,6 +961,18 @@ js_operation_callback (JSContext *cx)
dc3ed5
   JSString *val_str;
dc3ed5
   jsval val;
dc3ed5
 
dc3ed5
+  /* This callback can be called by the runtime at any time without us causing
dc3ed5
+   * it by JS_TriggerOperationCallback().
dc3ed5
+   */
dc3ed5
+  g_mutex_lock (&authority->priv->rkt_timeout_pending_mutex);
dc3ed5
+  if (!authority->priv->rkt_timeout_pending)
dc3ed5
+    {
dc3ed5
+      g_mutex_unlock (&authority->priv->rkt_timeout_pending_mutex);
dc3ed5
+      return JS_TRUE;
dc3ed5
+    }
dc3ed5
+  authority->priv->rkt_timeout_pending = FALSE;
dc3ed5
+  g_mutex_unlock (&authority->priv->rkt_timeout_pending_mutex);
dc3ed5
+
dc3ed5
   /* Log that we are terminating the script */
dc3ed5
   polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority), "Terminating runaway script");
dc3ed5
 
dc3ed5
@@ -974,6 +990,10 @@ rkt_on_timeout (gpointer user_data)
dc3ed5
 {
dc3ed5
   PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (user_data);
dc3ed5
 
dc3ed5
+  g_mutex_lock (&authority->priv->rkt_timeout_pending_mutex);
dc3ed5
+  authority->priv->rkt_timeout_pending = TRUE;
dc3ed5
+  g_mutex_unlock (&authority->priv->rkt_timeout_pending_mutex);
dc3ed5
+
dc3ed5
   /* Supposedly this is thread-safe... */
dc3ed5
 #if JS_VERSION == 186
dc3ed5
   JS_TriggerOperationCallback (authority->priv->rt);
dc3ed5
@@ -993,6 +1013,9 @@ runaway_killer_setup (PolkitBackendJsAuthority *authority)
dc3ed5
   g_assert (authority->priv->rkt_source == NULL);
dc3ed5
 
dc3ed5
   /* set-up timer for runaway scripts, will be executed in runaway_killer_thread */
dc3ed5
+  g_mutex_lock (&authority->priv->rkt_timeout_pending_mutex);
dc3ed5
+  authority->priv->rkt_timeout_pending = FALSE;
dc3ed5
+  g_mutex_unlock (&authority->priv->rkt_timeout_pending_mutex);
dc3ed5
   authority->priv->rkt_source = g_timeout_source_new_seconds (15);
dc3ed5
   g_source_set_callback (authority->priv->rkt_source, rkt_on_timeout, authority, NULL);
dc3ed5
   g_source_attach (authority->priv->rkt_source, authority->priv->rkt_context);