[Misc] Remove Hash from IPCCacheEngineKey#2700
Conversation
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request refactors how Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request refactors the code to remove the chunk_hash from IPCCacheEngineKey, generating chunk hashes on-the-fly and passing them to a new ipc_key_to_object_keys function, which is a good design improvement. However, the changes introduce multiple Denial of Service (DoS) vulnerabilities due to a lack of validation for client-provided input in the IPCCacheEngineKey. Specifically, unvalidated world_size, request_id, start, end, and token_ids can be exploited to crash worker threads or exhaust server resources. Additionally, my review includes suggestions to improve maintainability by reducing code duplication that has emerged from these changes.
| for chunk_hash in chunk_hashes: | ||
| if ipc_key.worker_id is None: | ||
| # For look up request, we want to expand to all workers | ||
| for worker_id in range(ipc_key.world_size): |
There was a problem hiding this comment.
The ipc_key_to_object_keys function uses key.world_size directly in a range() call within a loop. Since key is provided by the client and its fields are not validated, an attacker can provide a very large world_size to cause excessive CPU and memory consumption on the server, leading to a Denial of Service (DoS). It is recommended to validate that world_size is within a reasonable range (e.g., 1 to 1024) before processing. Additionally, the if/else block contains duplicated code for creating ObjectKey instances; consider refactoring for conciseness.
| session = self.session_manager.get_or_create(key.request_id) | ||
| session.set_tokens(list(key.token_ids)) | ||
| chunk_hashes = [ | ||
| TokenHasher.hash_to_bytes(h) for h in session.get_hashes(key.start, key.end) |
There was a problem hiding this comment.
The store and retrieve methods call session.get_hashes(key.start, key.end), which contains assertions that start and end must be multiples of chunk_size. Since these client-provided values are not validated, an attacker can provide unaligned values to trigger an assertion failure and crash the worker thread, leading to a Denial of Service. It is recommended to validate the alignment of start and end and handle errors gracefully. Additionally, the logic for initializing a session and retrieving chunk hashes is duplicated; consider extracting it into a private helper method.
| chunk_hashes = [ | ||
| TokenHasher.hash_to_bytes(h) | ||
| for h in self.token_hasher.compute_chunk_hashes( | ||
| list(temp_ipc_key.token_ids), True, self.BLEND_HASH_PREFIX |
There was a problem hiding this comment.
In cb_lookup_pre_computed, list(temp_ipc_key.token_ids) creates a copy of client-provided token IDs. If an attacker sends a request with an extremely large number of token IDs, this can lead to excessive memory consumption and a Denial of Service. It is recommended to validate the length of token_ids before processing. Furthermore, this block for computing chunk hashes is repeated multiple times; consider extracting it into a private helper method within the BlendEngine class to reduce duplication.
| # 1. the world size is the same between keys | ||
| # 2. the lookup sort the keys in prefix order and breaks at the first failure | ||
| found_count = found_count // ipc_keys[0].world_size | ||
| found_count = found_count // key.world_size |
There was a problem hiding this comment.
The lookup method uses key.world_size as a divisor without checking if it is zero. A malicious client can provide a world_size of 0 in the IPCCacheEngineKey to trigger a ZeroDivisionError, which will crash the worker thread handling the request. This can be exploited to cause a Denial of Service by repeatedly crashing all available worker threads.
| """ | ||
| update_session_for_key(key, self.session_manager) | ||
| ipc_keys = resolve_key(key, self.session_manager) | ||
| session = self.session_manager.get_or_create(key.request_id) |
There was a problem hiding this comment.
The store and retrieve methods call self.session_manager.get_or_create(key.request_id), which creates and stores a new Session object for every unique request_id provided by the client. There is no limit on the number of active sessions and no automatic cleanup of expired sessions in the request handling flow. An attacker can send a large number of requests with unique request_ids to exhaust the server's memory. It is recommended to implement a session limit and periodic cleanup of expired sessions.
| chunk_hashes = [ | ||
| TokenHasher.hash_to_bytes(h) | ||
| for h in self.token_hasher.compute_chunk_hashes(list(key.token_ids), True) | ||
| ] |
| TokenHasher.hash_to_bytes(h) | ||
| for h in self.token_hasher.compute_chunk_hashes(list(key.token_ids), True) |
There was a problem hiding this comment.
Can we put hash_to_bytes into compute_chunk_hashes
Signed-off-by: Oasis-Git <ayw.sirius19@gmail.com>
Signed-off-by: Oasis-Git <ayw.sirius19@gmail.com> Signed-off-by: Aaron Wu <aaron.wu@dell.com>
Signed-off-by: Oasis-Git <ayw.sirius19@gmail.com>
Signed-off-by: Oasis-Git <ayw.sirius19@gmail.com>
What this PR does / why we need it:
Remove the hash from IPCCacheEngineKey. Generate Hash list directly with IPCCacheEngineKey and set in ObjKey
Special notes for your reviewers:
If applicable: