Message ID | 20210818060533.3569517-13-keescook@chromium.org |
---|---|
State | New |
Headers | show |
Series | Introduce strict memcpy() bounds checking | expand |
On Wed, Aug 18, 2021 at 8:08 AM Kees Cook <keescook@chromium.org> wrote: > > In preparation for FORTIFY_SOURCE performing compile-time and run-time > field bounds checking for memcpy(), avoid intentionally writing across > neighboring fields. > > Use struct_group() in struct art around members weight, and ac[0-9]_max, > so they can be referenced together. This will allow memcpy() and sizeof() > to more easily reason about sizes, improve readability, and avoid future > warnings about writing beyond the end of weight. > > "pahole" shows no size nor member offset changes to struct art. > "objdump -d" shows no meaningful object code changes (i.e. only source > line number induced differences). > > Cc: Zhang Rui <rui.zhang@intel.com> > Cc: Daniel Lezcano <daniel.lezcano@linaro.org> > Cc: Amit Kucheria <amitk@kernel.org> > Cc: linux-pm@vger.kernel.org > Signed-off-by: Kees Cook <keescook@chromium.org> Rui, Srinivas, any comments here? > --- > .../intel/int340x_thermal/acpi_thermal_rel.c | 5 +- > .../intel/int340x_thermal/acpi_thermal_rel.h | 48 ++++++++++--------- > 2 files changed, 29 insertions(+), 24 deletions(-) > > diff --git a/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.c b/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.c > index a478cff8162a..e90690a234c4 100644 > --- a/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.c > +++ b/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.c > @@ -250,8 +250,9 @@ static int fill_art(char __user *ubuf) > get_single_name(arts[i].source, art_user[i].source_device); > get_single_name(arts[i].target, art_user[i].target_device); > /* copy the rest int data in addition to source and target */ > - memcpy(&art_user[i].weight, &arts[i].weight, > - sizeof(u64) * (ACPI_NR_ART_ELEMENTS - 2)); > + BUILD_BUG_ON(sizeof(art_user[i].data) != > + sizeof(u64) * (ACPI_NR_ART_ELEMENTS - 2)); > + memcpy(&art_user[i].data, &arts[i].data, sizeof(art_user[i].data)); > } > > if (copy_to_user(ubuf, art_user, art_len)) > diff --git a/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.h b/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.h > index 58822575fd54..78d942477035 100644 > --- a/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.h > +++ b/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.h > @@ -17,17 +17,19 @@ > struct art { > acpi_handle source; > acpi_handle target; > - u64 weight; > - u64 ac0_max; > - u64 ac1_max; > - u64 ac2_max; > - u64 ac3_max; > - u64 ac4_max; > - u64 ac5_max; > - u64 ac6_max; > - u64 ac7_max; > - u64 ac8_max; > - u64 ac9_max; > + struct_group(data, > + u64 weight; > + u64 ac0_max; > + u64 ac1_max; > + u64 ac2_max; > + u64 ac3_max; > + u64 ac4_max; > + u64 ac5_max; > + u64 ac6_max; > + u64 ac7_max; > + u64 ac8_max; > + u64 ac9_max; > + ); > } __packed; > > struct trt { > @@ -47,17 +49,19 @@ union art_object { > struct { > char source_device[8]; /* ACPI single name */ > char target_device[8]; /* ACPI single name */ > - u64 weight; > - u64 ac0_max_level; > - u64 ac1_max_level; > - u64 ac2_max_level; > - u64 ac3_max_level; > - u64 ac4_max_level; > - u64 ac5_max_level; > - u64 ac6_max_level; > - u64 ac7_max_level; > - u64 ac8_max_level; > - u64 ac9_max_level; > + struct_group(data, > + u64 weight; > + u64 ac0_max_level; > + u64 ac1_max_level; > + u64 ac2_max_level; > + u64 ac3_max_level; > + u64 ac4_max_level; > + u64 ac5_max_level; > + u64 ac6_max_level; > + u64 ac7_max_level; > + u64 ac8_max_level; > + u64 ac9_max_level; > + ); > }; > u64 __data[ACPI_NR_ART_ELEMENTS]; > }; > -- > 2.30.2 >
On Tue, 2021-11-23 at 14:19 +0100, Rafael J. Wysocki wrote: > On Wed, Aug 18, 2021 at 8:08 AM Kees Cook <keescook@chromium.org> > wrote: > > > > In preparation for FORTIFY_SOURCE performing compile-time and run- > > time > > field bounds checking for memcpy(), avoid intentionally writing > > across > > neighboring fields. > > > > Use struct_group() in struct art around members weight, and ac[0- > > 9]_max, > > so they can be referenced together. This will allow memcpy() and > > sizeof() > > to more easily reason about sizes, improve readability, and avoid > > future > > warnings about writing beyond the end of weight. > > > > "pahole" shows no size nor member offset changes to struct art. > > "objdump -d" shows no meaningful object code changes (i.e. only > > source > > line number induced differences). > > > > Cc: Zhang Rui <rui.zhang@intel.com> > > Cc: Daniel Lezcano <daniel.lezcano@linaro.org> > > Cc: Amit Kucheria <amitk@kernel.org> > > Cc: linux-pm@vger.kernel.org > > Signed-off-by: Kees Cook <keescook@chromium.org> > > Rui, Srinivas, any comments here? Looks good. Reviewed-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> Thanks, Srinivas > > > --- > > .../intel/int340x_thermal/acpi_thermal_rel.c | 5 +- > > .../intel/int340x_thermal/acpi_thermal_rel.h | 48 ++++++++++------- > > -- > > 2 files changed, 29 insertions(+), 24 deletions(-) > > > > diff --git a/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.c > > b/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.c > > index a478cff8162a..e90690a234c4 100644 > > --- a/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.c > > +++ b/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.c > > @@ -250,8 +250,9 @@ static int fill_art(char __user *ubuf) > > get_single_name(arts[i].source, > > art_user[i].source_device); > > get_single_name(arts[i].target, > > art_user[i].target_device); > > /* copy the rest int data in addition to source and > > target */ > > - memcpy(&art_user[i].weight, &arts[i].weight, > > - sizeof(u64) * (ACPI_NR_ART_ELEMENTS - 2)); > > + BUILD_BUG_ON(sizeof(art_user[i].data) != > > + sizeof(u64) * (ACPI_NR_ART_ELEMENTS - > > 2)); > > + memcpy(&art_user[i].data, &arts[i].data, > > sizeof(art_user[i].data)); > > } > > > > if (copy_to_user(ubuf, art_user, art_len)) > > diff --git a/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.h > > b/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.h > > index 58822575fd54..78d942477035 100644 > > --- a/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.h > > +++ b/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.h > > @@ -17,17 +17,19 @@ > > struct art { > > acpi_handle source; > > acpi_handle target; > > - u64 weight; > > - u64 ac0_max; > > - u64 ac1_max; > > - u64 ac2_max; > > - u64 ac3_max; > > - u64 ac4_max; > > - u64 ac5_max; > > - u64 ac6_max; > > - u64 ac7_max; > > - u64 ac8_max; > > - u64 ac9_max; > > + struct_group(data, > > + u64 weight; > > + u64 ac0_max; > > + u64 ac1_max; > > + u64 ac2_max; > > + u64 ac3_max; > > + u64 ac4_max; > > + u64 ac5_max; > > + u64 ac6_max; > > + u64 ac7_max; > > + u64 ac8_max; > > + u64 ac9_max; > > + ); > > } __packed; > > > > struct trt { > > @@ -47,17 +49,19 @@ union art_object { > > struct { > > char source_device[8]; /* ACPI single name */ > > char target_device[8]; /* ACPI single name */ > > - u64 weight; > > - u64 ac0_max_level; > > - u64 ac1_max_level; > > - u64 ac2_max_level; > > - u64 ac3_max_level; > > - u64 ac4_max_level; > > - u64 ac5_max_level; > > - u64 ac6_max_level; > > - u64 ac7_max_level; > > - u64 ac8_max_level; > > - u64 ac9_max_level; > > + struct_group(data, > > + u64 weight; > > + u64 ac0_max_level; > > + u64 ac1_max_level; > > + u64 ac2_max_level; > > + u64 ac3_max_level; > > + u64 ac4_max_level; > > + u64 ac5_max_level; > > + u64 ac6_max_level; > > + u64 ac7_max_level; > > + u64 ac8_max_level; > > + u64 ac9_max_level; > > + ); > > }; > > u64 __data[ACPI_NR_ART_ELEMENTS]; > > }; > > -- > > 2.30.2 > >
On Wed, Nov 24, 2021 at 12:53 AM Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> wrote: > > On Tue, 2021-11-23 at 14:19 +0100, Rafael J. Wysocki wrote: > > On Wed, Aug 18, 2021 at 8:08 AM Kees Cook <keescook@chromium.org> > > wrote: > > > > > > In preparation for FORTIFY_SOURCE performing compile-time and run- > > > time > > > field bounds checking for memcpy(), avoid intentionally writing > > > across > > > neighboring fields. > > > > > > Use struct_group() in struct art around members weight, and ac[0- > > > 9]_max, > > > so they can be referenced together. This will allow memcpy() and > > > sizeof() > > > to more easily reason about sizes, improve readability, and avoid > > > future > > > warnings about writing beyond the end of weight. > > > > > > "pahole" shows no size nor member offset changes to struct art. > > > "objdump -d" shows no meaningful object code changes (i.e. only > > > source > > > line number induced differences). > > > > > > Cc: Zhang Rui <rui.zhang@intel.com> > > > Cc: Daniel Lezcano <daniel.lezcano@linaro.org> > > > Cc: Amit Kucheria <amitk@kernel.org> > > > Cc: linux-pm@vger.kernel.org > > > Signed-off-by: Kees Cook <keescook@chromium.org> > > > > Rui, Srinivas, any comments here? > Looks good. > Reviewed-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> Applied as 5.17 material, thank you!
diff --git a/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.c b/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.c index a478cff8162a..e90690a234c4 100644 --- a/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.c +++ b/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.c @@ -250,8 +250,9 @@ static int fill_art(char __user *ubuf) get_single_name(arts[i].source, art_user[i].source_device); get_single_name(arts[i].target, art_user[i].target_device); /* copy the rest int data in addition to source and target */ - memcpy(&art_user[i].weight, &arts[i].weight, - sizeof(u64) * (ACPI_NR_ART_ELEMENTS - 2)); + BUILD_BUG_ON(sizeof(art_user[i].data) != + sizeof(u64) * (ACPI_NR_ART_ELEMENTS - 2)); + memcpy(&art_user[i].data, &arts[i].data, sizeof(art_user[i].data)); } if (copy_to_user(ubuf, art_user, art_len)) diff --git a/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.h b/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.h index 58822575fd54..78d942477035 100644 --- a/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.h +++ b/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.h @@ -17,17 +17,19 @@ struct art { acpi_handle source; acpi_handle target; - u64 weight; - u64 ac0_max; - u64 ac1_max; - u64 ac2_max; - u64 ac3_max; - u64 ac4_max; - u64 ac5_max; - u64 ac6_max; - u64 ac7_max; - u64 ac8_max; - u64 ac9_max; + struct_group(data, + u64 weight; + u64 ac0_max; + u64 ac1_max; + u64 ac2_max; + u64 ac3_max; + u64 ac4_max; + u64 ac5_max; + u64 ac6_max; + u64 ac7_max; + u64 ac8_max; + u64 ac9_max; + ); } __packed; struct trt { @@ -47,17 +49,19 @@ union art_object { struct { char source_device[8]; /* ACPI single name */ char target_device[8]; /* ACPI single name */ - u64 weight; - u64 ac0_max_level; - u64 ac1_max_level; - u64 ac2_max_level; - u64 ac3_max_level; - u64 ac4_max_level; - u64 ac5_max_level; - u64 ac6_max_level; - u64 ac7_max_level; - u64 ac8_max_level; - u64 ac9_max_level; + struct_group(data, + u64 weight; + u64 ac0_max_level; + u64 ac1_max_level; + u64 ac2_max_level; + u64 ac3_max_level; + u64 ac4_max_level; + u64 ac5_max_level; + u64 ac6_max_level; + u64 ac7_max_level; + u64 ac8_max_level; + u64 ac9_max_level; + ); }; u64 __data[ACPI_NR_ART_ELEMENTS]; };
In preparation for FORTIFY_SOURCE performing compile-time and run-time field bounds checking for memcpy(), avoid intentionally writing across neighboring fields. Use struct_group() in struct art around members weight, and ac[0-9]_max, so they can be referenced together. This will allow memcpy() and sizeof() to more easily reason about sizes, improve readability, and avoid future warnings about writing beyond the end of weight. "pahole" shows no size nor member offset changes to struct art. "objdump -d" shows no meaningful object code changes (i.e. only source line number induced differences). Cc: Zhang Rui <rui.zhang@intel.com> Cc: Daniel Lezcano <daniel.lezcano@linaro.org> Cc: Amit Kucheria <amitk@kernel.org> Cc: linux-pm@vger.kernel.org Signed-off-by: Kees Cook <keescook@chromium.org> --- .../intel/int340x_thermal/acpi_thermal_rel.c | 5 +- .../intel/int340x_thermal/acpi_thermal_rel.h | 48 ++++++++++--------- 2 files changed, 29 insertions(+), 24 deletions(-)