All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2][next] Fix undefined behavior bug and add bounds-checking coverage
@ 2023-10-11 21:31 Gustavo A. R. Silva
  2023-10-11 21:34 ` [PATCH 1/2][next] clk: socfpga: Fix undefined behavior bug in struct stratix10_clock_data Gustavo A. R. Silva
  2023-10-11 21:35 ` [PATCH 2/2][next] clk: socfpga: agilex: Add bounds-checking coverage for " Gustavo A. R. Silva
  0 siblings, 2 replies; 7+ messages in thread
From: Gustavo A. R. Silva @ 2023-10-11 21:31 UTC (permalink / raw)
  To: Dinh Nguyen, Michael Turquette, Stephen Boyd
  Cc: Kees Cook, linux-kernel, Gustavo A. R. Silva, linux-hardening

This series aims to fix an undefined behavior bug in
`struct stratix10_clock_data` and add bounds-checking
coverage at run-time for flexible-array member `hws`
in `struct clk_hw_onecell_data` when accessed throught
`struct stratix10_clock_data`.

Gustavo A. R. Silva (2):
  clk: socfpga: Fix undefined behavior bug in struct
    stratix10_clock_data
  clk: socfpga: agilex: Add bounds-checking coverage for struct
    stratix10_clock_data

 drivers/clk/socfpga/clk-agilex.c    | 12 ++++++------
 drivers/clk/socfpga/clk-s10.c       |  6 +++---
 drivers/clk/socfpga/stratix10-clk.h |  4 +++-
 3 files changed, 12 insertions(+), 10 deletions(-)

-- 
2.34.1


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

* [PATCH 1/2][next] clk: socfpga: Fix undefined behavior bug in struct stratix10_clock_data
  2023-10-11 21:31 [PATCH 0/2][next] Fix undefined behavior bug and add bounds-checking coverage Gustavo A. R. Silva
