diff mbox series

[3/4] arm64/kprobes: set VM_FLUSH_RESET_PERMS on kprobe instruction pages

Message ID 20190523102256.29168-4-ard.biesheuvel@arm.com (mailing list archive)
State New, archived
Headers show
Series arm64: wire up VM_FLUSH_RESET_PERMS | expand

Commit Message

Ard Biesheuvel May 23, 2019, 10:22 a.m. UTC
In order to avoid transient inconsistencies where freed code pages
are remapped writable while stale TLB entries still exist on other
cores, mark the kprobes text pages with the VM_FLUSH_RESET_PERMS
attribute. This instructs the core vmalloc code not to defer the
TLB flush when this region is unmapped and returned to the page
allocator.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@arm.com>
---
 arch/arm64/kernel/probes/kprobes.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

Comments

Anshuman Khandual May 28, 2019, 8:20 a.m. UTC | #1
On 05/23/2019 03:52 PM, Ard Biesheuvel wrote:
> In order to avoid transient inconsistencies where freed code pages
> are remapped writable while stale TLB entries still exist on other
> cores, mark the kprobes text pages with the VM_FLUSH_RESET_PERMS
> attribute. This instructs the core vmalloc code not to defer the
> TLB flush when this region is unmapped and returned to the page
> allocator.

Makes sense.

> 
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@arm.com>
> ---
>  arch/arm64/kernel/probes/kprobes.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c
> index 2509fcb6d404..036cfbf9682a 100644
> --- a/arch/arm64/kernel/probes/kprobes.c
> +++ b/arch/arm64/kernel/probes/kprobes.c
> @@ -131,8 +131,10 @@ void *alloc_insn_page(void)
>  	void *page;
>  
>  	page = vmalloc_exec(PAGE_SIZE);
> -	if (page)
> +	if (page) {
>  		set_memory_ro((unsigned long)page, 1);
> +		set_vm_flush_reset_perms(page);
> +	}

Looks good. It seems there might be more users who would like to set
VM_FLUSH_RESET_PERMS right after their allocation for the same reason.
Hence would not it help to have a variant like vmalloc_exec_reset() or
such which will tag vm_struct->flags with VM_FLUSH_RESET_PERMS right
after it's allocation without requiring the caller to do the same.
Ard Biesheuvel May 28, 2019, 8:23 a.m. UTC | #2
On 5/28/19 10:20 AM, Anshuman Khandual wrote:
> 
> 
> On 05/23/2019 03:52 PM, Ard Biesheuvel wrote:
>> In order to avoid transient inconsistencies where freed code pages
>> are remapped writable while stale TLB entries still exist on other
>> cores, mark the kprobes text pages with the VM_FLUSH_RESET_PERMS
>> attribute. This instructs the core vmalloc code not to defer the
>> TLB flush when this region is unmapped and returned to the page
>> allocator.
> 
> Makes sense.
> 
>>
>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@arm.com>
>> ---
>>   arch/arm64/kernel/probes/kprobes.c | 4 +++-
>>   1 file changed, 3 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c
>> index 2509fcb6d404..036cfbf9682a 100644
>> --- a/arch/arm64/kernel/probes/kprobes.c
>> +++ b/arch/arm64/kernel/probes/kprobes.c
>> @@ -131,8 +131,10 @@ void *alloc_insn_page(void)
>>   	void *page;
>>   
>>   	page = vmalloc_exec(PAGE_SIZE);
>> -	if (page)
>> +	if (page) {
>>   		set_memory_ro((unsigned long)page, 1);
>> +		set_vm_flush_reset_perms(page);
>> +	}
> 
> Looks good. It seems there might be more users who would like to set
> VM_FLUSH_RESET_PERMS right after their allocation for the same reason.
> Hence would not it help to have a variant like vmalloc_exec_reset() or
> such which will tag vm_struct->flags with VM_FLUSH_RESET_PERMS right
> after it's allocation without requiring the caller to do the same.
> 

If there is a sufficient number of similar users, then of course, it 
makes sense to factor this out. However, the kprobes code is slightly 
unusual in the sense that it allocates memory and immediately remaps it 
read-only, and relies on code patching to populate this allocation. I am 
not expecting to see this pattern in other places.
diff mbox series

Patch

diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c
index 2509fcb6d404..036cfbf9682a 100644
--- a/arch/arm64/kernel/probes/kprobes.c
+++ b/arch/arm64/kernel/probes/kprobes.c
@@ -131,8 +131,10 @@  void *alloc_insn_page(void)
 	void *page;
 
 	page = vmalloc_exec(PAGE_SIZE);
-	if (page)
+	if (page) {
 		set_memory_ro((unsigned long)page, 1);
+		set_vm_flush_reset_perms(page);
+	}
 
 	return page;
 }