Skip to contentSkip to conversation

Fix off-by-one in range_is_memory

PATCH Applied David Brazdil 3 participants 6 messages Jul 28, 2021 – Aug 20, 2021

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

cover Fix off-by-one in range_is_memory

Hi, here is an off-by-one bug fix and a very minor improvement for the range_is_memory function in hyp.

David Brazdil (2):
KVM: arm64: Fix off-by-one in range_is_memory
KVM: arm64: Minor optimization of range_is_memory

 arch/arm64/kvm/hyp/nvhe/mem_protect.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)
Signature · 1 line
2.32.0.432.gabb21c7263-goog
#1 lore raw

PATCH 1/2 KVM: arm64: Fix off-by-one in range_is_memory

Hyp checks whether an address range only covers RAM by checking the start/endpoints against a list of memblock_region structs. However, the endpoint here is exclusive but internally is treated as inclusive. Fix the off-by-one error that caused valid address ranges to be rejected.

Cc Quentin Perret <[email protected]>
Fixes 90134ac9cabb6 ("KVM: arm64: Protect the .hyp sections from the host")
---
 arch/arm64/kvm/hyp/nvhe/mem_protect.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm64/kvm/hyp/nvhe/mem_protect.c +1 -1
index d938ce95d3bd..a6ce991b1467 100644
@@ -193,7 +193,7 @@ static bool range_is_memory(u64 start, u64 end)
 {
 	struct kvm_mem_range r1, r2;
 
-	if (!find_mem_range(start, &r1) || !find_mem_range(end, &r2))
+	if (!find_mem_range(start, &r1) || !find_mem_range(end - 1, &r2))
 		return false;
 	if (r1.start != r2.start)
 		return false;
Signature · 6 lines
2.32.0.432.gabb21c7263-goog

_______________________________________________
kvmarm mailing list
[email protected]
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Reviewed-by on v1 1/2
#2 lore raw

Re: [PATCH 1/2] KVM: arm64: Fix off-by-one in range_is_memory

Quoted 18 lines · David Brazdil

Hyp checks whether an address range only covers RAM by checking the start/endpoints against a list of memblock_region structs. However, the endpoint here is exclusive but internally is treated as inclusive. Fix the off-by-one error that caused valid address ranges to be rejected.

Cc Quentin Perret <[email protected]>
Fixes 90134ac9cabb6 ("KVM: arm64: Protect the .hyp sections from the host")
---
 arch/arm64/kvm/hyp/nvhe/mem_protect.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm64/kvm/hyp/nvhe/mem_protect.c +0 -0
index d938ce95d3bd..a6ce991b1467 100644

arch/arm64/kvm/hyp/nvhe/mem_protect.c static bool range_is_memory(u64 start, u64 end) · line 199

Quoted 8 lines
arch/arm64/kvm/hyp/nvhe/mem_protect.c +1 -1
@@ -193,7 +193,7 @@ static bool range_is_memory(u64 start, u64 end)
 {
 	struct kvm_mem_range r1, r2;
 
-	if (!find_mem_range(start, &r1) || !find_mem_range(end, &r2))
+	if (!find_mem_range(start, &r1) || !find_mem_range(end - 1, &r2))
 		return false;
 	if (r1.start != r2.start)
 		return false;

Looks good to me:

Thanks,
Quentin
_______________________________________________
kvmarm mailing list
[email protected]
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

#3 lore raw

PATCH 2/2 KVM: arm64: Minor optimization of range_is_memory

In reply to David Brazdil

Currently range_is_memory finds the corresponding struct memblock_region for both the lower and upper bounds of the given address range with two rounds of binary search, and then checks that the two memblocks are the same. Simplify this by only doing binary search on the lower bound and then checking that the upper bound is in the same memblock.

---
 arch/arm64/kvm/hyp/nvhe/mem_protect.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)
arch/arm64/kvm/hyp/nvhe/mem_protect.c +8 -3
index a6ce991b1467..37d73af69634 100644
@@ -189,13 +189,18 @@ static bool find_mem_range(phys_addr_t addr, struct kvm_mem_range *range)
 	return false;
 }
 
