[PATCH 3/6] Make create_branch() return errors if the branch target is too large

Michael Ellerman michael at ellerman.id.au
Thu May 29 16:20:57 EST 2008


If you pass a target value to create_branch() which is more than 32MB - 4,
or - 32MB away from the branch site, then it's impossible to create an
immediate branch. The current code doesn't check, which will lead to us
creating a branch to somewhere else - which is bad.

For code that cares to check we return 0, which is easy to check for, and
for code that doesn't at least we'll be creating an illegal instruction,
rather than a branch to some random address.

Signed-off-by: Michael Ellerman <michael at ellerman.id.au>
---
 arch/powerpc/lib/code-patching.c |   10 ++++++++--
 1 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
index 1391981..2905c51 100644
--- a/arch/powerpc/lib/code-patching.c
+++ b/arch/powerpc/lib/code-patching.c
@@ -27,12 +27,18 @@ void patch_branch(unsigned long addr, unsigned long target, int flags)
 unsigned int create_branch(unsigned long addr, unsigned long target, int flags)
 {
 	unsigned int instruction;
+	long offset;
 
+	offset = target;
 	if (! (flags & BRANCH_ABSOLUTE))
-		target = target - addr;
+		offset = offset - addr;
+
+	/* Check we can represent the target in the instruction format */
+	if (offset < -0x2000000 || offset > 0x1fffffc || offset & 0x3)
+		return 0;
 
 	/* Mask out the flags and target, so they don't step on each other. */
-	instruction = 0x48000000 | (flags & 0x3) | (target & 0x03FFFFFC);
+	instruction = 0x48000000 | (flags & 0x3) | (offset & 0x03FFFFFC);
 
 	return instruction;
 }
-- 
1.5.5




More information about the Linuxppc-dev mailing list