Bug 1190641 part 3. Add the sandbox propagates to auxiliary browsing contexts flag to iframe sandboxing. r=ckerschb
☠☠ backed out by b7be22142cf4 ☠ ☠
authorBoris Zbarsky <bzbarsky@mit.edu>
Fri, 06 May 2016 13:56:36 -0400
changeset 296434 ef1d1a4334157c6e26a6006ae6e949222e4f6c89
parent 296433 b037f264208284688c059587db7e45158596c256
child 296435 02f0e7bad6ff654f5aae54e1c8eaa5c1340a181a
push id76327
push userbzbarsky@mozilla.com
push dateFri, 06 May 2016 18:04:36 +0000
treeherdermozilla-inbound@ef1d1a433415 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersckerschb
bugs1190641
milestone49.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1190641 part 3. Add the sandbox propagates to auxiliary browsing contexts flag to iframe sandboxing. r=ckerschb
dom/base/IframeSandboxKeywordList.h
dom/base/nsGkAtomList.h
dom/base/nsSandboxFlags.h
embedding/components/windowwatcher/nsWindowWatcher.cpp
testing/web-platform/meta/MANIFEST.json
testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping.html
testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_helper.html
testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping.html
--- a/dom/base/IframeSandboxKeywordList.h
+++ b/dom/base/IframeSandboxKeywordList.h
@@ -18,9 +18,10 @@ SANDBOX_KEYWORD("allow-scripts", allowsc
 		SANDBOXED_SCRIPTS | SANDBOXED_AUTOMATIC_FEATURES)
 SANDBOX_KEYWORD("allow-top-navigation", allowtopnavigation,
 		SANDBOXED_TOPLEVEL_NAVIGATION)
 SANDBOX_KEYWORD("allow-pointer-lock", allowpointerlock, SANDBOXED_POINTER_LOCK)
 SANDBOX_KEYWORD("allow-orientation-lock", alloworientationlock,
 		SANDBOXED_ORIENTATION_LOCK)
 SANDBOX_KEYWORD("allow-popups", allowpopups, SANDBOXED_AUXILIARY_NAVIGATION)
 SANDBOX_KEYWORD("allow-modals", allowmodals, SANDBOXED_MODALS)
-
+SANDBOX_KEYWORD("allow-popups-to-escape-sandbox", allowpopupstoescapesandbox,
+                SANDBOX_PROPAGATES_TO_AUXILIARY_BROWSING_CONTEXTS)
--- a/dom/base/nsGkAtomList.h
+++ b/dom/base/nsGkAtomList.h
@@ -77,16 +77,17 @@ GK_ATOM(alink, "alink")
 GK_ATOM(all, "all")
 GK_ATOM(allowevents, "allowevents")
 GK_ATOM(allownegativeassertions, "allownegativeassertions")
 GK_ATOM(allowforms,"allow-forms")
 GK_ATOM(allowfullscreen, "allowfullscreen")
 GK_ATOM(allowmodals, "allow-modals")
 GK_ATOM(alloworientationlock,"allow-orientation-lock")
 GK_ATOM(allowpointerlock,"allow-pointer-lock")
+GK_ATOM(allowpopupstoescapesandbox,"allow-popups-to-escape-sandbox")
 GK_ATOM(allowpopups,"allow-popups")
 GK_ATOM(allowsameorigin,"allow-same-origin")
 GK_ATOM(allowscripts,"allow-scripts")
 GK_ATOM(allowtopnavigation,"allow-top-navigation")
 GK_ATOM(allowuntrusted, "allowuntrusted")
 GK_ATOM(alt, "alt")
 GK_ATOM(alternate, "alternate")
 GK_ATOM(always, "always")
--- a/dom/base/nsSandboxFlags.h
+++ b/dom/base/nsSandboxFlags.h
@@ -97,14 +97,21 @@ const unsigned long SANDBOXED_DOMAIN = 0
 /**
  * This flag prevents content from using window.alert(), window.confirm(),
  * window.print(), window.prompt() and the beforeunload event from putting up
  * dialogs.
  */
 const unsigned long SANDBOXED_MODALS = 0x1000;
 
 /**
+ * This flag prevents content from escaping the sandbox by ensuring that any
+ * auxiliary browsing context it creates inherits the content's active
+ * sandboxing flag set.
+ */
+const unsigned long SANDBOX_PROPAGATES_TO_AUXILIARY_BROWSING_CONTEXTS = 0x2000;
+
+/**
  * This flag prevents locking screen orientation.
  */
-const unsigned long SANDBOXED_ORIENTATION_LOCK = 0x2000;
+const unsigned long SANDBOXED_ORIENTATION_LOCK = 0x4000;
 
