From ba6d9c1a971db3c42bf0b054ebb64f72b3e3ddba Mon Sep 17 00:00:00 2001
From: Dean Camera <dean@fourwalledcubicle.com>
Date: Mon, 22 Jan 2018 16:14:44 +1100
Subject: [PATCH] Fixed bootloaders accepting flash writes to the bootloader
 region (thanks to NicoHood).

---
 Bootloaders/CDC/BootloaderAPI.c         | 15 +++++++++++++++
 Bootloaders/DFU/BootloaderAPI.c         | 15 +++++++++++++++
 Bootloaders/HID/BootloaderHID.c         |  6 +++++-
 Bootloaders/MassStorage/BootloaderAPI.c | 15 +++++++++++++++
 Bootloaders/Printer/BootloaderAPI.c     | 15 +++++++++++++++
 LUFA/DoxygenPages/ChangeLog.txt         |  1 +
 6 files changed, 66 insertions(+), 1 deletion(-)

diff --git a/Bootloaders/CDC/BootloaderAPI.c b/Bootloaders/CDC/BootloaderAPI.c
index 5e8083ed3..c1e76d3bd 100644
--- a/Bootloaders/CDC/BootloaderAPI.c
+++ b/Bootloaders/CDC/BootloaderAPI.c
@@ -35,8 +35,20 @@
 
 #include "BootloaderAPI.h"
 
+static bool IsPageAddressValid(const uint32_t Address)
+{
+	/* Determine if the given page address is correctly aligned to the
+	   start of a flash page. */
+	bool PageAddressIsAligned = !(Address & (SPM_PAGESIZE - 1));
+
+	return (Address < BOOT_START_ADDR) && PageAddressIsAligned;
+}
+
 void BootloaderAPI_ErasePage(const uint32_t Address)
 {
+	if (! IsPageAddressValid(Address))
+		return;
+
 	ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
 	{
 		boot_page_erase_safe(Address);
@@ -47,6 +59,9 @@ void BootloaderAPI_ErasePage(const uint32_t Address)
 
 void BootloaderAPI_WritePage(const uint32_t Address)
 {
+	if (! IsPageAddressValid(Address))
+		return;
+
 	ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
 	{
 		boot_page_write_safe(Address);
diff --git a/Bootloaders/DFU/BootloaderAPI.c b/Bootloaders/DFU/BootloaderAPI.c
index 5e8083ed3..c1e76d3bd 100644
--- a/Bootloaders/DFU/BootloaderAPI.c
+++ b/Bootloaders/DFU/BootloaderAPI.c
@@ -35,8 +35,20 @@
 
 #include "BootloaderAPI.h"
 
+static bool IsPageAddressValid(const uint32_t Address)
+{
+	/* Determine if the given page address is correctly aligned to the
+	   start of a flash page. */
+	bool PageAddressIsAligned = !(Address & (SPM_PAGESIZE - 1));
+
+	return (Address < BOOT_START_ADDR) && PageAddressIsAligned;
+}
+
 void BootloaderAPI_ErasePage(const uint32_t Address)
 {
+	if (! IsPageAddressValid(Address))
+		return;
+
 	ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
 	{
 		boot_page_erase_safe(Address);
@@ -47,6 +59,9 @@ void BootloaderAPI_ErasePage(const uint32_t Address)
 
 void BootloaderAPI_WritePage(const uint32_t Address)
 {
+	if (! IsPageAddressValid(Address))
+		return;
+
 	ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
 	{
 		boot_page_write_safe(Address);
diff --git a/Bootloaders/HID/BootloaderHID.c b/Bootloaders/HID/BootloaderHID.c
index c21bf5692..e5b7d3258 100644
--- a/Bootloaders/HID/BootloaderHID.c
+++ b/Bootloaders/HID/BootloaderHID.c
@@ -152,6 +152,10 @@ void EVENT_USB_Device_ControlRequest(void)
 			uint16_t PageAddress = Endpoint_Read_16_LE();
 			#endif
 
+			/* Determine if the given page address is correctly aligned to the
+			   start of a flash page. */
+			bool PageAddressIsAligned = !(PageAddress & (SPM_PAGESIZE - 1));
+
 			/* Check if the command is a program page command, or a start application command */
 			#if (FLASHEND > 0xFFFF)
 			if ((uint16_t)(PageAddress >> 8) == COMMAND_STARTAPPLICATION)
@@ -161,7 +165,7 @@ void EVENT_USB_Device_ControlRequest(void)
 			{
 				RunBootloader = false;
 			}
-			else if (PageAddress < BOOT_START_ADDR)
+			else if ((PageAddress < BOOT_START_ADDR) && PageAddressIsAligned)
 			{
 				/* Erase the given FLASH page, ready to be programmed */
 				ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
diff --git a/Bootloaders/MassStorage/BootloaderAPI.c b/Bootloaders/MassStorage/BootloaderAPI.c
index 5e8083ed3..c1e76d3bd 100644
--- a/Bootloaders/MassStorage/BootloaderAPI.c
+++ b/Bootloaders/MassStorage/BootloaderAPI.c
@@ -35,8 +35,20 @@
 
 #include "BootloaderAPI.h"
 
+static bool IsPageAddressValid(const uint32_t Address)
+{
+	/* Determine if the given page address is correctly aligned to the
+	   start of a flash page. */
+	bool PageAddressIsAligned = !(Address & (SPM_PAGESIZE - 1));
+
+	return (Address < BOOT_START_ADDR) && PageAddressIsAligned;
+}
+
 void BootloaderAPI_ErasePage(const uint32_t Address)
 {
+	if (! IsPageAddressValid(Address))
+		return;
+
 	ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
 	{
 		boot_page_erase_safe(Address);
@@ -47,6 +59,9 @@ void BootloaderAPI_ErasePage(const uint32_t Address)
 
 void BootloaderAPI_WritePage(const uint32_t Address)
 {
+	if (! IsPageAddressValid(Address))
+		return;
+
 	ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
 	{
 		boot_page_write_safe(Address);
diff --git a/Bootloaders/Printer/BootloaderAPI.c b/Bootloaders/Printer/BootloaderAPI.c
index 5e8083ed3..c1e76d3bd 100644
--- a/Bootloaders/Printer/BootloaderAPI.c
+++ b/Bootloaders/Printer/BootloaderAPI.c
@@ -35,8 +35,20 @@
 
 #include "BootloaderAPI.h"
 
+static bool IsPageAddressValid(const uint32_t Address)
+{
+	/* Determine if the given page address is correctly aligned to the
+	   start of a flash page. */
+	bool PageAddressIsAligned = !(Address & (SPM_PAGESIZE - 1));
+
+	return (Address < BOOT_START_ADDR) && PageAddressIsAligned;
+}
+
 void BootloaderAPI_ErasePage(const uint32_t Address)
 {
+	if (! IsPageAddressValid(Address))
+		return;
+
 	ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
 	{
 		boot_page_erase_safe(Address);
@@ -47,6 +59,9 @@ void BootloaderAPI_ErasePage(const uint32_t Address)
 
 void BootloaderAPI_WritePage(const uint32_t Address)
 {
+	if (! IsPageAddressValid(Address))
+		return;
+
 	ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
 	{
 		boot_page_write_safe(Address);
diff --git a/LUFA/DoxygenPages/ChangeLog.txt b/LUFA/DoxygenPages/ChangeLog.txt
index 8f299f7ea..147cacc36 100644
--- a/LUFA/DoxygenPages/ChangeLog.txt
+++ b/LUFA/DoxygenPages/ChangeLog.txt
@@ -14,6 +14,7 @@
   *     character after a successful write (thanks to NicoHood)
   *  - Library Applications:
   *   - Fixed bootloaders not disabling global interrupts during erase and write operations (thanks to Zoltan)
+  *   - Fixed bootloaders accepting flash writes to the bootloader region (thanks to NicoHood)
   *
   *  \section Sec_ChangeLog170418 Version 170418
   *  <b>New:</b>
-- 
GitLab