summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibWeb
diff options
context:
space:
mode:
authorTobias Christiansen <tobi@tobyase.de>2021-04-19 14:30:08 +0200
committerAndreas Kling <kling@serenityos.org>2021-05-07 22:34:34 +0200
commit1b6824d2962b534b34b2d3ec6ba3ab5f77bc68b5 (patch)
tree64f45efd5d2fc4e88716b6f0edf3a9762c361394 /Userland/Libraries/LibWeb
parent9e49895bbf941339e971be383723822fbd422b23 (diff)
downloadserenity-1b6824d2962b534b34b2d3ec6ba3ab5f77bc68b5.zip
LibWeb: Make frames nesting-aware and disallow deep nesting
A Frame now knows about its nesting-level. The FrameLoader checks whether the recursion level of the current frame allows it to be displayed and if not doesn't even load the requested resource. The nesting-check is done on a per-URL-basis, so there can be many many nested Frames as long as they have different URLs. If there are however Frames with the same URL nested inside each other we only allow this to happen 3 times. This mitigates infinetely recursing <iframe>s in an HTML-document crashing the browser with an OOM.
Diffstat (limited to 'Userland/Libraries/LibWeb')
-rw-r--r--Userland/Libraries/LibWeb/HTML/FrameHostElement.cpp5
-rw-r--r--Userland/Libraries/LibWeb/Loader/FrameLoader.cpp5
-rw-r--r--Userland/Libraries/LibWeb/Page/Frame.cpp10
-rw-r--r--Userland/Libraries/LibWeb/Page/Frame.h8
4 files changed, 27 insertions, 1 deletions
diff --git a/Userland/Libraries/LibWeb/HTML/FrameHostElement.cpp b/Userland/Libraries/LibWeb/HTML/FrameHostElement.cpp
index 19d5d6a560..30b338a8d3 100644
--- a/Userland/Libraries/LibWeb/HTML/FrameHostElement.cpp
+++ b/Userland/Libraries/LibWeb/HTML/FrameHostElement.cpp
@@ -26,8 +26,11 @@ void FrameHostElement::inserted()
HTMLElement::inserted();
if (!is_connected())
return;
- if (auto* frame = document().frame())
+ if (auto* frame = document().frame()) {
m_content_frame = Frame::create_subframe(*this, frame->main_frame());
+ m_content_frame->set_frame_nesting_levels(frame->frame_nesting_levels());
+ m_content_frame->register_frame_nesting(document().url());
+ }
}
Origin FrameHostElement::content_origin() const
diff --git a/Userland/Libraries/LibWeb/Loader/FrameLoader.cpp b/Userland/Libraries/LibWeb/Loader/FrameLoader.cpp
index d0052aed99..c36000191b 100644
--- a/Userland/Libraries/LibWeb/Loader/FrameLoader.cpp
+++ b/Userland/Libraries/LibWeb/Loader/FrameLoader.cpp
@@ -136,6 +136,11 @@ bool FrameLoader::load(const LoadRequest& request, Type type)
return false;
}
+ if (!m_frame.is_frame_nesting_allowed(request.url())) {
+ dbgln("No further recursion is allowed for the frame, abort load!");
+ return false;
+ }
+
auto& url = request.url();
set_resource(ResourceLoader::the().load_resource(Resource::Type::Generic, request));
diff --git a/Userland/Libraries/LibWeb/Page/Frame.cpp b/Userland/Libraries/LibWeb/Page/Frame.cpp
index 99c0e111b3..0a4386fadc 100644
--- a/Userland/Libraries/LibWeb/Page/Frame.cpp
+++ b/Userland/Libraries/LibWeb/Page/Frame.cpp
@@ -286,4 +286,14 @@ void Frame::unregister_viewport_client(ViewportClient& client)
VERIFY(was_removed);
}
+void Frame::register_frame_nesting(URL const& url)
+{
+ m_frame_nesting_levels.ensure(url)++;
+}
+
+bool Frame::is_frame_nesting_allowed(URL const& url) const
+{
+ return m_frame_nesting_levels.get(url).value_or(0) < 3;
+}
+
}
diff --git a/Userland/Libraries/LibWeb/Page/Frame.h b/Userland/Libraries/LibWeb/Page/Frame.h
index 49370b8683..daac863581 100644
--- a/Userland/Libraries/LibWeb/Page/Frame.h
+++ b/Userland/Libraries/LibWeb/Page/Frame.h
@@ -81,6 +81,12 @@ public:
void did_edit(Badge<EditEventHandler>);
+ void register_frame_nesting(URL const&);
+ bool is_frame_nesting_allowed(URL const&) const;
+
+ void set_frame_nesting_levels(const HashMap<URL, size_t> frame_nesting_levels) { m_frame_nesting_levels = move(frame_nesting_levels); };
+ HashMap<URL, size_t> const& frame_nesting_levels() const { return m_frame_nesting_levels; }
+
private:
explicit Frame(DOM::Element& host_element, Frame& main_frame);
explicit Frame(Page&);
@@ -105,6 +111,8 @@ private:
bool m_cursor_blink_state { false };
HashTable<ViewportClient*> m_viewport_clients;
+
+ HashMap<URL, size_t> m_frame_nesting_levels;
};
}