All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] arm64: fix address fault during mapping fdt region
@ 2016-08-01  9:42 ` zijun_hu
  0 siblings, 0 replies; 22+ messages in thread
From: zijun_hu @ 2016-08-01  9:42 UTC (permalink / raw)
  To: catalin.marinas, will.deacon, linux-arm-kernel, ard.biesheuvel,
	mark.rutland, labbott, suzuki.poulose, jeremy.linton, tj
  Cc: linux-kernel, stable, akpm, zijun_hu

>From 07b9216ec3494515e7a6c41e0333eb8782427db3 Mon Sep 17 00:00:00 2001
From: zijun_hu <zijun_hu@htc.com>
Date: Mon, 1 Aug 2016 17:04:59 +0800
Subject: [PATCH] arm64: fix address fault during mapping fdt region

fdt_check_header() accesses other fileds of fdt header but
the first 8 bytes such as version; so accessing unmapped
address fault happens if fdt region locates below align
boundary nearly during mapping fdt region, or expressed as
(offset + sizeof(struct fdt_header)) > SWAPPER_BLOCK_SIZE

fdt header size at least is mapped in order to avoid the issue

Signed-off-by: zijun_hu <zijun_hu@htc.com>
---
 arch/arm64/mm/mmu.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 0f85a46..0d72b71 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -744,6 +744,7 @@ void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot)
 	const u64 dt_virt_base = __fix_to_virt(FIX_FDT);
 	int offset;
 	void *dt_virt;
+	int dt_header_map_size;
 
 	/*
 	 * Check whether the physical FDT address is set and meets the minimum
@@ -774,9 +775,18 @@ void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot)
 	offset = dt_phys % SWAPPER_BLOCK_SIZE;
 	dt_virt = (void *)dt_virt_base + offset;
 
+	/*
+	 * fdt_check_header() maybe access any field of fdt header not
+	 * the first 8 bytes only, so map fdt header size at least for
+	 * checking fdt header without address fault more portably
+	 */
+	BUILD_BUG_ON(sizeof(struct fdt_header) > SWAPPER_BLOCK_SIZE);
+	dt_header_map_size = round_up(offset + sizeof(struct fdt_header),
+			SWAPPER_BLOCK_SIZE);
+
 	/* map the first chunk so we can read the size from the header */
 	create_mapping_noalloc(round_down(dt_phys, SWAPPER_BLOCK_SIZE),
-			dt_virt_base, SWAPPER_BLOCK_SIZE, prot);
+			dt_virt_base, dt_header_map_size, prot);
 
 	if (fdt_check_header(dt_virt) != 0)
 		return NULL;
@@ -785,7 +795,7 @@ void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot)
 	if (*size > MAX_FDT_SIZE)
 		return NULL;
 
-	if (offset + *size > SWAPPER_BLOCK_SIZE)
+	if (offset + *size > dt_header_map_size)
 		create_mapping_noalloc(round_down(dt_phys, SWAPPER_BLOCK_SIZE), dt_virt_base,
 			       round_up(offset + *size, SWAPPER_BLOCK_SIZE), prot);
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH] arm64: fix address fault during mapping fdt region
@ 2016-08-01  9:42 ` zijun_hu
  0 siblings, 0 replies; 22+ messages in thread
From: zijun_hu @ 2016-08-01  9:42 UTC (permalink / raw)
  To: linux-arm-kernel

>From 07b9216ec3494515e7a6c41e0333eb8782427db3 Mon Sep 17 00:00:00 2001
From: zijun_hu <zijun_hu@htc.com>
Date: Mon, 1 Aug 2016 17:04:59 +0800
Subject: [PATCH] arm64: fix address fault during mapping fdt region

fdt_check_header() accesses other fileds of fdt header but
the first 8 bytes such as version; so accessing unmapped
address fault happens if fdt region locates below align
boundary nearly during mapping fdt region, or expressed as
(offset + sizeof(struct fdt_header)) > SWAPPER_BLOCK_SIZE

fdt header size at least is mapped in order to avoid the issue

Signed-off-by: zijun_hu <zijun_hu@htc.com>
---
 arch/arm64/mm/mmu.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 0f85a46..0d72b71 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -744,6 +744,7 @@ void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot)
 	const u64 dt_virt_base = __fix_to_virt(FIX_FDT);
 	int offset;
 	void *dt_virt;
+	int dt_header_map_size;
 
 	/*
 	 * Check whether the physical FDT address is set and meets the minimum
@@ -774,9 +775,18 @@ void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot)
 	offset = dt_phys % SWAPPER_BLOCK_SIZE;
 	dt_virt = (void *)dt_virt_base + offset;
 
+	/*
+	 * fdt_check_header() maybe access any field of fdt header not
+	 * the first 8 bytes only, so map fdt header size at least for
+	 * checking fdt header without address fault more portably
+	 */
+	BUILD_BUG_ON(sizeof(struct fdt_header) > SWAPPER_BLOCK_SIZE);
+	dt_header_map_size = round_up(offset + sizeof(struct fdt_header),
+			SWAPPER_BLOCK_SIZE);
+
 	/* map the first chunk so we can read the size from the header */
 	create_mapping_noalloc(round_down(dt_phys, SWAPPER_BLOCK_SIZE),
-			dt_virt_base, SWAPPER_BLOCK_SIZE, prot);
+			dt_virt_base, dt_header_map_size, prot);
 
 	if (fdt_check_header(dt_virt) != 0)
 		return NULL;
@@ -785,7 +795,7 @@ void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot)
 	if (*size > MAX_FDT_SIZE)
 		return NULL;
 
-	if (offset + *size > SWAPPER_BLOCK_SIZE)
+	if (offset + *size > dt_header_map_size)
 		create_mapping_noalloc(round_down(dt_phys, SWAPPER_BLOCK_SIZE), dt_virt_base,
 			       round_up(offset + *size, SWAPPER_BLOCK_SIZE), prot);
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [PATCH] arm64: fix address fault during mapping fdt region
  2016-08-01  9:42 ` zijun_hu
  (?)
@ 2016-08-01  9:50   ` Ard Biesheuvel
  -1 siblings, 0 replies; 22+ messages in thread
From: Ard Biesheuvel @ 2016-08-01  9:50 UTC (permalink / raw)
  To: zijun_hu
  Cc: Catalin Marinas, Will Deacon, linux-arm-kernel, Mark Rutland,
	Laura Abbott, Suzuki K. Poulose, Jeremy Linton, tj, linux-kernel,
	stable, Andrew Morton, zijun_hu

On 1 August 2016 at 11:42, zijun_hu <zijun_hu@zoho.com> wrote:
> From 07b9216ec3494515e7a6c41e0333eb8782427db3 Mon Sep 17 00:00:00 2001
> From: zijun_hu <zijun_hu@htc.com>
> Date: Mon, 1 Aug 2016 17:04:59 +0800
> Subject: [PATCH] arm64: fix address fault during mapping fdt region
>
> fdt_check_header() accesses other fileds of fdt header but
> the first 8 bytes such as version; so accessing unmapped
> address fault happens if fdt region locates below align
> boundary nearly during mapping fdt region, or expressed as
> (offset + sizeof(struct fdt_header)) > SWAPPER_BLOCK_SIZE
>
> fdt header size at least is mapped in order to avoid the issue
>
> Signed-off-by: zijun_hu <zijun_hu@htc.com>
> ---
>  arch/arm64/mm/mmu.c | 14 ++++++++++++--
>  1 file changed, 12 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
> index 0f85a46..0d72b71 100644
> --- a/arch/arm64/mm/mmu.c
> +++ b/arch/arm64/mm/mmu.c
> @@ -744,6 +744,7 @@ void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot)
>         const u64 dt_virt_base = __fix_to_virt(FIX_FDT);
>         int offset;
>         void *dt_virt;
> +       int dt_header_map_size;
>
>         /*
>          * Check whether the physical FDT address is set and meets the minimum
> @@ -774,9 +775,18 @@ void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot)
>         offset = dt_phys % SWAPPER_BLOCK_SIZE;
>         dt_virt = (void *)dt_virt_base + offset;
>
> +       /*
> +        * fdt_check_header() maybe access any field of fdt header not
> +        * the first 8 bytes only, so map fdt header size at least for
> +        * checking fdt header without address fault more portably
> +        */
> +       BUILD_BUG_ON(sizeof(struct fdt_header) > SWAPPER_BLOCK_SIZE);
> +       dt_header_map_size = round_up(offset + sizeof(struct fdt_header),
> +                       SWAPPER_BLOCK_SIZE);
> +
>         /* map the first chunk so we can read the size from the header */
>         create_mapping_noalloc(round_down(dt_phys, SWAPPER_BLOCK_SIZE),
> -                       dt_virt_base, SWAPPER_BLOCK_SIZE, prot);
> +                       dt_virt_base, dt_header_map_size, prot);
>
>         if (fdt_check_header(dt_virt) != 0)
>                 return NULL;
> @@ -785,7 +795,7 @@ void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot)
>         if (*size > MAX_FDT_SIZE)
>                 return NULL;
>
> -       if (offset + *size > SWAPPER_BLOCK_SIZE)
> +       if (offset + *size > dt_header_map_size)
>                 create_mapping_noalloc(round_down(dt_phys, SWAPPER_BLOCK_SIZE), dt_virt_base,
>                                round_up(offset + *size, SWAPPER_BLOCK_SIZE), prot);
>

Couldn't we simply do this instead?

diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 0f85a46c3e18..e8d3b04a2b57 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -778,7 +778,7 @@ void *__init __fixmap_remap_fdt(phys_addr_t
dt_phys, int *size, pgprot_t prot)
        create_mapping_noalloc(round_down(dt_phys, SWAPPER_BLOCK_SIZE),
                        dt_virt_base, SWAPPER_BLOCK_SIZE, prot);

-       if (fdt_check_header(dt_virt) != 0)
+       if (fdt_magic(dt_virt) != FDT_MAGIC)
                return NULL;

        *size = fdt_totalsize(dt_virt);

We are simply looking for a size field. The OF code will call
fdt_check_header() again, so anything that is checked there in
addition to the magic field will still be checked.

-- 
Ard.

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [PATCH] arm64: fix address fault during mapping fdt region
@ 2016-08-01  9:50   ` Ard Biesheuvel
  0 siblings, 0 replies; 22+ messages in thread
From: Ard Biesheuvel @ 2016-08-01  9:50 UTC (permalink / raw)
  To: zijun_hu
  Cc: Catalin Marinas, Will Deacon, linux-arm-kernel, Mark Rutland,
	Laura Abbott, Suzuki K. Poulose, Jeremy Linton, tj, linux-kernel,
	stable, Andrew Morton, zijun_hu

On 1 August 2016 at 11:42, zijun_hu <zijun_hu@zoho.com> wrote:
> From 07b9216ec3494515e7a6c41e0333eb8782427db3 Mon Sep 17 00:00:00 2001
> From: zijun_hu <zijun_hu@htc.com>
> Date: Mon, 1 Aug 2016 17:04:59 +0800
> Subject: [PATCH] arm64: fix address fault during mapping fdt region
>
> fdt_check_header() accesses other fileds of fdt header but
> the first 8 bytes such as version; so accessing unmapped
> address fault happens if fdt region locates below align
> boundary nearly during mapping fdt region, or expressed as
> (offset + sizeof(struct fdt_header)) > SWAPPER_BLOCK_SIZE
>
> fdt header size at least is mapped in order to avoid the issue
>
> Signed-off-by: zijun_hu <zijun_hu@htc.com>
> ---
>  arch/arm64/mm/mmu.c | 14 ++++++++++++--
>  1 file changed, 12 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
> index 0f85a46..0d72b71 100644
> --- a/arch/arm64/mm/mmu.c
> +++ b/arch/arm64/mm/mmu.c
> @@ -744,6 +744,7 @@ void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot)
>         const u64 dt_virt_base = __fix_to_virt(FIX_FDT);
>         int offset;
>         void *dt_virt;
> +       int dt_header_map_size;
>
>         /*
>          * Check whether the physical FDT address is set and meets the minimum
> @@ -774,9 +775,18 @@ void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot)
>         offset = dt_phys % SWAPPER_BLOCK_SIZE;
>         dt_virt = (void *)dt_virt_base + offset;
>
> +       /*
> +        * fdt_check_header() maybe access any field of fdt header not
> +        * the first 8 bytes only, so map fdt header size at least for
> +        * checking fdt header without address fault more portably
> +        */
> +       BUILD_BUG_ON(sizeof(struct fdt_header) > SWAPPER_BLOCK_SIZE);
> +       dt_header_map_size = round_up(offset + sizeof(struct fdt_header),
> +                       SWAPPER_BLOCK_SIZE);
> +
>         /* map the first chunk so we can read the size from the header */
>         create_mapping_noalloc(round_down(dt_phys, SWAPPER_BLOCK_SIZE),
> -                       dt_virt_base, SWAPPER_BLOCK_SIZE, prot);
> +                       dt_virt_base, dt_header_map_size, prot);
>
>         if (fdt_check_header(dt_virt) != 0)
>                 return NULL;
> @@ -785,7 +795,7 @@ void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot)
>         if (*size > MAX_FDT_SIZE)
>                 return NULL;
>
> -       if (offset + *size > SWAPPER_BLOCK_SIZE)
> +       if (offset + *size > dt_header_map_size)
>                 create_mapping_noalloc(round_down(dt_phys, SWAPPER_BLOCK_SIZE), dt_virt_base,
>                                round_up(offset + *size, SWAPPER_BLOCK_SIZE), prot);
>

Couldn't we simply do this instead?

diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 0f85a46c3e18..e8d3b04a2b57 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -778,7 +778,7 @@ void *__init __fixmap_remap_fdt(phys_addr_t
dt_phys, int *size, pgprot_t prot)
        create_mapping_noalloc(round_down(dt_phys, SWAPPER_BLOCK_SIZE),
                        dt_virt_base, SWAPPER_BLOCK_SIZE, prot);

-       if (fdt_check_header(dt_virt) != 0)
+       if (fdt_magic(dt_virt) != FDT_MAGIC)
                return NULL;

        *size = fdt_totalsize(dt_virt);

We are simply looking for a size field. The OF code will call
fdt_check_header() again, so anything that is checked there in
addition to the magic field will still be checked.

-- 
Ard.

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH] arm64: fix address fault during mapping fdt region
@ 2016-08-01  9:50   ` Ard Biesheuvel
  0 siblings, 0 replies; 22+ messages in thread
From: Ard Biesheuvel @ 2016-08-01  9:50 UTC (permalink / raw)
  To: linux-arm-kernel

On 1 August 2016 at 11:42, zijun_hu <zijun_hu@zoho.com> wrote:
> From 07b9216ec3494515e7a6c41e0333eb8782427db3 Mon Sep 17 00:00:00 2001
> From: zijun_hu <zijun_hu@htc.com>
> Date: Mon, 1 Aug 2016 17:04:59 +0800
> Subject: [PATCH] arm64: fix address fault during mapping fdt region
>
> fdt_check_header() accesses other fileds of fdt header but
> the first 8 bytes such as version; so accessing unmapped
> address fault happens if fdt region locates below align
> boundary nearly during mapping fdt region, or expressed as
> (offset + sizeof(struct fdt_header)) > SWAPPER_BLOCK_SIZE
>
> fdt header size at least is mapped in order to avoid the issue
>
> Signed-off-by: zijun_hu <zijun_hu@htc.com>
> ---
>  arch/arm64/mm/mmu.c | 14 ++++++++++++--
>  1 file changed, 12 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
> index 0f85a46..0d72b71 100644
> --- a/arch/arm64/mm/mmu.c
> +++ b/arch/arm64/mm/mmu.c
> @@ -744,6 +744,7 @@ void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot)
>         const u64 dt_virt_base = __fix_to_virt(FIX_FDT);
>         int offset;
>         void *dt_virt;
> +       int dt_header_map_size;
>
>         /*
>          * Check whether the physical FDT address is set and meets the minimum
> @@ -774,9 +775,18 @@ void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot)
>         offset = dt_phys % SWAPPER_BLOCK_SIZE;
>         dt_virt = (void *)dt_virt_base + offset;
>
> +       /*
> +        * fdt_check_header() maybe access any field of fdt header not
> +        * the first 8 bytes only, so map fdt header size at least for
> +        * checking fdt header without address fault more portably
> +        */
> +       BUILD_BUG_ON(sizeof(struct fdt_header) > SWAPPER_BLOCK_SIZE);
> +       dt_header_map_size = round_up(offset + sizeof(struct fdt_header),
> +                       SWAPPER_BLOCK_SIZE);
> +
>         /* map the first chunk so we can read the size from the header */
>         create_mapping_noalloc(round_down(dt_phys, SWAPPER_BLOCK_SIZE),
> -                       dt_virt_base, SWAPPER_BLOCK_SIZE, prot);
> +                       dt_virt_base, dt_header_map_size, prot);
>
>         if (fdt_check_header(dt_virt) != 0)
>                 return NULL;
> @@ -785,7 +795,7 @@ void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot)
>         if (*size > MAX_FDT_SIZE)
>                 return NULL;
>
> -       if (offset + *size > SWAPPER_BLOCK_SIZE)
> +       if (offset + *size > dt_header_map_size)
>                 create_mapping_noalloc(round_down(dt_phys, SWAPPER_BLOCK_SIZE), dt_virt_base,
>                                round_up(offset + *size, SWAPPER_BLOCK_SIZE), prot);
>

Couldn't we simply do this instead?

diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 0f85a46c3e18..e8d3b04a2b57 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -778,7 +778,7 @@ void *__init __fixmap_remap_fdt(phys_addr_t
dt_phys, int *size, pgprot_t prot)
        create_mapping_noalloc(round_down(dt_phys, SWAPPER_BLOCK_SIZE),
                        dt_virt_base, SWAPPER_BLOCK_SIZE, prot);

-       if (fdt_check_header(dt_virt) != 0)
+       if (fdt_magic(dt_virt) != FDT_MAGIC)
                return NULL;

        *size = fdt_totalsize(dt_virt);

We are simply looking for a size field. The OF code will call
fdt_check_header() again, so anything that is checked there in
addition to the magic field will still be checked.

-- 
Ard.

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [PATCH] arm64: fix address fault during mapping fdt region
  2016-08-01  9:50   ` Ard Biesheuvel
  (?)
@ 2016-08-01 10:59     ` zijun_hu
  -1 siblings, 0 replies; 22+ messages in thread
From: zijun_hu @ 2016-08-01 10:59 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Catalin Marinas, Will Deacon, linux-arm-kernel, Mark Rutland,
	Laura Abbott, Suzuki K. Poulose, Jeremy Linton, tj, linux-kernel,
	stable, Andrew Morton, zijun_hu

On 08/01/2016 05:50 PM, Ard Biesheuvel wrote:
> On 1 August 2016 at 11:42, zijun_hu <zijun_hu@zoho.com> wrote:
>> From 07b9216ec3494515e7a6c41e0333eb8782427db3 Mon Sep 17 00:00:00 2001
>> From: zijun_hu <zijun_hu@htc.com>
>> Date: Mon, 1 Aug 2016 17:04:59 +0800
>> Subject: [PATCH] arm64: fix address fault during mapping fdt region
>>
>> fdt_check_header() accesses other fileds of fdt header but
>> the first 8 bytes such as version; so accessing unmapped
>> address fault happens if fdt region locates below align
>> boundary nearly during mapping fdt region, or expressed as
>> (offset + sizeof(struct fdt_header)) > SWAPPER_BLOCK_SIZE
>>
>> fdt header size at least is mapped in order to avoid the issue
>>
>> Signed-off-by: zijun_hu <zijun_hu@htc.com>
>> ---
>>  arch/arm64/mm/mmu.c | 14 ++++++++++++--
>>  1 file changed, 12 insertions(+), 2 deletions(-)
>>
>> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
>> index 0f85a46..0d72b71 100644
>> --- a/arch/arm64/mm/mmu.c
>> +++ b/arch/arm64/mm/mmu.c
>> @@ -744,6 +744,7 @@ void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot)
>>         const u64 dt_virt_base = __fix_to_virt(FIX_FDT);
>>         int offset;
>>         void *dt_virt;
>> +       int dt_header_map_size;
>>
>>         /*
>>          * Check whether the physical FDT address is set and meets the minimum
>> @@ -774,9 +775,18 @@ void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot)
>>         offset = dt_phys % SWAPPER_BLOCK_SIZE;
>>         dt_virt = (void *)dt_virt_base + offset;
>>
>> +       /*
>> +        * fdt_check_header() maybe access any field of fdt header not
>> +        * the first 8 bytes only, so map fdt header size at least for
>> +        * checking fdt header without address fault more portably
>> +        */
>> +       BUILD_BUG_ON(sizeof(struct fdt_header) > SWAPPER_BLOCK_SIZE);
>> +       dt_header_map_size = round_up(offset + sizeof(struct fdt_header),
>> +                       SWAPPER_BLOCK_SIZE);
>> +
>>         /* map the first chunk so we can read the size from the header */
>>         create_mapping_noalloc(round_down(dt_phys, SWAPPER_BLOCK_SIZE),
>> -                       dt_virt_base, SWAPPER_BLOCK_SIZE, prot);
>> +                       dt_virt_base, dt_header_map_size, prot);
>>
>>         if (fdt_check_header(dt_virt) != 0)
>>                 return NULL;
>> @@ -785,7 +795,7 @@ void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot)
>>         if (*size > MAX_FDT_SIZE)
>>                 return NULL;
>>
>> -       if (offset + *size > SWAPPER_BLOCK_SIZE)
>> +       if (offset + *size > dt_header_map_size)
>>                 create_mapping_noalloc(round_down(dt_phys, SWAPPER_BLOCK_SIZE), dt_virt_base,
>>                                round_up(offset + *size, SWAPPER_BLOCK_SIZE), prot);
>>
> 
> Couldn't we simply do this instead?
this solution maybe better, my reason as follows:

1,it can achieve our original purpose, namely, checking whether fdt
header is corrupted before fetching fdt size field; good fdt header can
ensure good fdt size field included more rightly than only a magic filed
normally

2,it is more portable; we only need to call fdt_check_header() and don't
care about fdt header filed layout; moreover,fdt module is another independent
module and arm64 only uses it and should not depend on more details of fdt
such as size and magic fields locate within the first MIN_FDT_ALIGN bytes;
the decision whether a fdt header is corrupted should be left to fdt team

> 
> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
> index 0f85a46c3e18..e8d3b04a2b57 100644
> --- a/arch/arm64/mm/mmu.c
> +++ b/arch/arm64/mm/mmu.c
> @@ -778,7 +778,7 @@ void *__init __fixmap_remap_fdt(phys_addr_t
> dt_phys, int *size, pgprot_t prot)
>         create_mapping_noalloc(round_down(dt_phys, SWAPPER_BLOCK_SIZE),
>                         dt_virt_base, SWAPPER_BLOCK_SIZE, prot);
> 
> -       if (fdt_check_header(dt_virt) != 0)
> +       if (fdt_magic(dt_virt) != FDT_MAGIC)
>                 return NULL;
> 
>         *size = fdt_totalsize(dt_virt);
> 
> We are simply looking for a size field. The OF code will call
> fdt_check_header() again, so anything that is checked there in
> addition to the magic field will still be checked.
> 
here is the first position to involve fdt functions, it maybe more suitable
to checking before using

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] arm64: fix address fault during mapping fdt region
@ 2016-08-01 10:59     ` zijun_hu
  0 siblings, 0 replies; 22+ messages in thread
From: zijun_hu @ 2016-08-01 10:59 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Catalin Marinas, Will Deacon, linux-arm-kernel, Mark Rutland,
	Laura Abbott, Suzuki K. Poulose, Jeremy Linton, tj, linux-kernel,
	stable, Andrew Morton, zijun_hu

On 08/01/2016 05:50 PM, Ard Biesheuvel wrote:
> On 1 August 2016 at 11:42, zijun_hu <zijun_hu@zoho.com> wrote:
>> From 07b9216ec3494515e7a6c41e0333eb8782427db3 Mon Sep 17 00:00:00 2001
>> From: zijun_hu <zijun_hu@htc.com>
>> Date: Mon, 1 Aug 2016 17:04:59 +0800
>> Subject: [PATCH] arm64: fix address fault during mapping fdt region
>>
>> fdt_check_header() accesses other fileds of fdt header but
>> the first 8 bytes such as version; so accessing unmapped
>> address fault happens if fdt region locates below align
>> boundary nearly during mapping fdt region, or expressed as
>> (offset + sizeof(struct fdt_header)) > SWAPPER_BLOCK_SIZE
>>
>> fdt header size at least is mapped in order to avoid the issue
>>
>> Signed-off-by: zijun_hu <zijun_hu@htc.com>
>> ---
>>  arch/arm64/mm/mmu.c | 14 ++++++++++++--
>>  1 file changed, 12 insertions(+), 2 deletions(-)
>>
>> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
>> index 0f85a46..0d72b71 100644
>> --- a/arch/arm64/mm/mmu.c
>> +++ b/arch/arm64/mm/mmu.c
>> @@ -744,6 +744,7 @@ void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot)
>>         const u64 dt_virt_base = __fix_to_virt(FIX_FDT);
>>         int offset;
>>         void *dt_virt;
>> +       int dt_header_map_size;
>>
>>         /*
>>          * Check whether the physical FDT address is set and meets the minimum
>> @@ -774,9 +775,18 @@ void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot)
>>         offset = dt_phys % SWAPPER_BLOCK_SIZE;
>>         dt_virt = (void *)dt_virt_base + offset;
>>
>> +       /*
>> +        * fdt_check_header() maybe access any field of fdt header not
>> +        * the first 8 bytes only, so map fdt header size at least for
>> +        * checking fdt header without address fault more portably
>> +        */
>> +       BUILD_BUG_ON(sizeof(struct fdt_header) > SWAPPER_BLOCK_SIZE);
>> +       dt_header_map_size = round_up(offset + sizeof(struct fdt_header),
>> +                       SWAPPER_BLOCK_SIZE);
>> +
>>         /* map the first chunk so we can read the size from the header */
>>         create_mapping_noalloc(round_down(dt_phys, SWAPPER_BLOCK_SIZE),
>> -                       dt_virt_base, SWAPPER_BLOCK_SIZE, prot);
>> +                       dt_virt_base, dt_header_map_size, prot);
>>
>>         if (fdt_check_header(dt_virt) != 0)
>>                 return NULL;
>> @@ -785,7 +795,7 @@ void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot)
>>         if (*size > MAX_FDT_SIZE)
>>                 return NULL;
>>
>> -       if (offset + *size > SWAPPER_BLOCK_SIZE)
>> +       if (offset + *size > dt_header_map_size)
>>                 create_mapping_noalloc(round_down(dt_phys, SWAPPER_BLOCK_SIZE), dt_virt_base,
>>                                round_up(offset + *size, SWAPPER_BLOCK_SIZE), prot);
>>
> 
> Couldn't we simply do this instead?
this solution maybe better, my reason as follows:

1,it can achieve our original purpose, namely, checking whether fdt
header is corrupted before fetching fdt size field; good fdt header can
ensure good fdt size field included more rightly than only a magic filed
normally

2,it is more portable; we only need to call fdt_check_header() and don't
care about fdt header filed layout; moreover,fdt module is another independent
module and arm64 only uses it and should not depend on more details of fdt
such as size and magic fields locate within the first MIN_FDT_ALIGN bytes;
the decision whether a fdt header is corrupted should be left to fdt team

> 
> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
> index 0f85a46c3e18..e8d3b04a2b57 100644
> --- a/arch/arm64/mm/mmu.c
> +++ b/arch/arm64/mm/mmu.c
> @@ -778,7 +778,7 @@ void *__init __fixmap_remap_fdt(phys_addr_t
> dt_phys, int *size, pgprot_t prot)
>         create_mapping_noalloc(round_down(dt_phys, SWAPPER_BLOCK_SIZE),
>                         dt_virt_base, SWAPPER_BLOCK_SIZE, prot);
> 
> -       if (fdt_check_header(dt_virt) != 0)
> +       if (fdt_magic(dt_virt) != FDT_MAGIC)
>                 return NULL;
> 
>         *size = fdt_totalsize(dt_virt);
> 
> We are simply looking for a size field. The OF code will call
> fdt_check_header() again, so anything that is checked there in
> addition to the magic field will still be checked.
> 
here is the first position to involve fdt functions, it maybe more suitable
to checking before using


^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH] arm64: fix address fault during mapping fdt region
@ 2016-08-01 10:59     ` zijun_hu
  0 siblings, 0 replies; 22+ messages in thread
