[PATCH] Simple NX lowmem mappings

Nicolas Pitre nico at fluxnic.net
Thu Oct 24 13:31:11 EDT 2013


On Thu, 24 Oct 2013, Russell King - ARM Linux wrote:

> This patch has similar functionality to Laura's patch set earlier this
> month, except I've just done the basic change - we don't increase the
> size of the kernel for this, so there should be no kernel size related
> problems with this.  We mark sections which do not overlap any kernel
> text as non-executable.  
> 
> 8<====
> From: Russell King <rmk+kernel at arm.linux.org.uk>
> ARM: Implement basic NX support for kernel lowmem mappings
> 
> Add basic NX support for kernel lowmem mappings.  We mark any section
> which does not overlap kernel text as non-executable, preventing it
> from being used to write code and then execute directly from there.
> 
> This does not change the alignment of the sections, so the kernel
> image doesn't grow significantly via this change, so we can do this
> without needing a config option.
> 
> Signed-off-by: Russell King <rmk+kernel at arm.linux.org.uk>

[...]

> @@ -1294,6 +1309,8 @@ static void __init kmap_init(void)
>  static void __init map_lowmem(void)
>  {
>  	struct memblock_region *reg;
> +	unsigned long kernel_x_start = round_down(__pa(_stext), SECTION_SIZE);
> +	unsigned long kernel_x_end = round_up(__pa(__init_end), SECTION_SIZE);

Maybe a worthwhile config option could allow for the above to be rounded 
to PAGE_SIZE instead.  That would require a second level page table for 
the kernel text edges with increased TLB pressure but also with tighter 
protection.  That would also allow removing executability of __init 
memory after it is discarded.

>  	/* Map all the lowmem memory banks. */
>  	for_each_memblock(memory, reg) {
> @@ -1306,12 +1323,40 @@ static void __init map_lowmem(void)
>  		if (start >= end)
>  			break;
>  
> -		map.pfn = __phys_to_pfn(start);
> -		map.virtual = __phys_to_virt(start);
> -		map.length = end - start;
> -		map.type = MT_MEMORY;
> +		if (end < kernel_x_start || start >= kernel_x_end) {

Isn't it supposed to be "end <= kernel_x_start" ?

> +			map.pfn = __phys_to_pfn(start);
> +			map.virtual = __phys_to_virt(start);
> +			map.length = end - start;
> +			map.type = MT_MEMORY;

Isn't it supposed to be MT_MEMORY_NX here?

> -		create_mapping(&map);
> +			create_mapping(&map);
> +		} else {
> +			/* This better cover the entire kernel */
> +			if (start < kernel_x_start) {
> +				map.pfn = __phys_to_pfn(start);
> +				map.virtual = __phys_to_virt(start);
> +				map.length = kernel_x_start - start;
> +				map.type = MT_MEMORY_NX;
> +
> +				create_mapping(&map);
> +			}
> +
> +			map.pfn = __phys_to_pfn(kernel_x_start);
> +			map.virtual = __phys_to_virt(kernel_x_start);
> +			map.length = kernel_x_end - kernel_x_start;
> +			map.type = MT_MEMORY;
> +
> +			create_mapping(&map);
> +
> +			if (kernel_x_end < end) {
> +				map.pfn = __phys_to_pfn(kernel_x_end);
> +				map.virtual = __phys_to_virt(kernel_x_end);
> +				map.length = end - kernel_x_end;
> +				map.type = MT_MEMORY_NX;
> +
> +				create_mapping(&map);
> +			}
> +		}
>  	}
>  }
>  
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 



More information about the linux-arm-kernel mailing list