-const unsigned long SANDBOX_ALL_FLAGS = 0x3FFF;
+const unsigned long SANDBOX_ALL_FLAGS = 0x7FFF;
 #endif
--- a/embedding/components/windowwatcher/nsWindowWatcher.cpp
+++ b/embedding/components/windowwatcher/nsWindowWatcher.cpp
@@ -867,19 +867,21 @@ nsWindowWatcher::OpenWindowInternal(mozI
   // better have a window to use by this point
   if (!newDocShellItem) {
     return rv;
   }
 
   nsCOMPtr<nsIDocShell> newDocShell(do_QueryInterface(newDocShellItem));
   NS_ENSURE_TRUE(newDocShell, NS_ERROR_UNEXPECTED);
 
-  // Set up sandboxing attributes if the window is new.
-  // The flags can only be non-zero for new windows.
-  if (activeDocsSandboxFlags != 0) {
+  // Copy sandbox flags to the new window if activeDocsSandboxFlags says to do
+  // so.  Note that it's only nonzero if the window is new, so clobbering
+  // sandbox flags on the window makes sense in that case.
+  if (activeDocsSandboxFlags &
+        SANDBOX_PROPAGATES_TO_AUXILIARY_BROWSING_CONTEXTS) {
     newDocShell->SetSandboxFlags(activeDocsSandboxFlags);
     if (parentWindow) {
       newDocShell->SetOnePermittedSandboxedNavigator(
         parentWindow->GetDocShell());
     }
   }
 
   rv = ReadyOpenedDocShellItem(newDocShellItem, parentWindow, windowIsNew, aResult);
--- a/testing/web-platform/meta/MANIFEST.json
+++ b/testing/web-platform/meta/MANIFEST.json
@@ -40789,16 +40789,28 @@
           }
         ],
         "html/semantics/embedded-content/the-iframe-element/iframe-load-event.html": [
           {
             "path": "html/semantics/embedded-content/the-iframe-element/iframe-load-event.html",
             "url": "/html/semantics/embedded-content/the-iframe-element/iframe-load-event.html"
           }
         ],
+        "html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping.html": [
+          {
+            "path": "html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping.html",
+            "url": "/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping.html"
+          }
+        ],
+        "html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping.html": [
+          {
+            "path": "html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping.html",
+            "url": "/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping.html"
+          }
+        ],
         "html/syntax/serializing-html-fragments/serializing.html": [
           {
             "path": "html/syntax/serializing-html-fragments/serializing.html",
             "url": "/html/syntax/serializing-html-fragments/serializing.html"
           }
         ],
         "html/webappapis/scripting/processing-model-2/window-onerror-with-cross-frame-event-listeners-1.html": [
           {
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Check that popups from a sandboxed iframe escape the sandbox if
+       allow-popups-to-escape-sandbox is used</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<iframe sandbox="allow-scripts allow-popups allow-popups-to-escape-sandbox">
+</iframe>
+<script>
+  var t = async_test();
+  var ourOrigin;
+  onmessage = t.step_func(function(e) {
+    assert_equals(e.data, "hello", "This is our origin getter message");
+    ourOrigin = e.origin;
+
+    onmessage = t.step_func_done(function(e) {
+      assert_equals(e.origin, "null", "It came from a sandboxed iframe");
+      assert_equals(e.data.data, undefined, "Should have the right message");
+      assert_equals(e.data.origin, ourOrigin, "Should have escaped the sandbox");
+    });
+
+    document.querySelector("iframe").src = "iframe_sandbox_popups_helper.html";
+  });
+  postMessage("hello", "*");
+</script>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_helper.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<script>
+  var popupWin;
+  if (opener) {
+    // We're the popup.  Send back our state.  What we really want to send is
+    // our origin, but that will come automatically.
+    opener.postMessage(undefined, "*");
+    self.close();
+  } else {
+    // We're the child.  Start listening for messages and open ourselves as the
+    // popup.
+    onmessage = function (e) {
+      parent.postMessage({ data: e.data, origin: e.origin }, "*");
+    };
+    popupWin = window.open(location.href);
+  }
+</script>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Check that popups from a sandboxed iframe do not escape the sandbox</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+  var t = async_test();
+  onmessage = t.step_func_done(function(e) {
+    assert_equals(e.origin, "null", "It came from a sandboxed iframe");
+    assert_equals(e.data.data, undefined, "Should have the right message");
+    assert_equals(e.data.origin, "null", "Should not have escaped the sandbox");
+  });
+</script>
+<iframe sandbox="allow-scripts allow-popups"
+        src="iframe_sandbox_popups_helper.html"></iframe>