From: zijun_hu @ 2016-08-01 10:59 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/01/2016 05:50 PM, Ard Biesheuvel wrote:
> On 1 August 2016 at 11:42, zijun_hu <zijun_hu@zoho.com> wrote:
>> From 07b9216ec3494515e7a6c41e0333eb8782427db3 Mon Sep 17 00:00:00 2001
>> From: zijun_hu <zijun_hu@htc.com>
>> Date: Mon, 1 Aug 2016 17:04:59 +0800
>> Subject: [PATCH] arm64: fix address fault during mapping fdt region
>>
>> fdt_check_header() accesses other fileds of fdt header but
>> the first 8 bytes such as version; so accessing unmapped
>> address fault happens if fdt region locates below align
>> boundary nearly during mapping fdt region, or expressed as
>> (offset + sizeof(struct fdt_header)) > SWAPPER_BLOCK_SIZE
>>
>> fdt header size at least is mapped in order to avoid the issue
>>
>> Signed-off-by: zijun_hu <zijun_hu@htc.com>
>> ---
>>  arch/arm64/mm/mmu.c | 14 ++++++++++++--
>>  1 file changed, 12 insertions(+), 2 deletions(-)
>>
>> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
>> index 0f85a46..0d72b71 100644
>> --- a/arch/arm64/mm/mmu.c
>> +++ b/arch/arm64/mm/mmu.c
>> @@ -744,6 +744,7 @@ void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot)
>>         const u64 dt_virt_base = __fix_to_virt(FIX_FDT);
>>         int offset;
>>         void *dt_virt;
>> +       int dt_header_map_size;
>>
>>         /*
>>          * Check whether the physical FDT address is set and meets the minimum
>> @@ -774,9 +775,18 @@ void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot)
>>         offset = dt_phys % SWAPPER_BLOCK_SIZE;
>>         dt_virt = (void *)dt_virt_base + offset;
>>
>> +       /*
>> +        * fdt_check_header() maybe access any field of fdt header not
>> +        * the first 8 bytes only, so map fdt header size at least for
>> +        * checking fdt header without address fault more portably
>> +        */
>> +       BUILD_BUG_ON(sizeof(struct fdt_header) > SWAPPER_BLOCK_SIZE);
>> +       dt_header_map_size = round_up(offset + sizeof(struct fdt_header),
>> +                       SWAPPER_BLOCK_SIZE);
>> +
>>         /* map the first chunk so we can read the size from the header */
>>         create_mapping_noalloc(round_down(dt_phys, SWAPPER_BLOCK_SIZE),
>> -                       dt_virt_base, SWAPPER_BLOCK_SIZE, prot);
>> +                       dt_virt_base, dt_header_map_size, prot);
>>
>>         if (fdt_check_header(dt_virt) != 0)
>>                 return NULL;
>> @@ -785,7 +795,7 @@ void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot)
>>         if (*size > MAX_FDT_SIZE)
>>                 return NULL;
>>
>> -       if (offset + *size > SWAPPER_BLOCK_SIZE)
>> +       if (offset + *size > dt_header_map_size)
>>                 create_mapping_noalloc(round_down(dt_phys, SWAPPER_BLOCK_SIZE), dt_virt_base,
>>                                round_up(offset + *size, SWAPPER_BLOCK_SIZE), prot);
>>
> 
> Couldn't we simply do this instead?
this solution maybe better, my reason as follows?

1?it can achieve our original purpose, namely, checking whether fdt
header is corrupted before fetching fdt size field; good fdt header can
ensure good fdt size field included more rightly than only a magic filed
normally

2?it is more portable; we only need to call fdt_check_header() and don't
care about fdt header filed layout; moreover,fdt module is another independent
module and arm64 only uses it and should not depend on more details of fdt
such as size and magic fields locate within the first MIN_FDT_ALIGN bytes;
the decision whether a fdt header is corrupted should be left to fdt team

> 
> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
> index 0f85a46c3e18..e8d3b04a2b57 100644
> --- a/arch/arm64/mm/mmu.c
> +++ b/arch/arm64/mm/mmu.c
> @@ -778,7 +778,7 @@ void *__init __fixmap_remap_fdt(phys_addr_t
> dt_phys, int *size, pgprot_t prot)
>         create_mapping_noalloc(round_down(dt_phys, SWAPPER_BLOCK_SIZE),
>                         dt_virt_base, SWAPPER_BLOCK_SIZE, prot);
> 
> -       if (fdt_check_header(dt_virt) != 0)
> +       if (fdt_magic(dt_virt) != FDT_MAGIC)
>                 return NULL;
> 
>         *size = fdt_totalsize(dt_virt);
> 
> We are simply looking for a size field. The OF code will call
> fdt_check_header() again, so anything that is checked there in
> addition to the magic field will still be checked.
> 
here is the first position to involve fdt functions, it maybe more suitable
to checking before using

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] arm64: fix address fault during mapping fdt region
  2016-08-01  9:50   ` Ard Biesheuvel
  (?)
@ 2016-08-01 11:06     ` Mark Rutland
  -1 siblings, 0 replies; 22+ messages in thread
From: Mark Rutland @ 2016-08-01 11:06 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: zijun_hu, Catalin Marinas, Will Deacon, linux-arm-kernel,
	Laura Abbott, Suzuki K. Poulose, Jeremy Linton, tj, linux-kernel,
	stable, Andrew Morton, zijun_hu

On Mon, Aug 01, 2016 at 11:50:39AM +0200, Ard Biesheuvel wrote:
> On 1 August 2016 at 11:42, zijun_hu <zijun_hu@zoho.com> wrote:
> > From 07b9216ec3494515e7a6c41e0333eb8782427db3 Mon Sep 17 00:00:00 2001
> > From: zijun_hu <zijun_hu@htc.com>
> > Date: Mon, 1 Aug 2016 17:04:59 +0800
> > Subject: [PATCH] arm64: fix address fault during mapping fdt region
> >
> > fdt_check_header() accesses other fileds of fdt header but
> > the first 8 bytes such as version; so accessing unmapped
> > address fault happens if fdt region locates below align
> > boundary nearly during mapping fdt region, or expressed as
> > (offset + sizeof(struct fdt_header)) > SWAPPER_BLOCK_SIZE
> >
> > fdt header size at least is mapped in order to avoid the issue
> >
> > Signed-off-by: zijun_hu <zijun_hu@htc.com>
> > ---
> >  arch/arm64/mm/mmu.c | 14 ++++++++++++--
> >  1 file changed, 12 insertions(+), 2 deletions(-)
> >
> > diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
> > index 0f85a46..0d72b71 100644
> > --- a/arch/arm64/mm/mmu.c
> > +++ b/arch/arm64/mm/mmu.c
> > @@ -744,6 +744,7 @@ void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot)
> >         const u64 dt_virt_base = __fix_to_virt(FIX_FDT);
> >         int offset;
> >         void *dt_virt;
> > +       int dt_header_map_size;
> >
> >         /*
> >          * Check whether the physical FDT address is set and meets the minimum
> > @@ -774,9 +775,18 @@ void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot)
> >         offset = dt_phys % SWAPPER_BLOCK_SIZE;
> >         dt_virt = (void *)dt_virt_base + offset;
> >
> > +       /*
> > +        * fdt_check_header() maybe access any field of fdt header not
> > +        * the first 8 bytes only, so map fdt header size at least for
> > +        * checking fdt header without address fault more portably
> > +        */
> > +       BUILD_BUG_ON(sizeof(struct fdt_header) > SWAPPER_BLOCK_SIZE);
> > +       dt_header_map_size = round_up(offset + sizeof(struct fdt_header),
> > +                       SWAPPER_BLOCK_SIZE);
> > +
> >         /* map the first chunk so we can read the size from the header */
> >         create_mapping_noalloc(round_down(dt_phys, SWAPPER_BLOCK_SIZE),
> > -                       dt_virt_base, SWAPPER_BLOCK_SIZE, prot);
> > +                       dt_virt_base, dt_header_map_size, prot);
> >
> >         if (fdt_check_header(dt_virt) != 0)
> >                 return NULL;
> > @@ -785,7 +795,7 @@ void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot)
> >         if (*size > MAX_FDT_SIZE)
> >                 return NULL;
> >
> > -       if (offset + *size > SWAPPER_BLOCK_SIZE)
> > +       if (offset + *size > dt_header_map_size)
> >                 create_mapping_noalloc(round_down(dt_phys, SWAPPER_BLOCK_SIZE), dt_virt_base,
> >                                round_up(offset + *size, SWAPPER_BLOCK_SIZE), prot);
> >
> 
> Couldn't we simply do this instead?
> 
> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
> index 0f85a46c3e18..e8d3b04a2b57 100644
> --- a/arch/arm64/mm/mmu.c
> +++ b/arch/arm64/mm/mmu.c
> @@ -778,7 +778,7 @@ void *__init __fixmap_remap_fdt(phys_addr_t
> dt_phys, int *size, pgprot_t prot)
>         create_mapping_noalloc(round_down(dt_phys, SWAPPER_BLOCK_SIZE),
>                         dt_virt_base, SWAPPER_BLOCK_SIZE, prot);
> 
> -       if (fdt_check_header(dt_virt) != 0)
> +       if (fdt_magic(dt_virt) != FDT_MAGIC)
>                 return NULL;
> 
>         *size = fdt_totalsize(dt_virt);
> 
> We are simply looking for a size field. The OF code will call
> fdt_check_header() again, so anything that is checked there in
> addition to the magic field will still be checked.

That looks much nicer to me, and deferring the header check also looks
fine.

If you add a comment above the fdt_magic() check, pointing out why we
can only safely access the magic and totalsize fields (and thus can't
call fdt_check_header() yet):

Acked-by: Mark Rutland <mark.rutland@arm.com>

Thanks,
Mark.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] arm64: fix address fault during mapping fdt region
@ 2016-08-01 11:06     ` Mark Rutland
  0 siblings, 0 replies; 22+ messages in thread
From: Mark Rutland @ 2016-08-01 11:06 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: zijun_hu, Catalin Marinas, Will Deacon, linux-arm-kernel,
	Laura Abbott, Suzuki K. Poulose, Jeremy Linton, tj, linux-kernel,
	stable, Andrew Morton, zijun_hu

On Mon, Aug 01, 2016 at 11:50:39AM +0200, Ard Biesheuvel wrote:
> On 1 August 2016 at 11:42, zijun_hu <zijun_hu@zoho.com> wrote:
> > From 07b9216ec3494515e7a6c41e0333eb8782427db3 Mon Sep 17 00:00:00 2001
> > From: zijun_hu <zijun_hu@htc.com>
> > Date: Mon, 1 Aug 2016 17:04:59 +0800
> > Subject: [PATCH] arm64: fix address fault during mapping fdt region
> >
> > fdt_check_header() accesses other fileds of fdt header but
> > the first 8 bytes such as version; so accessing unmapped
> > address fault happens if fdt region locates below align
> > boundary nearly during mapping fdt region, or expressed as
> > (offset + sizeof(struct fdt_header)) > SWAPPER_BLOCK_SIZE
> >
> > fdt header size at least is mapped in order to avoid the issue
> >
> > Signed-off-by: zijun_hu <zijun_hu@htc.com>
> > ---
> >  arch/arm64/mm/mmu.c | 14 ++++++++++++--
> >  1 file changed, 12 insertions(+), 2 deletions(-)
> >
> > diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
> > index 0f85a46..0d72b71 100644
> > --- a/arch/arm64/mm/mmu.c
> > +++ b/arch/arm64/mm/mmu.c
> > @@ -744,6 +744,7 @@ void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot)
> >         const u64 dt_virt_base = __fix_to_virt(FIX_FDT);
> >         int offset;
> >         void *dt_virt;
> > +       int dt_header_map_size;
> >
> >         /*
> >          * Check whether the physical FDT address is set and meets the minimum
> > @@ -774,9 +775,18 @@ void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot)
> >         offset = dt_phys % SWAPPER_BLOCK_SIZE;
> >         dt_virt = (void *)dt_virt_base + offset;
> >
> > +       /*
> > +        * fdt_check_header() maybe access any field of fdt header not
> > +        * the first 8 bytes only, so map fdt header size at least for
> > +        * checking fdt header without address fault more portably
> > +        */
> > +       BUILD_BUG_ON(sizeof(struct fdt_header) > SWAPPER_BLOCK_SIZE);
> > +       dt_header_map_size = round_up(offset + sizeof(struct fdt_header),
> > +                       SWAPPER_BLOCK_SIZE);
> > +
> >         /* map the first chunk so we can read the size from the header */
> >         create_mapping_noalloc(round_down(dt_phys, SWAPPER_BLOCK_SIZE),
> > -                       dt_virt_base, SWAPPER_BLOCK_SIZE, prot);
> > +                       dt_virt_base, dt_header_map_size, prot);
> >
> >         if (fdt_check_header(dt_virt) != 0)
> >                 return NULL;
> > @@ -785,7 +795,7 @@ void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot)
> >         if (*size > MAX_FDT_SIZE)
> >                 return NULL;
> >
> > -       if (offset + *size > SWAPPER_BLOCK_SIZE)
> > +       if (offset + *size > dt_header_map_size)
> >                 create_mapping_noalloc(round_down(dt_phys, SWAPPER_BLOCK_SIZE), dt_virt_base,
> >                                round_up(offset + *size, SWAPPER_BLOCK_SIZE), prot);
> >
> 
> Couldn't we simply do this instead?
> 
> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
> index 0f85a46c3e18..e8d3b04a2b57 100644
> --- a/arch/arm64/mm/mmu.c
> +++ b/arch/arm64/mm/mmu.c
> @@ -778,7 +778,7 @@ void *__init __fixmap_remap_fdt(phys_addr_t
> dt_phys, int *size, pgprot_t prot)
>         create_mapping_noalloc(round_down(dt_phys, SWAPPER_BLOCK_SIZE),
>                         dt_virt_base, SWAPPER_BLOCK_SIZE, prot);
> 
> -       if (fdt_check_header(dt_virt) != 0)
> +       if (fdt_magic(dt_virt) != FDT_MAGIC)
>                 return NULL;
> 
>         *size = fdt_totalsize(dt_virt);
> 
> We are simply looking for a size field. The OF code will call
> fdt_check_header() again, so anything that is checked there in
> addition to the magic field will still be checked.

That looks much nicer to me, and deferring the header check also looks
fine.

If you add a comment above the fdt_magic() check, pointing out why we
can only safely access the magic and totalsize fields (and thus can't
call fdt_check_header() yet):

Acked-by: Mark Rutland <mark.rutland@arm.com>

Thanks,
Mark.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH] arm64: fix address fault during mapping fdt region
@ 2016-08-01 11:06     ` Mark Rutland
  0 siblings, 0 replies; 22+ messages in thread
From: Mark Rutland @ 2016-08-01 11:06 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Aug 01, 2016 at 11:50:39AM +0200, Ard Biesheuvel wrote:
> On 1 August 2016 at 11:42, zijun_hu <zijun_hu@zoho.com> wrote:
> > From 07b9216ec3494515e7a6c41e0333eb8782427db3 Mon Sep 17 00:00:00 2001
> > From: zijun_hu <zijun_hu@htc.com>
> > Date: Mon, 1 Aug 2016 17:04:59 +0800
> > Subject: [PATCH] arm64: fix address fault during mapping fdt region
> >
> > fdt_check_header() accesses other fileds of fdt header but
> > the first 8 bytes such as version; so accessing unmapped
> > address fault happens if fdt region locates below align
> > boundary nearly during mapping fdt region, or expressed as
> > (offset + sizeof(struct fdt_header)) > SWAPPER_BLOCK_SIZE
> >
> > fdt header size at least is mapped in order to avoid the issue
> >
> > Signed-off-by: zijun_hu <zijun_hu@htc.com>
> > ---
> >  arch/arm64/mm/mmu.c | 14 ++++++++++++--
> >  1 file changed, 12 insertions(+), 2 deletions(-)
> >
> > diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
> > index 0f85a46..0d72b71 100644
> > --- a/arch/arm64/mm/mmu.c
> > +++ b/arch/arm64/mm/mmu.c
> > @@ -744,6 +744,7 @@ void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot)
> >         const u64 dt_virt_base = __fix_to_virt(FIX_FDT);
> >         int offset;
> >         void *dt_virt;
> > +       int dt_header_map_size;
> >
> >         /*
> >          * Check whether the physical FDT address is set and meets the minimum
> > @@ -774,9 +775,18 @@ void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot)
> >         offset = dt_phys % SWAPPER_BLOCK_SIZE;
> >         dt_virt = (void *)dt_virt_base + offset;
> >
> > +       /*
> > +        * fdt_check_header() maybe access any field of fdt header not
> > +        * the first 8 bytes only, so map fdt header size at least for
> > +        * checking fdt header without address fault more portably
> > +        */
> > +       BUILD_BUG_ON(sizeof(struct fdt_header) > SWAPPER_BLOCK_SIZE);
> > +       dt_header_map_size = round_up(offset + sizeof(struct fdt_header),
> > +                       SWAPPER_BLOCK_SIZE);
> > +
> >         /* map the first chunk so we can read the size from the header */
> >         create_mapping_noalloc(round_down(dt_phys, SWAPPER_BLOCK_SIZE),
> > -                       dt_virt_base, SWAPPER_BLOCK_SIZE, prot);
> > +                       dt_virt_base, dt_header_map_size, prot);
> >
> >         if (fdt_check_header(dt_virt) != 0)
> >                 return NULL;
> > @@ -785,7 +795,7 @@ void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot)
> >         if (*size > MAX_FDT_SIZE)
> >                 return NULL;
> >
> > -       if (offset + *size > SWAPPER_BLOCK_SIZE)
> > +       if (offset + *size > dt_header_map_size)
> >                 create_mapping_noalloc(round_down(dt_phys, SWAPPER_BLOCK_SIZE), dt_virt_base,
> >                                round_up(offset + *size, SWAPPER_BLOCK_SIZE), prot);
> >
> 
> Couldn't we simply do this instead?
> 
> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
> index 0f85a46c3e18..e8d3b04a2b57 100644
> --- a/arch/arm64/mm/mmu.c
> +++ b/arch/arm64/mm/mmu.c
> @@ -778,7 +778,7 @@ void *__init __fixmap_remap_fdt(phys_addr_t
> dt_phys, int *size, pgprot_t prot)
>         create_mapping_noalloc(round_down(dt_phys, SWAPPER_BLOCK_SIZE),
>                         dt_virt_base, SWAPPER_BLOCK_SIZE, prot);
> 
> -       if (fdt_check_header(dt_virt) != 0)
> +       if (fdt_magic(dt_virt) != FDT_MAGIC)
>                 return NULL;
> 
>         *size = fdt_totalsize(dt_virt);
> 
> We are simply looking for a size field. The OF code will call
> fdt_check_header() again, so anything that is checked there in
> addition to the magic field will still be checked.