@ 2023-10-11 21:34 ` Gustavo A. R. Silva
  2023-10-11 21:38   ` Kees Cook
  2023-10-11 21:35 ` [PATCH 2/2][next] clk: socfpga: agilex: Add bounds-checking coverage for " Gustavo A. R. Silva
  1 sibling, 1 reply; 7+ messages in thread
From: Gustavo A. R. Silva @ 2023-10-11 21:34 UTC (permalink / raw)
  To: Dinh Nguyen, Michael Turquette, Stephen Boyd
  Cc: Kees Cook, linux-kernel, Gustavo A. R. Silva, linux-hardening

`struct clk_hw_onecell_data` is a flexible structure, which means that
it contains flexible-array member at the bottom, in this case array
`hws`:

include/linux/clk-provider.h:
1380 struct clk_hw_onecell_data {
1381         unsigned int num;
1382         struct clk_hw *hws[] __counted_by(num);
1383 };

This could potentially lead to an overwrite of the objects following
`clk_data` in `struct stratix10_clock_data`, in this case
`void __iomem *base;` at run-time:

drivers/clk/socfpga/stratix10-clk.h:
  9 struct stratix10_clock_data {
 10         struct clk_hw_onecell_data      clk_data;
 11         void __iomem            *base;
 12 };

There are currently three different places where memory is allocated for
`struct stratix10_clock_data`, including the flex-array `hws` in
`struct clk_hw_onecell_data`:

drivers/clk/socfpga/clk-agilex.c:
469         clk_data = devm_kzalloc(dev, struct_size(clk_data, clk_data.hws,
470                                 num_clks), GFP_KERNEL);

drivers/clk/socfpga/clk-agilex.c:
509         clk_data = devm_kzalloc(dev, struct_size(clk_data, clk_data.hws,
510                                 num_clks), GFP_KERNEL);

drivers/clk/socfpga/clk-s10.c:
400         clk_data = devm_kzalloc(dev, struct_size(clk_data, clk_data.hws,
401                                                  num_clks), GFP_KERNEL);

I'll use just one of them to describe the issue. See below.

Notice that a total of 440 bytes are allocated for flexible-array member
`hws` at line 469:

include/dt-bindings/clock/agilex-clock.h:
 70 #define AGILEX_NUM_CLKS	55

drivers/clk/socfpga/clk-agilex.c:
459         struct stratix10_clock_data *clk_data;
460         void __iomem *base;
...
466
467         num_clks = AGILEX_NUM_CLKS;
468
469         clk_data = devm_kzalloc(dev, struct_size(clk_data, clk_data.hws,
470                                 num_clks), GFP_KERNEL);

`struct_size(clk_data, clk_data.hws, num_clks)`	above translates to
sizeof(struct stratix10_clock_data) + sizeof(struct clk_hw *) * 55 ==
16 + 8 * 55 == 16 + 440
		    ^^^
		     |
	allocated bytes for flex-array `hws`

474         for (i = 0; i < num_clks; i++)
475                 clk_data->clk_data.hws[i] = ERR_PTR(-ENOENT);
476
477         clk_data->base = base;

and then some data is written into both `hws` and `base` objects.

Fix this by placing the declaration of object `clk_data` at the end of
`struct stratix10_clock_data`. Also, add a comment to make it clear
that this object must always be last in the structure.

Fixes: ba7e258425ac ("clk: socfpga: Convert to s10/agilex/n5x to use clk_hw")
Cc: stable@vger.kernel.org
Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
---
 drivers/clk/socfpga/stratix10-clk.h | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/socfpga/stratix10-clk.h b/drivers/clk/socfpga/stratix10-clk.h
index 75234e0783e1..83fe4eb3133c 100644
--- a/drivers/clk/socfpga/stratix10-clk.h
+++ b/drivers/clk/socfpga/stratix10-clk.h
@@ -7,8 +7,10 @@
 #define	__STRATIX10_CLK_H
 
 struct stratix10_clock_data {
-	struct clk_hw_onecell_data	clk_data;
 	void __iomem		*base;
+
+	/* Must be last */
+	struct clk_hw_onecell_data	clk_data;
 };
 
 struct stratix10_pll_clock {
-- 
2.34.1


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

* [PATCH 2/2][next] clk: socfpga: agilex: Add bounds-checking coverage for struct stratix10_clock_data
  2023-10-11 21:31 [PATCH 0/2][next] Fix undefined behavior bug and add bounds-checking coverage Gustavo A. R. Silva
  2023-10-11 21:34 ` [PATCH 1/2][next] clk: socfpga: Fix undefined behavior bug in struct stratix10_clock_data Gustavo A. R. Silva
@ 2023-10-11 21:35 ` Gustavo A. R. Silva
  2023-10-11 21:41   ` Kees Cook
  1 sibling, 1 reply; 7+ messages in thread
From: Gustavo A. R. Silva @ 2023-10-11 21:35 UTC (permalink / raw)
  To: Dinh Nguyen, Michael Turquette, Stephen Boyd
  Cc: Kees Cook, linux-kernel, Gustavo A. R. Silva, linux-hardening

In order to gain the bounds-checking coverage that __counted_by provides
to flexible-array members at run-time via CONFIG_UBSAN_BOUNDS (for array
indexing) and CONFIG_FORTIFY_SOURCE (for strcpy/memcpy-family functions),
we must make sure that the counter member, in this case `num`, is updated
before the first access to the flex-array member, in this case array `hws`.

commit f316cdff8d67 ("clk: Annotate struct clk_hw_onecell_data with
__counted_by") introduced `__counted_by` for `struct clk_hw_onecell_data`
together with changes to relocate some of assignments of counter `num`
before `hws` is accessed:

include/linux/clk-provider.h:
1380 struct clk_hw_onecell_data {
1381         unsigned int num;
1382         struct clk_hw *hws[] __counted_by(num);
1383 };

However, this structure is used as a member in other structs, in this
case in `struct sstratix10_clock_data`:

drivers/clk/socfpga/stratix10-clk.h:
  9 struct stratix10_clock_data {
 10         void __iomem            *base;
 11 
 12         /* Must be last */
 13         struct clk_hw_onecell_data      clk_data;
 14 };

Hence, we need to move the assignments to `clk_data->clk_data.num` after
allocations for `struct stratix10_clock_data` and before accessing the
flexible array `clk_data->clk_data.hws`. And, as assignments for both
`clk_data->clk_data.num` and `clk_data->base` are originally adjacent to
each other, relocate both assignments together.

Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
---
 drivers/clk/socfpga/clk-agilex.c | 12 ++++++------
 drivers/clk/socfpga/clk-s10.c    |  6 +++---
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/clk/socfpga/clk-agilex.c b/drivers/clk/socfpga/clk-agilex.c
index 6b65a74aefa6..8dd94f64756b 100644
--- a/drivers/clk/socfpga/clk-agilex.c
+++ b/drivers/clk/socfpga/clk-agilex.c
@@ -471,12 +471,12 @@ static int agilex_clkmgr_init(struct platform_device *pdev)
 	if (!clk_data)
 		return -ENOMEM;
 
+	clk_data->clk_data.num = num_clks;
+	clk_data->base = base;
+
 	for (i = 0; i < num_clks; i++)
 		clk_data->clk_data.hws[i] = ERR_PTR(-ENOENT);
 
-	clk_data->base = base;
-	clk_data->clk_data.num = num_clks;
-
 	agilex_clk_register_pll(agilex_pll_clks, ARRAY_SIZE(agilex_pll_clks), clk_data);
 
 	agilex_clk_register_c_perip(agilex_main_perip_c_clks,
@@ -511,12 +511,12 @@ static int n5x_clkmgr_init(struct platform_device *pdev)
 	if (!clk_data)
 		return -ENOMEM;
 
-	for (i = 0; i < num_clks; i++)
-		clk_data->clk_data.hws[i] = ERR_PTR(-ENOENT);
-
 	clk_data->base = base;
 	clk_data->clk_data.num = num_clks;
 
+	for (i = 0; i < num_clks; i++)
+		clk_data->clk_data.hws[i] = ERR_PTR(-ENOENT);
+
 	n5x_clk_register_pll(agilex_pll_clks, ARRAY_SIZE(agilex_pll_clks), clk_data);
 
 	n5x_clk_register_c_perip(n5x_main_perip_c_clks,
diff --git a/drivers/clk/socfpga/clk-s10.c b/drivers/clk/socfpga/clk-s10.c
index 3752bd9c103c..b4bf4e2d38e1 100644
--- a/drivers/clk/socfpga/clk-s10.c
+++ b/drivers/clk/socfpga/clk-s10.c
@@ -402,12 +402,12 @@ static int s10_clkmgr_init(struct platform_device *pdev)
 	if (!clk_data)
 		return -ENOMEM;
 
-	for (i = 0; i < num_clks; i++)
-		clk_data->clk_data.hws[i] = ERR_PTR(-ENOENT);
-
 	clk_data->base = base;
 	clk_data->clk_data.num = num_clks;
 
+	for (i = 0; i < num_clks; i++)
+		clk_data->clk_data.hws[i] = ERR_PTR(-ENOENT);
+
 	s10_clk_register_pll(s10_pll_clks, ARRAY_SIZE(s10_pll_clks), clk_data);
 
 	s10_clk_register_c_perip(s10_main_perip_c_clks,
-- 
2.34.1


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

* Re: [PATCH 1/2][next] clk: socfpga: Fix undefined behavior bug in struct stratix10_clock_data
  2023-10-11 21:34 ` [PATCH 1/2][next] clk: socfpga: Fix undefined behavior bug in struct stratix10_clock_data Gustavo A. R. Silva
@ 2023-10-11 21:38   ` Kees Cook
  2023-10-12  1:22     ` Gustavo A. R. Silva
  0 siblings, 1 reply; 7+ messages in thread
From: Kees Cook @ 2023-10-11 21:38 UTC (permalink / raw)
  To: Gustavo A. R. Silva
  Cc: Dinh Nguyen, Michael Turquette, Stephen Boyd, linux-kernel,
	linux-hardening

On Wed, Oct 11, 2023 at 03:34:03PM -0600, Gustavo A. R. Silva wrote:
> `struct clk_hw_onecell_data` is a flexible structure, which means that
> it contains flexible-array member at the bottom, in this case array
> `hws`:
> 
> include/linux/clk-provider.h:
> 1380 struct clk_hw_onecell_data {
> 1381         unsigned int num;
> 1382         struct clk_hw *hws[] __counted_by(num);
> 1383 };
> 
> This could potentially lead to an overwrite of the objects following
> `clk_data` in `struct stratix10_clock_data`, in this case
> `void __iomem *base;` at run-time:
> 
> drivers/clk/socfpga/stratix10-clk.h:
>   9 struct stratix10_clock_data {
>  10         struct clk_hw_onecell_data      clk_data;
>  11         void __iomem            *base;
>  12 };
> 
> There are currently three different places where memory is allocated for
> `struct stratix10_clock_data`, including the flex-array `hws` in
> `struct clk_hw_onecell_data`:
> 
> drivers/clk/socfpga/clk-agilex.c:
> 469         clk_data = devm_kzalloc(dev, struct_size(clk_data, clk_data.hws,
> 470                                 num_clks), GFP_KERNEL);
> 
> drivers/clk/socfpga/clk-agilex.c:
> 509         clk_data = devm_kzalloc(dev, struct_size(clk_data, clk_data.hws,
> 510                                 num_clks), GFP_KERNEL);
> 
> drivers/clk/socfpga/clk-s10.c:
> 400         clk_data = devm_kzalloc(dev, struct_size(clk_data, clk_data.hws,
> 401                                                  num_clks), GFP_KERNEL);
> 
> I'll use just one of them to describe the issue. See below.
> 
> Notice that a total of 440 bytes are allocated for flexible-array member
> `hws` at line 469:
> 
> include/dt-bindings/clock/agilex-clock.h:
>  70 #define AGILEX_NUM_CLKS	55
> 
> drivers/clk/socfpga/clk-agilex.c:
> 459         struct stratix10_clock_data *clk_data;
> 460         void __iomem *base;
> ...
> 466
> 467         num_clks = AGILEX_NUM_CLKS;
> 468
> 469         clk_data = devm_kzalloc(dev, struct_size(clk_data, clk_data.hws,
> 470                                 num_clks), GFP_KERNEL);
> 
> `struct_size(clk_data, clk_data.hws, num_clks)`	above translates to
> sizeof(struct stratix10_clock_data) + sizeof(struct clk_hw *) * 55 ==
> 16 + 8 * 55 == 16 + 440
> 		    ^^^
> 		     |
> 	allocated bytes for flex-array `hws`
> 
> 474         for (i = 0; i < num_clks; i++)
> 475                 clk_data->clk_data.hws[i] = ERR_PTR(-ENOENT);
> 476
> 477         clk_data->base = base;
> 
> and then some data is written into both `hws` and `base` objects.
> 
> Fix this by placing the declaration of object `clk_data` at the end of
> `struct stratix10_clock_data`. Also, add a comment to make it clear
> that this object must always be last in the structure.
> 
> Fixes: ba7e258425ac ("clk: socfpga: Convert to s10/agilex/n5x to use clk_hw")
> Cc: stable@vger.kernel.org
> Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>

Nice find!

Reviewed-by: Kees Cook <keescook@chromium.org>

-- 
Kees Cook

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

* Re: [PATCH 2/2][next] clk: socfpga: agilex: Add bounds-checking coverage for struct stratix10_clock_data
  2023-10-11 21:35 ` [PATCH 2/2][next] clk: socfpga: agilex: Add bounds-checking coverage for " Gustavo A. R. Silva
@ 2023-10-11 21:41   ` Kees Cook
  2023-10-12  1:22     ` Gustavo A. R. Silva
  0 siblings, 1 reply; 7+ messages in thread
From: Kees Cook @ 2023-10-11 21:41 UTC (permalink / raw)
  To: Gustavo A. R. Silva
  Cc: Dinh Nguyen, Michael Turquette, Stephen Boyd, linux-kernel,
	linux-hardening

On Wed, Oct 11, 2023 at 03:35:26PM -0600, Gustavo A. R. Silva wrote:
> In order to gain the bounds-checking coverage that __counted_by provides
> to flexible-array members at run-time via CONFIG_UBSAN_BOUNDS (for array
> indexing) and CONFIG_FORTIFY_SOURCE (for strcpy/memcpy-family functions),
> we must make sure that the counter member, in this case `num`, is updated
> before the first access to the flex-array member, in this case array `hws`.
> 
> commit f316cdff8d67 ("clk: Annotate struct clk_hw_onecell_data with
> __counted_by") introduced `__counted_by` for `struct clk_hw_onecell_data`
> together with changes to relocate some of assignments of counter `num`
> before `hws` is accessed:
> 
> include/linux/clk-provider.h:
> 1380 struct clk_hw_onecell_data {
> 1381         unsigned int num;
> 1382         struct clk_hw *hws[] __counted_by(num);
> 1383 };
> 
> However, this structure is used as a member in other structs, in this
> case in `struct sstratix10_clock_data`:
> 
> drivers/clk/socfpga/stratix10-clk.h:
>   9 struct stratix10_clock_data {
>  10         void __iomem            *base;
>  11 
>  12         /* Must be last */
>  13         struct clk_hw_onecell_data      clk_data;
>  14 };
> 
> Hence, we need to move the assignments to `clk_data->clk_data.num` after
> allocations for `struct stratix10_clock_data` and before accessing the
> flexible array `clk_data->clk_data.hws`. And, as assignments for both
> `clk_data->clk_data.num` and `clk_data->base` are originally adjacent to
> each other, relocate both assignments together.
> 
> Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>

Yeah, ew. That's super tricky. Nice find.

Reviewed-by: Kees Cook <keescook@chromium.org>

-- 
Kees Cook

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

* Re: [PATCH 2/2][next] clk: socfpga: agilex: Add bounds-checking coverage for struct stratix10_clock_data
  2023-10-11 21:41   ` Kees Cook
@ 2023-10-12  1:22     ` Gustavo A. R. Silva
  0 siblings, 0 replies; 7+ messages in thread
From: Gustavo A. R. Silva @ 2023-10-12  1:22 UTC (permalink / raw)
  To: Kees Cook, Gustavo A. R. Silva
  Cc: Dinh Nguyen, Michael Turquette, Stephen Boyd, linux-kernel,
	linux-hardening




>> Hence, we need to move the assignments to `clk_data->clk_data.num` after
>> allocations for `struct stratix10_clock_data` and before accessing the
>> flexible array `clk_data->clk_data.hws`. And, as assignments for both
>> `clk_data->clk_data.num` and `clk_data->base` are originally adjacent to
>> each other, relocate both assignments together.
>>
>> Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
> 
> Yeah, ew. That's super tricky. Nice find.

Indeed. D:

> 
> Reviewed-by: Kees Cook <keescook@chromium.org>


Thanks!
--
Gustavo


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

* Re: [PATCH 1/2][next] clk: socfpga: Fix undefined behavior bug in struct stratix10_clock_data
  2023-10-11 21:38   ` Kees Cook
@ 2023-10-12  1:22     ` Gustavo A. R. Silva
  0 siblings, 0 replies; 7+ messages in thread
From: Gustavo A. R. Silva @ 2023-10-12  1:22 UTC (permalink / raw)
  To: Kees Cook, Gustavo A. R. Silva
  Cc: Dinh Nguyen, Michael Turquette, Stephen Boyd, linux-kernel,
	linux-hardening


>> Fixes: ba7e258425ac ("clk: socfpga: Convert to s10/agilex/n5x to use clk_hw")
>> Cc: stable@vger.kernel.org
>> Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
> 
> Nice find!

:D

> 
> Reviewed-by: Kees Cook <keescook@chromium.org>
> 

Thanks!
--
Gustavo

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

end of thread, other threads:[~2023-10-12  1:22 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-10-11 21:31 [PATCH 0/2][next] Fix undefined behavior bug and add bounds-checking coverage Gustavo A. R. Silva
2023-10-11 21:34 ` [PATCH 1/2][next] clk: socfpga: Fix undefined behavior bug in struct stratix10_clock_data Gustavo A. R. Silva
2023-10-11 21:38   ` Kees Cook
2023-10-12  1:22     ` Gustavo A. R. Silva
2023-10-11 21:35 ` [PATCH 2/2][next] clk: socfpga: agilex: Add bounds-checking coverage for " Gustavo A. R. Silva
2023-10-11 21:41   ` Kees Cook
2023-10-12  1:22     ` Gustavo A. R. Silva

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.