diff mbox

[v2,1/2] arm64: mm: Mark .rodata as RO

Message ID 1455727274-16328-2-git-send-email-jeremy.linton@arm.com (mailing list archive)
State New, archived
Headers show

Commit Message

Jeremy Linton Feb. 17, 2016, 4:41 p.m. UTC
Currently the .rodata section is actually still executable when DEBUG_RODATA
is enabled. This changes that so the .rodata is actually read only, no execute.

Signed-off-by: Jeremy Linton <jeremy.linton@arm.com>
---
 arch/arm64/kernel/vmlinux.lds.S |  5 +++--
 arch/arm64/mm/mmu.c             | 17 +++++++++++++----
 2 files changed, 16 insertions(+), 6 deletions(-)

Comments

Ard Biesheuvel Feb. 17, 2016, 4:46 p.m. UTC | #1
On 17 February 2016 at 17:41, Jeremy Linton <jeremy.linton@arm.com> wrote:
> Currently the .rodata section is actually still executable when DEBUG_RODATA
> is enabled. This changes that so the .rodata is actually read only, no execute.
>
> Signed-off-by: Jeremy Linton <jeremy.linton@arm.com>
> ---
>  arch/arm64/kernel/vmlinux.lds.S |  5 +++--
>  arch/arm64/mm/mmu.c             | 17 +++++++++++++----
>  2 files changed, 16 insertions(+), 6 deletions(-)
>
> diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
> index 8f4fc2c..9208f53 100644
> --- a/arch/arm64/kernel/vmlinux.lds.S
> +++ b/arch/arm64/kernel/vmlinux.lds.S
> @@ -114,8 +114,9 @@ SECTIONS
>                 *(.got)                 /* Global offset table          */
>         }
>
> -       RO_DATA(PAGE_SIZE)
> -       EXCEPTION_TABLE(8)
> +       ALIGN_DEBUG_RO_MIN(0)
> +       RO_DATA(PAGE_SIZE)              /* everything from this point to */
> +       EXCEPTION_TABLE(8)              /* _etext will be marked RO NX   */
>         NOTES
>
>         ALIGN_DEBUG_RO_MIN(PAGE_SIZE)
> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
> index ab69a99..9aa5201 100644
> --- a/arch/arm64/mm/mmu.c
> +++ b/arch/arm64/mm/mmu.c
> @@ -453,10 +453,18 @@ static void __init map_mem(pgd_t *pgd)
>  #ifdef CONFIG_DEBUG_RODATA
>  void mark_rodata_ro(void)
>  {
> -       create_mapping_late(__pa(_stext), (unsigned long)_stext,
> -                               (unsigned long)_etext - (unsigned long)_stext,
> -                               PAGE_KERNEL_ROX);
> +       unsigned long section_size;
>
> +       section_size = (unsigned long)__start_rodata - (unsigned long)_stext;
> +       create_mapping_late(__pa(_stext), (unsigned long)_stext,
> +                           section_size, PAGE_KERNEL_ROX);
> +       /*
> +        * mark .rodata as read only. Use _etext rather than __end_rodata to
> +        * cover NOTES and EXCEPTION_TABLE.
> +        */
> +       section_size = (unsigned long)_etext - (unsigned long)__start_rodata;
> +       create_mapping_late(__pa(__start_rodata), (unsigned long)__start_rodata,
> +                           section_size, PAGE_KERNEL_RO);
>  }
>  #endif
>
> @@ -486,7 +494,8 @@ static void __init map_kernel_chunk(pgd_t *pgd, void *va_start, void *va_end,
>  static void __init map_kernel(pgd_t *pgd)
>  {
>
> -       map_kernel_chunk(pgd, _stext, _etext, PAGE_KERNEL_EXEC);
> +       map_kernel_chunk(pgd, _stext, __start_rodata, PAGE_KERNEL_EXEC);
> +       map_kernel_chunk(pgd, __start_rodata, _etext, PAGE_KERNEL_EXEC);

Couldn't we map this non-exec from the start?

>         map_kernel_chunk(pgd, __init_begin, __init_end, PAGE_KERNEL_EXEC);
>         map_kernel_chunk(pgd, _data, _end, PAGE_KERNEL);
>
> --
> 2.4.3
>
Jeremy Linton Feb. 17, 2016, 4:54 p.m. UTC | #2
On 02/17/2016 10:46 AM, Ard Biesheuvel wrote:
> On 17 February 2016 at 17:41, Jeremy Linton <jeremy.linton@arm.com> wrote:
>> Currently the .rodata section is actually still executable when DEBUG_RODATA
>> is enabled. This changes that so the .rodata is actually read only, no execute.
>>
(trimming)
>>
>> -       map_kernel_chunk(pgd, _stext, _etext, PAGE_KERNEL_EXEC);
>> +       map_kernel_chunk(pgd, _stext, __start_rodata, PAGE_KERNEL_EXEC);
>> +       map_kernel_chunk(pgd, __start_rodata, _etext, PAGE_KERNEL_EXEC);
>
> Couldn't we map this non-exec from the start?

Probably, Mark suggested that, but Kees seemed to have reasons not to. 
Either way, my opinion is that for that change to make sense we also 
need to always enable the functionality turned on by DEBUG_RODATA.

>
>>          map_kernel_chunk(pgd, __init_begin, __init_end, PAGE_KERNEL_EXEC);
>>          map_kernel_chunk(pgd, _data, _end, PAGE_KERNEL);
>>
>> --
>> 2.4.3
>>
>
Ard Biesheuvel Feb. 17, 2016, 4:55 p.m. UTC | #3
On 17 February 2016 at 17:54, Jeremy Linton <jeremy.linton@arm.com> wrote:
> On 02/17/2016 10:46 AM, Ard Biesheuvel wrote:
>>
>> On 17 February 2016 at 17:41, Jeremy Linton <jeremy.linton@arm.com> wrote:
>>>
>>> Currently the .rodata section is actually still executable when
>>> DEBUG_RODATA
>>> is enabled. This changes that so the .rodata is actually read only, no
>>> execute.
>>>
> (trimming)
>>>
>>>
>>> -       map_kernel_chunk(pgd, _stext, _etext, PAGE_KERNEL_EXEC);
>>> +       map_kernel_chunk(pgd, _stext, __start_rodata, PAGE_KERNEL_EXEC);
>>> +       map_kernel_chunk(pgd, __start_rodata, _etext, PAGE_KERNEL_EXEC);
>>
>>
>> Couldn't we map this non-exec from the start?
>
>
> Probably, Mark suggested that, but Kees seemed to have reasons not to.
> Either way, my opinion is that for that change to make sense we also need to
> always enable the functionality turned on by DEBUG_RODATA.
>

Actually, I think that was about mapping read-only, not non-exec. For
text patching and Kees's __ro_after_init stuff, the region would need
to be writable early on. But I don't think there is a reason to make
it executable.
Mark Rutland Feb. 17, 2016, 5:02 p.m. UTC | #4
On Wed, Feb 17, 2016 at 05:55:57PM +0100, Ard Biesheuvel wrote:
> On 17 February 2016 at 17:54, Jeremy Linton <jeremy.linton@arm.com> wrote:
> > On 02/17/2016 10:46 AM, Ard Biesheuvel wrote:
> >>
> >> On 17 February 2016 at 17:41, Jeremy Linton <jeremy.linton@arm.com> wrote:
> >>>
> >>> Currently the .rodata section is actually still executable when
> >>> DEBUG_RODATA
> >>> is enabled. This changes that so the .rodata is actually read only, no
> >>> execute.
> >>>
> > (trimming)
> >>>
> >>>
> >>> -       map_kernel_chunk(pgd, _stext, _etext, PAGE_KERNEL_EXEC);
> >>> +       map_kernel_chunk(pgd, _stext, __start_rodata, PAGE_KERNEL_EXEC);
> >>> +       map_kernel_chunk(pgd, __start_rodata, _etext, PAGE_KERNEL_EXEC);
> >>
> >>
> >> Couldn't we map this non-exec from the start?
> >
> >
> > Probably, Mark suggested that, but Kees seemed to have reasons not to.
> > Either way, my opinion is that for that change to make sense we also need to
> > always enable the functionality turned on by DEBUG_RODATA.
> >
> 
> Actually, I think that was about mapping read-only, not non-exec. For
> text patching and Kees's __ro_after_init stuff, the region would need
> to be writable early on. But I don't think there is a reason to make
> it executable.

Yup, we should be able to make it PAGE_KERNEL here, even if we can't
make it PAGE_KERNEL_RO.

Mark.
diff mbox

Patch

diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
index 8f4fc2c..9208f53 100644
--- a/arch/arm64/kernel/vmlinux.lds.S
+++ b/arch/arm64/kernel/vmlinux.lds.S
@@ -114,8 +114,9 @@  SECTIONS
 		*(.got)			/* Global offset table		*/
 	}
 
-	RO_DATA(PAGE_SIZE)
-	EXCEPTION_TABLE(8)
+	ALIGN_DEBUG_RO_MIN(0)
+	RO_DATA(PAGE_SIZE)		/* everything from this point to */
+	EXCEPTION_TABLE(8)		/* _etext will be marked RO NX   */
 	NOTES
 
 	ALIGN_DEBUG_RO_MIN(PAGE_SIZE)
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index ab69a99..9aa5201 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -453,10 +453,18 @@  static void __init map_mem(pgd_t *pgd)
 #ifdef CONFIG_DEBUG_RODATA
 void mark_rodata_ro(void)
 {
-	create_mapping_late(__pa(_stext), (unsigned long)_stext,
-				(unsigned long)_etext - (unsigned long)_stext,
-				PAGE_KERNEL_ROX);
+	unsigned long section_size;
 
+	section_size = (unsigned long)__start_rodata - (unsigned long)_stext;
+	create_mapping_late(__pa(_stext), (unsigned long)_stext,
+			    section_size, PAGE_KERNEL_ROX);
+	/*
+	 * mark .rodata as read only. Use _etext rather than __end_rodata to
+	 * cover NOTES and EXCEPTION_TABLE.
+	 */
+	section_size = (unsigned long)_etext - (unsigned long)__start_rodata;
+	create_mapping_late(__pa(__start_rodata), (unsigned long)__start_rodata,
+			    section_size, PAGE_KERNEL_RO);
 }
 #endif
 
@@ -486,7 +494,8 @@  static void __init map_kernel_chunk(pgd_t *pgd, void *va_start, void *va_end,
 static void __init map_kernel(pgd_t *pgd)
 {
 
-	map_kernel_chunk(pgd, _stext, _etext, PAGE_KERNEL_EXEC);
+	map_kernel_chunk(pgd, _stext, __start_rodata, PAGE_KERNEL_EXEC);
+	map_kernel_chunk(pgd, __start_rodata, _etext, PAGE_KERNEL_EXEC);
 	map_kernel_chunk(pgd, __init_begin, __init_end, PAGE_KERNEL_EXEC);
 	map_kernel_chunk(pgd, _data, _end, PAGE_KERNEL);