diff mbox

[U-Boot] memmove_wd: copy chunk down from big address if parameter to is larger than from

Message ID 1418206853-29337-1-git-send-email-sonic.adi@gmail.com
State Accepted
Delegated to: Tom Rini
Headers show

Commit Message

Sonic Zhang Dec. 10, 2014, 10:20 a.m. UTC
From: Sonic Zhang <sonic.zhang@analog.com>

When watchdog is enabled, memmove_wd() always copy chunk up from small address.
This damanges overlapped memory data if destination address is smaller than
source address.

Signed-off-by: Sonic Zhang <sonic.zhang@analog.com>
---

 common/image.c |   14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

Comments

Simon Glass Dec. 15, 2014, 9:22 p.m. UTC | #1
On 10 December 2014 at 03:20, Sonic Zhang <sonic.adi@gmail.com> wrote:
> From: Sonic Zhang <sonic.zhang@analog.com>
>
> When watchdog is enabled, memmove_wd() always copy chunk up from small address.
> This damanges overlapped memory data if destination address is smaller than
> source address.
>
> Signed-off-by: Sonic Zhang <sonic.zhang@analog.com>
> ---
>
>  common/image.c |   14 ++++++++++++--
>  1 file changed, 12 insertions(+), 2 deletions(-)

Acked-by: Simon Glass <sjg@chromium.org>
Tom Rini Jan. 7, 2015, 3:15 p.m. UTC | #2
On Wed, Dec 10, 2014 at 06:20:53PM +0800, Sonic Zhang wrote:

> From: Sonic Zhang <sonic.zhang@analog.com>
> 
> When watchdog is enabled, memmove_wd() always copy chunk up from small address.
> This damanges overlapped memory data if destination address is smaller than
> source address.
> 
> Signed-off-by: Sonic Zhang <sonic.zhang@analog.com>
> Acked-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!
diff mbox

Patch

diff --git a/common/image.c b/common/image.c
index b75a5ce..e691a51 100644
--- a/common/image.c
+++ b/common/image.c
@@ -485,12 +485,22 @@  void memmove_wd(void *to, void *from, size_t len, ulong chunksz)
 		return;
 
 #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
+	if (to > from) {
+		from += len;
+		to += len;
+	}
 	while (len > 0) {
 		size_t tail = (len > chunksz) ? chunksz : len;
 		WATCHDOG_RESET();
+		if (to > from) {
+			to -= tail;
+			from -= tail;
+		}
 		memmove(to, from, tail);
-		to += tail;
-		from += tail;
+		if (to < from) {
+			to += tail;
+			from += tail;
+		}
 		len -= tail;
 	}
 #else	/* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */