summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Bendebury <vbendeb@chromium.org>2017-02-20 12:15:52 -0800
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2017-03-02 16:48:25 +0000
commit00d4dd954399a07641bd5b30f070bcc663a128e6 (patch)
tree0a780de6fe424adb12867def488432bf35f69637
parent1210ff1b9c9b288ffe11bf8e123fc795b09a151d (diff)
downloadchrome-ec-00d4dd954399a07641bd5b30f070bcc663a128e6.tar.gz
g: rate limit firmware updates
This patch introduces a delay between accepted cr50 firmware upload attempts. The next attempt to write into the same or lower address in flash would be accepted no sooner than in 60 seconds after the previous attempt. This would prevent a rogue user from wearing the flash by repeated uploads to the same address. This limitation is not imposed by dev images (those compiled with CR50_DEV=1). BRANCH=none BUG=chrome-os-partner:63098 TEST=verified that attempts to update soon after the previous update result in the following error message issued by usb_updater: sending 0x2d8b8 bytes to 0x4000 Error: status 0x9 Modified usb_updater to send one random pdu twice. Observed the same error message. Change-Id: Idca55ad091d09daaddd0a4cad5b1f871af1ede93 Signed-off-by: Vadim Bendebury <vbendeb@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/445496 Reviewed-by: Randall Spangler <rspangler@chromium.org> (cherry picked from commit 5221d127e157240a1e3b2275190b2686dfafe6e5) Reviewed-on: https://chromium-review.googlesource.com/448335
-rw-r--r--chip/g/upgrade_fw.c40
-rw-r--r--chip/g/upgrade_fw.h7
-rw-r--r--extra/usb_updater/usb_updater.c1
3 files changed, 47 insertions, 1 deletions
diff --git a/chip/g/upgrade_fw.c b/chip/g/upgrade_fw.c
index f36e5cbd7a..182f1308fc 100644
--- a/chip/g/upgrade_fw.c
+++ b/chip/g/upgrade_fw.c
@@ -252,7 +252,40 @@ static int contents_allowed(uint32_t block_offset,
return 1;
}
+
+static uint32_t prev_offset;
+static uint64_t prev_timestamp;
+#define BACKOFF_TIME (60 * SECOND)
+
+static int chunk_came_too_soon(uint32_t block_offset)
+{
+ if (!prev_timestamp ||
+ ((get_time().val - prev_timestamp) > BACKOFF_TIME))
+ return 0;
+
+ if (!prev_offset ||
+ (block_offset >= (prev_offset + SIGNED_TRANSFER_SIZE)))
+ return 0;
+
+ CPRINTF("%s: rejecting a write to the same block\n", __func__);
+ return 1;
+}
+
+static void new_chunk_written(uint32_t block_offset)
+{
+ prev_timestamp = get_time().val;
+ prev_offset = block_offset;
+}
#else
+static int chunk_came_too_soon(uint32_t block_offset)
+{
+ return 0;
+}
+
+static void new_chunk_written(uint32_t block_offset)
+{
+}
+
static int contents_allowed(uint32_t block_offset,
size_t body_size, void *upgrade_data)
{
@@ -354,6 +387,11 @@ void fw_upgrade_command_handler(void *body,
if (*error_code)
return;
+ if (chunk_came_too_soon(block_offset)) {
+ *error_code = UPGRADE_RATE_LIMIT_ERROR;
+ return;
+ }
+
CPRINTF("%s: programming at address 0x%x\n", __func__,
block_offset + CONFIG_PROGRAM_MEMORY_BASE);
if (flash_physical_write(block_offset, body_size, upgrade_data)
@@ -363,6 +401,8 @@ void fw_upgrade_command_handler(void *body,
return;
}
+ new_chunk_written(block_offset);
+
/* Verify that data was written properly. */
if (memcmp(upgrade_data, (void *)
(block_offset + CONFIG_PROGRAM_MEMORY_BASE),
diff --git a/chip/g/upgrade_fw.h b/chip/g/upgrade_fw.h
index 8fe0f0269c..092f2812fa 100644
--- a/chip/g/upgrade_fw.h
+++ b/chip/g/upgrade_fw.h
@@ -137,6 +137,13 @@ enum return_value {
UPGRADE_GEN_ERROR = 6,
UPGRADE_MALLOC_ERROR = 7,
UPGRADE_ROLLBACK_ERROR = 8,
+ UPGRADE_RATE_LIMIT_ERROR = 9,
};
+/*
+ * This is the size of the update frame payload, unless this is the last chunk
+ * of the image.
+ */
+#define SIGNED_TRANSFER_SIZE 1024
+
#endif /* ! __EC_CHIP_G_UPGRADE_FW_H */
diff --git a/extra/usb_updater/usb_updater.c b/extra/usb_updater/usb_updater.c
index e41c3027b1..50d7cfaf3c 100644
--- a/extra/usb_updater/usb_updater.c
+++ b/extra/usb_updater/usb_updater.c
@@ -179,7 +179,6 @@ struct upgrade_pkt {
char data[0];
} __packed;
-#define SIGNED_TRANSFER_SIZE 1024
#define MAX_BUF_SIZE (SIGNED_TRANSFER_SIZE + sizeof(struct upgrade_pkt))
struct usb_endpoint {