Limit the number of key descriptors sent back
In case the number of key descriptors and their content exceeds the
binder transaction size limit, only return a subset that does fit.
This is a temporary fix - long-term fix is to introduce new API that
lets the caller specify the range of aliases to be fetched.
Bug: 222287335
Test: Manual: Generate 100 keys with a 6k characters name each.
Change-Id: I5e8543a25dd9f1bb504fbc23f35779da0a0153b0
diff --git a/keystore2/src/utils.rs b/keystore2/src/utils.rs
index 75d98e2..1bae75e 100644
--- a/keystore2/src/utils.rs
+++ b/keystore2/src/utils.rs
@@ -276,7 +276,40 @@
);
result.sort_unstable();
result.dedup();
- Ok(result)
+
+ let mut items_to_return = 0;
+ let mut returned_bytes: usize = 0;
+ const RESPONSE_SIZE_LIMIT: usize = 358400;
+ // Estimate the transaction size to avoid returning more items than what
+ // could fit in a binder transaction.
+ for kd in result.iter() {
+ // 4 bytes for the Domain enum
+ // 8 bytes for the Namespace long.
+ returned_bytes += 4 + 8;
+ // Size of the alias string. Includes 4 bytes for length encoding.
+ if let Some(alias) = &kd.alias {
+ returned_bytes += 4 + alias.len();
+ }
+ // Size of the blob. Includes 4 bytes for length encoding.
+ if let Some(blob) = &kd.blob {
+ returned_bytes += 4 + blob.len();
+ }
+ // The binder transaction size limit is 1M. Empirical measurements show
+ // that the binder overhead is 60% (to be confirmed). So break after
+ // 350KB and return a partial list.
+ if returned_bytes > RESPONSE_SIZE_LIMIT {
+ log::warn!(
+ "Key descriptors list ({} items) may exceed binder \
+ size, returning {} items est {} bytes.",
+ result.len(),
+ items_to_return,
+ returned_bytes
+ );
+ break;
+ }
+ items_to_return += 1;
+ }
+ Ok(result[..items_to_return].to_vec())
}
/// This module provides helpers for simplified use of the watchdog module.