That looks much nicer to me, and deferring the header check also looks
fine.

If you add a comment above the fdt_magic() check, pointing out why we
can only safely access the magic and totalsize fields (and thus can't
call fdt_check_header() yet):

Acked-by: Mark Rutland <mark.rutland@arm.com>

Thanks,
Mark.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] arm64: fix address fault during mapping fdt region
  2016-08-01 10:59     ` zijun_hu
  (?)
@ 2016-08-01 11:24       ` Mark Rutland
  -1 siblings, 0 replies; 22+ messages in thread
From: Mark Rutland @ 2016-08-01 11:24 UTC (permalink / raw)
  To: zijun_hu
  Cc: Ard Biesheuvel, Catalin Marinas, Will Deacon, linux-arm-kernel,
	Laura Abbott, Suzuki K. Poulose, Jeremy Linton, tj, linux-kernel,
	stable, Andrew Morton, zijun_hu

On Mon, Aug 01, 2016 at 06:59:50PM +0800, zijun_hu wrote:
> On 08/01/2016 05:50 PM, Ard Biesheuvel wrote:
> > On 1 August 2016 at 11:42, zijun_hu <zijun_hu@zoho.com> wrote:
> > Couldn't we simply do this instead?
> this solution maybe better, my reason as follows:
> 
> 1,it can achieve our original purpose, namely, checking whether fdt
> header is corrupted before fetching fdt size field; good fdt header can
> ensure good fdt size field included more rightly than only a magic filed
> normally

The only additional fields fdt_check_header checks are version and
last_comp_version. In the absence of corruption, deferring these checks
should be ok. We assume that the header is compatible regardless (or
those fields would be meaningless).

Even with corruption, it's possible for these to appear valid to
fdt_check_header(). For the purpose of best-effort corruption detection,
checking the magic alone in this early codepath seems ok to me. It seems
unlikely that we'd have a valid magic yet a corrupted totalsize.

That all said, I'm not against mapping the whole header if it's simple
enough to do so.

> 2,it is more portable; we only need to call fdt_check_header() and don't
> care about fdt header filed layout; moreover,fdt module is another independent
> module and arm64 only uses it and should not depend on more details of fdt
> such as size and magic fields locate within the first MIN_FDT_ALIGN bytes;
> the decision whether a fdt header is corrupted should be left to fdt team

While it's true that we assume knowledge of the FDT format, and ideally
we'd leave this to common code, we do so regardless by requiring the
header size. So both approaches assume details regarding the FDT format.

Thanks,
Mark.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] arm64: fix address fault during mapping fdt region
@ 2016-08-01 11:24       ` Mark Rutland
  0 siblings, 0 replies; 22+ messages in thread
From: Mark Rutland @ 2016-08-01 11:24 UTC (permalink / raw)
  To: zijun_hu
  Cc: Ard Biesheuvel, Catalin Marinas, Will Deacon, linux-arm-kernel,
	Laura Abbott, Suzuki K. Poulose, Jeremy Linton, tj, linux-kernel,
	stable, Andrew Morton, zijun_hu

On Mon, Aug 01, 2016 at 06:59:50PM +0800, zijun_hu wrote:
> On 08/01/2016 05:50 PM, Ard Biesheuvel wrote:
> > On 1 August 2016 at 11:42, zijun_hu <zijun_hu@zoho.com> wrote:
> > Couldn't we simply do this instead?
> this solution maybe better, my reason as follows:
> 
> 1,it can achieve our original purpose, namely, checking whether fdt
> header is corrupted before fetching fdt size field; good fdt header can
> ensure good fdt size field included more rightly than only a magic filed
> normally

The only additional fields fdt_check_header checks are version and
last_comp_version. In the absence of corruption, deferring these checks
should be ok. We assume that the header is compatible regardless (or
those fields would be meaningless).

Even with corruption, it's possible for these to appear valid to
fdt_check_header(). For the purpose of best-effort corruption detection,
checking the magic alone in this early codepath seems ok to me. It seems
unlikely that we'd have a valid magic yet a corrupted totalsize.

That all said, I'm not against mapping the whole header if it's simple
enough to do so.

> 2,it is more portable; we only need to call fdt_check_header() and don't
> care about fdt header filed layout; moreover,fdt module is another independent
> module and arm64 only uses it and should not depend on more details of fdt
> such as size and magic fields locate within the first MIN_FDT_ALIGN bytes;
> the decision whether a fdt header is corrupted should be left to fdt team

While it's true that we assume knowledge of the FDT format, and ideally
we'd leave this to common code, we do so regardless by requiring the
header size. So both approaches assume details regarding the FDT format.

Thanks,
Mark.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH] arm64: fix address fault during mapping fdt region
@ 2016-08-01 11:24       ` Mark Rutland
  0 siblings, 0 replies; 22+ messages in thread
From: Mark Rutland @ 2016-08-01 11:24 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Aug 01, 2016 at 06:59:50PM +0800, zijun_hu wrote:
> On 08/01/2016 05:50 PM, Ard Biesheuvel wrote:
> > On 1 August 2016 at 11:42, zijun_hu <zijun_hu@zoho.com> wrote:
> > Couldn't we simply do this instead?
> this solution maybe better, my reason as follows?
> 
> 1?it can achieve our original purpose, namely, checking whether fdt
> header is corrupted before fetching fdt size field; good fdt header can
> ensure good fdt size field included more rightly than only a magic filed
> normally

The only additional fields fdt_check_header checks are version and
last_comp_version. In the absence of corruption, deferring these checks
should be ok. We assume that the header is compatible regardless (or
those fields would be meaningless).

Even with corruption, it's possible for these to appear valid to
fdt_check_header(). For the purpose of best-effort corruption detection,
checking the magic alone in this early codepath seems ok to me. It seems
unlikely that we'd have a valid magic yet a corrupted totalsize.

That all said, I'm not against mapping the whole header if it's simple
enough to do so.

> 2?it is more portable; we only need to call fdt_check_header() and don't
> care about fdt header filed layout; moreover,fdt module is another independent
> module and arm64 only uses it and should not depend on more details of fdt
> such as size and magic fields locate within the first MIN_FDT_ALIGN bytes;
> the decision whether a fdt header is corrupted should be left to fdt team

While it's true that we assume knowledge of the FDT format, and ideally
we'd leave this to common code, we do so regardless by requiring the
header size. So both approaches assume details regarding the FDT format.

Thanks,
Mark.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] arm64: fix address fault during mapping fdt region
  2016-08-01  9:42 ` zijun_hu
@ 2016-08-01 12:24   ` Greg KH
  -1 siblings, 0 replies; 22+ messages in thread
From: Greg KH @ 2016-08-01 12:24 UTC (permalink / raw)
  To: zijun_hu
  Cc: catalin.marinas, will.deacon, linux-arm-kernel, ard.biesheuvel,
	mark.rutland, labbott, suzuki.poulose, jeremy.linton, tj,
	linux-kernel, stable, akpm, zijun_hu

On Mon, Aug 01, 2016 at 05:42:19PM +0800, zijun_hu wrote:
> >From 07b9216ec3494515e7a6c41e0333eb8782427db3 Mon Sep 17 00:00:00 2001
> From: zijun_hu <zijun_hu@htc.com>
> Date: Mon, 1 Aug 2016 17:04:59 +0800
> Subject: [PATCH] arm64: fix address fault during mapping fdt region
> 
> fdt_check_header() accesses other fileds of fdt header but
> the first 8 bytes such as version; so accessing unmapped
> address fault happens if fdt region locates below align
> boundary nearly during mapping fdt region, or expressed as
> (offset + sizeof(struct fdt_header)) > SWAPPER_BLOCK_SIZE
> 
> fdt header size at least is mapped in order to avoid the issue
> 
> Signed-off-by: zijun_hu <zijun_hu@htc.com>
> ---
>  arch/arm64/mm/mmu.c | 14 ++++++++++++--
>  1 file changed, 12 insertions(+), 2 deletions(-)

<formletter>

This is not the correct way to submit patches for inclusion in the
stable kernel tree.  Please read Documentation/stable_kernel_rules.txt
for how to do this properly.

</formletter>

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH] arm64: fix address fault during mapping fdt region
@ 2016-08-01 12:24   ` Greg KH
  0 siblings, 0 replies; 22+ messages in thread
From: Greg KH @ 2016-08-01 12:24 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Aug 01, 2016 at 05:42:19PM +0800, zijun_hu wrote:
> >From 07b9216ec3494515e7a6c41e0333eb8782427db3 Mon Sep 17 00:00:00 2001
> From: zijun_hu <zijun_hu@htc.com>
> Date: Mon, 1 Aug 2016 17:04:59 +0800
> Subject: [PATCH] arm64: fix address fault during mapping fdt region
> 
> fdt_check_header() accesses other fileds of fdt header but
> the first 8 bytes such as version; so accessing unmapped
> address fault happens if fdt region locates below align
> boundary nearly during mapping fdt region, or expressed as
> (offset + sizeof(struct fdt_header)) > SWAPPER_BLOCK_SIZE
> 
> fdt header size at least is mapped in order to avoid the issue
> 
> Signed-off-by: zijun_hu <zijun_hu@htc.com>
> ---
>  arch/arm64/mm/mmu.c | 14 ++++++++++++--
>  1 file changed, 12 insertions(+), 2 deletions(-)

<formletter>

This is not the correct way to submit patches for inclusion in the
stable kernel tree.  Please read Documentation/stable_kernel_rules.txt
for how to do this properly.

</formletter>

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] arm64: fix address fault during mapping fdt region
  2016-08-01 11:24       ` Mark Rutland
  (?)
@ 2016-08-01 13:17         ` zijun_hu
  -1 siblings, 0 replies; 22+ messages in thread
From: zijun_hu @ 2016-08-01 13:17 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Ard Biesheuvel, Catalin Marinas, Will Deacon, linux-arm-kernel,
	Laura Abbott, Suzuki K. Poulose, Jeremy Linton, tj, linux-kernel,
	stable, Andrew Morton, zijun_hu

On 08/01/2016 07:24 PM, Mark Rutland wrote:
> On Mon, Aug 01, 2016 at 06:59:50PM +0800, zijun_hu wrote:
>> On 08/01/2016 05:50 PM, Ard Biesheuvel wrote:
>>> On 1 August 2016 at 11:42, zijun_hu <zijun_hu@zoho.com> wrote:
>>> Couldn't we simply do this instead?
>> this solution maybe better, my reason as follows:
>>
>> 1,it can achieve our original purpose, namely, checking whether fdt
>> header is corrupted before fetching fdt size field; good fdt header can
>> ensure good fdt size field included more rightly than only a magic filed
>> normally
> 
> The only additional fields fdt_check_header checks are version and
> last_comp_version. In the absence of corruption, deferring these checks
> should be ok. We assume that the header is compatible regardless (or
> those fields would be meaningless).
> 
> Even with corruption, it's possible for these to appear valid to
> fdt_check_header(). For the purpose of best-effort corruption detection,
> checking the magic alone in this early codepath seems ok to me. It seems
> unlikely that we'd have a valid magic yet a corrupted totalsize.
> 
> That all said, I'm not against mapping the whole header if it's simple
> enough to do so.
>
 
okay, as indicated by another mail sent by ard.biesheuvel, "the only fields we
can assume to be mapped are 'magic' and 'totalsize'", accessing last_comp_version
or version maybe causes address fault under some extreme conditions

according to current fdt_check_header definition, another case is regard as 
good fdt header, condition (fdt_magic(dt_virt) != FDT_MAGIC) don't cover
as marked within below function body

int fdt_check_header(const void *fdt)
{
	if (fdt_magic(fdt) == FDT_MAGIC) {
		/* Complete tree */
		if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
			return -FDT_ERR_BADVERSION;
		if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION)
			return -FDT_ERR_BADVERSION;
	} else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
		/* Unfinished sequential-write blob */
		if (fdt_size_dt_struct(fdt) == 0)  
			return -FDT_ERR_BADSTATE;

acess field size_dt_struct too, this condition is regarded as good fdt header too


	} else {
		return -FDT_ERR_BADMAGIC;
	}

	return 0;
}

>> 2,it is more portable; we only need to call fdt_check_header() and don't
>> care about fdt header filed layout; moreover,fdt module is another independent
>> module and arm64 only uses it and should not depend on more details of fdt
>> such as size and magic fields locate within the first MIN_FDT_ALIGN bytes;
>> the decision whether a fdt header is corrupted should be left to fdt team
> 
> While it's true that we assume knowledge of the FDT format, and ideally
> we'd leave this to common code, we do so regardless by requiring the
> header size. So both approaches assume details regarding the FDT format.
> 
okay, the only thing my solution is depends on is the fdt header struct name
which maybe remain unchanged in further fdt source modification
regardless of fields layout or position or header size;

by the way, my solution only maps more one SWAPPER_BLOCK_SIZE at extreme condition
(offset + sizeof(struct fdt_header)) > SWAPPER_BLOCK_SIZE, it can occurs very rarely,
even it happens, it is no matter due to the fast mapping operations

That all said, ard.biesheuvel's can resolves address fault too, you can decide which
solution to used, maybe ask fdt team for some advisements

> Thanks,
> Mark.
> 

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] arm64: fix address fault during mapping fdt region
@ 2016-08-01 13:17         ` zijun_hu
  0 siblings, 0 replies; 22+ messages in thread
From: zijun_hu @ 2016-08-01 13:17 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Ard Biesheuvel, Catalin Marinas, Will Deacon, linux-arm-kernel,
	Laura Abbott, Suzuki K. Poulose, Jeremy Linton, tj, linux-kernel,
	stable, Andrew Morton, zijun_hu

On 08/01/2016 07:24 PM, Mark Rutland wrote:
> On Mon, Aug 01, 2016 at 06:59:50PM +0800, zijun_hu wrote:
>> On 08/01/2016 05:50 PM, Ard Biesheuvel wrote:
>>> On 1 August 2016 at 11:42, zijun_hu <zijun_hu@zoho.com> wrote:
>>> Couldn't we simply do this instead?
>> this solution maybe better, my reason as follows:
>>
>> 1,it can achieve our original purpose, namely, checking whether fdt
>> header is corrupted before fetching fdt size field; good fdt header can
>> ensure good fdt size field included more rightly than only a magic filed
>> normally
> 
> The only additional fields fdt_check_header checks are version and
> last_comp_version. In the absence of corruption, deferring these checks
> should be ok. We assume that the header is compatible regardless (or
> those fields would be meaningless).
> 
> Even with corruption, it's possible for these to appear valid to
> fdt_check_header(). For the purpose of best-effort corruption detection,
> checking the magic alone in this early codepath seems ok to me. It seems
> unlikely that we'd have a valid magic yet a corrupted totalsize.
> 
> That all said, I'm not against mapping the whole header if it's simple
> enough to do so.
>
 
okay, as indicated by another mail sent by ard.biesheuvel, "the only fields we
can assume to be mapped are 'magic' and 'totalsize'", accessing last_comp_version
or version maybe causes address fault under some extreme conditions

according to current fdt_check_header definition, another case is regard as 
good fdt header, condition (fdt_magic(dt_virt) != FDT_MAGIC) don't cover
as marked within below function body

int fdt_check_header(const void *fdt)
{
	if (fdt_magic(fdt) == FDT_MAGIC) {
		/* Complete tree */
		if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
			return -FDT_ERR_BADVERSION;
		if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION)
			return -FDT_ERR_BADVERSION;
	} else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
		/* Unfinished sequential-write blob */
		if (fdt_size_dt_struct(fdt) == 0)  
			return -FDT_ERR_BADSTATE;

acess field size_dt_struct too, this condition is regarded as good fdt header too


	} else {
		return -FDT_ERR_BADMAGIC;
	}

	return 0;
}

>> 2,it is more portable; we only need to call fdt_check_header() and don't
>> care about fdt header filed layout; moreover,fdt module is another independent
>> module and arm64 only uses it and should not depend on more details of fdt
>> such as size and magic fields locate within the first MIN_FDT_ALIGN bytes;
>> the decision whether a fdt header is corrupted should be left to fdt team
> 
> While it's true that we assume knowledge of the FDT format, and ideally
> we'd leave this to common code, we do so regardless by requiring the
> header size. So both approaches assume details regarding the FDT format.
> 
okay, the only thing my solution is depends on is the fdt header struct name
which maybe remain unchanged in further fdt source modification
regardless of fields layout or position or header size;

by the way, my solution only maps more one SWAPPER_BLOCK_SIZE at extreme condition
(offset + sizeof(struct fdt_header)) > SWAPPER_BLOCK_SIZE, it can occurs very rarely,
even it happens, it is no matter due to the fast mapping operations

That all said, ard.biesheuvel's can resolves address fault too, you can decide which
solution to used, maybe ask fdt team for some advisements

> Thanks,
> Mark.
> 


^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH] arm64: fix address fault during mapping fdt region
@ 2016-08-01 13:17         ` zijun_hu
  0 siblings, 0 replies; 22+ messages in thread
From: zijun_hu @ 2016-08-01 13:17 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/01/2016 07:24 PM, Mark Rutland wrote:
> On Mon, Aug 01, 2016 at 06:59:50PM +0800, zijun_hu wrote:
>> On 08/01/2016 05:50 PM, Ard Biesheuvel wrote:
>>> On 1 August 2016 at 11:42, zijun_hu <zijun_hu@zoho.com> wrote:
>>> Couldn't we simply do this instead?
>> this solution maybe better, my reason as follows?
>>
>> 1?it can achieve our original purpose, namely, checking whether fdt
>> header is corrupted before fetching fdt size field; good fdt header can
>> ensure good fdt size field included more rightly than only a magic filed
>> normally
> 
> The only additional fields fdt_check_header checks are version and
> last_comp_version. In the absence of corruption, deferring these checks
> should be ok. We assume that the header is compatible regardless (or
> those fields would be meaningless).
> 
> Even with corruption, it's possible for these to appear valid to
> fdt_check_header(). For the purpose of best-effort corruption detection,
> checking the magic alone in this early codepath seems ok to me. It seems
> unlikely that we'd have a valid magic yet a corrupted totalsize.
> 
> That all said, I'm not against mapping the whole header if it's simple
> enough to do so.
>
 
okay, as indicated by another mail sent by ard.biesheuvel, "the only fields we
can assume to be mapped are 'magic' and 'totalsize'", accessing last_comp_version
or version maybe causes address fault under some extreme conditions

according to current fdt_check_header definition, another case is regard as 
good fdt header, condition (fdt_magic(dt_virt) != FDT_MAGIC) don't cover
as marked within below function body

int fdt_check_header(const void *fdt)
{
	if (fdt_magic(fdt) == FDT_MAGIC) {
		/* Complete tree */
		if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
			return -FDT_ERR_BADVERSION;
		if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION)
			return -FDT_ERR_BADVERSION;
	} else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
		/* Unfinished sequential-write blob */
		if (fdt_size_dt_struct(fdt) == 0)  
			return -FDT_ERR_BADSTATE;

acess field size_dt_struct too, this condition is regarded as good fdt header too


	} else {
		return -FDT_ERR_BADMAGIC;
	}

	return 0;
}

>> 2?it is more portable; we only need to call fdt_check_header() and don't
>> care about fdt header filed layout; moreover,fdt module is another independent
>> module and arm64 only uses it and should not depend on more details of fdt
>> such as size and magic fields locate within the first MIN_FDT_ALIGN bytes;
>> the decision whether a fdt header is corrupted should be left to fdt team
> 
> While it's true that we assume knowledge of the FDT format, and ideally
> we'd leave this to common code, we do so regardless by requiring the
> header size. So both approaches assume details regarding the FDT format.
> 
okay, the only thing my solution is depends on is the fdt header struct name
which maybe remain unchanged in further fdt source modification
regardless of fields layout or position or header size;

by the way, my solution only maps more one SWAPPER_BLOCK_SIZE at extreme condition
(offset + sizeof(struct fdt_header)) > SWAPPER_BLOCK_SIZE, it can occurs very rarely,
even it happens, it is no matter due to the fast mapping operations

That all said, ard.biesheuvel's can resolves address fault too, you can decide which
solution to used, maybe ask fdt team for some advisements

> Thanks,
> Mark.
> 

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] arm64: fix address fault during mapping fdt region
  2016-08-01 13:17         ` zijun_hu
  (?)
@ 2016-08-01 13:31           ` Mark Rutland
  -1 siblings, 0 replies; 22+ messages in thread
From: Mark Rutland @ 2016-08-01 13:31 UTC (permalink / raw)
  To: zijun_hu
  Cc: Ard Biesheuvel, Catalin Marinas, Will Deacon, linux-arm-kernel,
	Laura Abbott, Suzuki K. Poulose, Jeremy Linton, tj, linux-kernel,
	stable, Andrew Morton, zijun_hu

On Mon, Aug 01, 2016 at 09:17:09PM +0800, zijun_hu wrote:
> On 08/01/2016 07:24 PM, Mark Rutland wrote:
> > On Mon, Aug 01, 2016 at 06:59:50PM +0800, zijun_hu wrote:
> >> 2,it is more portable; we only need to call fdt_check_header() and don't
> >> care about fdt header filed layout; moreover,fdt module is another independent
> >> module and arm64 only uses it and should not depend on more details of fdt
> >> such as size and magic fields locate within the first MIN_FDT_ALIGN bytes;
> >> the decision whether a fdt header is corrupted should be left to fdt team
> > 
> > While it's true that we assume knowledge of the FDT format, and ideally
> > we'd leave this to common code, we do so regardless by requiring the
> > header size. So both approaches assume details regarding the FDT format.
> > 
> okay, the only thing my solution is depends on is the fdt header struct name
> which maybe remain unchanged in further fdt source modification
> regardless of fields layout or position or header size;
> 
> by the way, my solution only maps more one SWAPPER_BLOCK_SIZE at extreme condition
> (offset + sizeof(struct fdt_header)) > SWAPPER_BLOCK_SIZE, it can occurs very rarely,
> even it happens, it is no matter due to the fast mapping operations
> 
> That all said, ard.biesheuvel's can resolves address fault too, you can decide which
> solution to used, maybe ask fdt team for some advisements

As a member of the "fdt team" (at least for bindings and the spec), I'm
happy with Ard's patch. ;)

Regardless, many thanks for the report, and the proposed fix!

Thanks,
Mark.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] arm64: fix address fault during mapping fdt region
@ 2016-08-01 13:31           ` Mark Rutland
  0 siblings, 0 replies; 22+ messages in thread
From: Mark Rutland @ 2016-08-01 13:31 UTC (permalink / raw)
  To: zijun_hu
  Cc: Ard Biesheuvel, Catalin Marinas, Will Deacon, linux-arm-kernel,
	Laura Abbott, Suzuki K. Poulose, Jeremy Linton, tj, linux-kernel,
	stable, Andrew Morton, zijun_hu

On Mon, Aug 01, 2016 at 09:17:09PM +0800, zijun_hu wrote:
> On 08/01/2016 07:24 PM, Mark Rutland wrote:
> > On Mon, Aug 01, 2016 at 06:59:50PM +0800, zijun_hu wrote:
> >> 2,it is more portable; we only need to call fdt_check_header() and don't
> >> care about fdt header filed layout; moreover,fdt module is another independent
> >> module and arm64 only uses it and should not depend on more details of fdt
> >> such as size and magic fields locate within the first MIN_FDT_ALIGN bytes;
> >> the decision whether a fdt header is corrupted should be left to fdt team
> > 
> > While it's true that we assume knowledge of the FDT format, and ideally
> > we'd leave this to common code, we do so regardless by requiring the
> > header size. So both approaches assume details regarding the FDT format.
> > 
> okay, the only thing my solution is depends on is the fdt header struct name
> which maybe remain unchanged in further fdt source modification
> regardless of fields layout or position or header size;
> 
> by the way, my solution only maps more one SWAPPER_BLOCK_SIZE at extreme condition
> (offset + sizeof(struct fdt_header)) > SWAPPER_BLOCK_SIZE, it can occurs very rarely,
> even it happens, it is no matter due to the fast mapping operations
> 
> That all said, ard.biesheuvel's can resolves address fault too, you can decide which
> solution to used, maybe ask fdt team for some advisements

As a member of the "fdt team" (at least for bindings and the spec), I'm
happy with Ard's patch. ;)

Regardless, many thanks for the report, and the proposed fix!

Thanks,
Mark.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH] arm64: fix address fault during mapping fdt region
@ 2016-08-01 13:31           ` Mark Rutland
  0 siblings, 0 replies; 22+ messages in thread
From: Mark Rutland @ 2016-08-01 13:31 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Aug 01, 2016 at 09:17:09PM +0800, zijun_hu wrote:
> On 08/01/2016 07:24 PM, Mark Rutland wrote:
> > On Mon, Aug 01, 2016 at 06:59:50PM +0800, zijun_hu wrote:
> >> 2?it is more portable; we only need to call fdt_check_header() and don't
> >> care about fdt header filed layout; moreover,fdt module is another independent
> >> module and arm64 only uses it and should not depend on more details of fdt
> >> such as size and magic fields locate within the first MIN_FDT_ALIGN bytes;
> >> the decision whether a fdt header is corrupted should be left to fdt team
> > 
> > While it's true that we assume knowledge of the FDT format, and ideally
> > we'd leave this to common code, we do so regardless by requiring the
> > header size. So both approaches assume details regarding the FDT format.
> > 
> okay, the only thing my solution is depends on is the fdt header struct name
> which maybe remain unchanged in further fdt source modification
> regardless of fields layout or position or header size;
> 
> by the way, my solution only maps more one SWAPPER_BLOCK_SIZE at extreme condition
> (offset + sizeof(struct fdt_header)) > SWAPPER_BLOCK_SIZE, it can occurs very rarely,
> even it happens, it is no matter due to the fast mapping operations
> 
> That all said, ard.biesheuvel's can resolves address fault too, you can decide which
> solution to used, maybe ask fdt team for some advisements

As a member of the "fdt team" (at least for bindings and the spec), I'm
happy with Ard's patch. ;)

Regardless, many thanks for the report, and the proposed fix!

Thanks,
Mark.

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2016-08-01 13:31 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-08-01  9:42 [PATCH] arm64: fix address fault during mapping fdt region zijun_hu
2016-08-01  9:42 ` zijun_hu
2016-08-01  9:50 ` Ard Biesheuvel
2016-08-01  9:50   ` Ard Biesheuvel
2016-08-01  9:50   ` Ard Biesheuvel
2016-08-01 10:59   ` zijun_hu
2016-08-01 10:59     ` zijun_hu
2016-08-01 10:59     ` zijun_hu
2016-08-01 11:24     ` Mark Rutland
2016-08-01 11:24       ` Mark Rutland
2016-08-01 11:24       ` Mark Rutland
2016-08-01 13:17       ` zijun_hu
2016-08-01 13:17         ` zijun_hu
2016-08-01 13:17         ` zijun_hu
2016-08-01 13:31         ` Mark Rutland
2016-08-01 13:31           ` Mark Rutland
2016-08-01 13:31           ` Mark Rutland
2016-08-01 11:06   ` Mark Rutland
2016-08-01 11:06     ` Mark Rutland
2016-08-01 11:06     ` Mark Rutland
2016-08-01 12:24 ` Greg KH
2016-08-01 12:24   ` Greg KH

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.