+static bool is_in_mem_range(phys_addr_t addr, struct kvm_mem_range *range)
+{
+	return range->start <= addr && addr < range->end;
+}
+
 static bool range_is_memory(u64 start, u64 end)
 {
-	struct kvm_mem_range r1, r2;
+	struct kvm_mem_range r;
 
-	if (!find_mem_range(start, &r1) || !find_mem_range(end - 1, &r2))
+	if (!find_mem_range(start, &r))
 		return false;
-	if (r1.start != r2.start)
+	if (!is_in_mem_range(end - 1, &r))
 		return false;
 
 	return true;
Signature · 6 lines
2.32.0.432.gabb21c7263-goog

_______________________________________________
kvmarm mailing list
[email protected]
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Reviewed-by on v1 2/2
#4 lore raw

Re: [PATCH 2/2] KVM: arm64: Minor optimization of range_is_memory

Quoted 16 lines · David Brazdil

Currently range_is_memory finds the corresponding struct memblock_region for both the lower and upper bounds of the given address range with two rounds of binary search, and then checks that the two memblocks are the same. Simplify this by only doing binary search on the lower bound and then checking that the upper bound is in the same memblock.

---
 arch/arm64/kvm/hyp/nvhe/mem_protect.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)
arch/arm64/kvm/hyp/nvhe/mem_protect.c +0 -0
index a6ce991b1467..37d73af69634 100644

arch/arm64/kvm/hyp/nvhe/mem_protect.c static bool find_mem_range(phys_addr_t addr, struct kvm_mem_range *range) · line 193

Quoted 5 lines
arch/arm64/kvm/hyp/nvhe/mem_protect.c +2 -0
@@ -189,13 +189,18 @@ static bool find_mem_range(phys_addr_t addr, struct kvm_mem_range *range)
 	return false;
 }
 
+static bool is_in_mem_range(phys_addr_t addr, struct kvm_mem_range *range)
+{

Nit: addr@ could be u64 for consistency -- struct kvm_mem_range holds IPAs in general.

Quoted 6 lines
arch/arm64/kvm/hyp/nvhe/mem_protect.c +3 -1
+	return range->start <= addr && addr < range->end;
+}
+
 static bool range_is_memory(u64 start, u64 end)
 {
-	struct kvm_mem_range r1, r2;

arch/arm64/kvm/hyp/nvhe/mem_protect.c static bool find_mem_range(phys_addr_t addr, struct kvm_mem_range *range) · line 206

Quoted 10 lines
arch/arm64/kvm/hyp/nvhe/mem_protect.c +3 -2
+	struct kvm_mem_range r;
 
-	if (!find_mem_range(start, &r1) || !find_mem_range(end - 1, &r2))
+	if (!find_mem_range(start, &r))
 		return false;
-	if (r1.start != r2.start)
+	if (!is_in_mem_range(end - 1, &r))
 		return false;
 
 	return true;

Nit: maybe drop the second if and simplify to:

	return is_in_mem_range(end - 1, &r);

With that:

Thanks,
Quentin
_______________________________________________
kvmarm mailing list
[email protected]
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

maintainer Applied
#5 lore raw

Re: (subset) [PATCH 0/2] Fix off-by-one in range_is_memory

In reply to David Brazdil
Quoted 8 lines · David Brazdil

the range_is_memory function in hyp.

David Brazdil (2):
KVM: arm64: Fix off-by-one in range_is_memory
KVM: arm64: Minor optimization of range_is_memory

 arch/arm64/kvm/hyp/nvhe/mem_protect.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

Applied to kvm-arm64/mmu/el2-tracking, thanks!

[2/2] KVM: arm64: Minor optimization of range_is_memory

      commit: 14ecf075fe5be01860927fdf3aa11d7b18023ab2

Cheers,

	M.
Signature · 7 lines
Without deviation from the norm, progress is not possible.


_______________________________________________
kvmarm mailing list
[email protected]
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm