This repository has been archived by the owner on Apr 26, 2024. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Mitigate a race where /make_join could 403 for restricted rooms #15080
Merged
squahtx
merged 1 commit into
develop
from
squah/mitigate_restricted_room_make_join_race
Feb 17, 2023
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Reduce the likelihood of a rare race condition where rejoining a restricted room over federation would fail. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -952,7 +952,20 @@ async def on_make_join_request( | |
# | ||
# Note that this requires the /send_join request to come back to the | ||
# same server. | ||
prev_event_ids = None | ||
if room_version.msc3083_join_rules: | ||
# Note that the room's state can change out from under us and render our | ||
# nice join rules-conformant event non-conformant by the time we build the | ||
# event. When this happens, our validation at the end fails and we respond | ||
# to the requesting server with a 403, which is misleading — it indicates | ||
# that the user is not allowed to join the room and the joining server | ||
# should not bother retrying via this homeserver or any others, when | ||
# in fact we've just messed up with building the event. | ||
# | ||
# To reduce the likelihood of this race, we capture the forward extremities | ||
# of the room (prev_event_ids) just before fetching the current state, and | ||
# hope that the state we fetch corresponds to the prev events we chose. | ||
prev_event_ids = await self.store.get_prev_events_for_room(room_id) | ||
state_ids = await self._state_storage_controller.get_current_state_ids( | ||
room_id | ||
) | ||
Comment on lines
969
to
971
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wanted to calculate the state off the prev events, but that looked like it would involve state resolution which is slow. |
||
|
@@ -994,7 +1007,8 @@ async def on_make_join_request( | |
event, | ||
unpersisted_context, | ||
) = await self.event_creation_handler.create_new_client_event( | ||
builder=builder | ||
builder=builder, | ||
prev_event_ids=prev_event_ids, | ||
) | ||
except SynapseError as e: | ||
logger.warning("Failed to create join to %s because %s", room_id, e) | ||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pedantry: there can be at most 20 prev events in a given event, so in the worst case the prev events are a subset of the forward extremities of the room. I don't think we need to say that here (but I couldn't resist pointing it out now).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's annoying, since the prev events we feed in won't always be representative of the room state the event is evaluated against.
Though I note that right now we hit an assert if there are more than 10 prev events.
synapse/synapse/handlers/message.py
Lines 1164 to 1169 in 5febf88
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good to know. FWIW The spec says
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It turns out that
get_prev_events_for_room
only returns up to 10 forward extremities, so the prev events we feed in to the event builder will be the ones used. I hadn't quite realised thatget_prev_events_for_room
was subtly different to fetching the forward extremities.synapse/synapse/storage/databases/main/event_federation.py
Lines 1087 to 1099 in d0c713c