Message ID | 20230406000212.3442647-6-keescook@chromium.org (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | fortify: Add KUnit tests for runtime overflows | expand |
On Thu, Apr 6, 2023 at 3:02 AM Kees Cook <keescook@chromium.org> wrote: > > In preparation for KUnit testing and further improvements in fortify > failure reporting, split out the report and encode the function and > access failure (read or write overflow) into a single int argument. This > mainly ends up saving some space in the data segment. For a defconfig > with FORTIFY_SOURCE enabled: > > $ size gcc/vmlinux.before gcc/vmlinux.after > text data bss dec hex filename > 26132309 9760658 2195460 38088427 2452eeb gcc/vmlinux.before > 26132386 9748382 2195460 38076228 244ff44 gcc/vmlinux.after ... > + const char *name; > + const bool write = !!(reason & 0x1); Perhaps define that as FORTIFY_READ_WRITE BIT(0) FORTIFY_FUNC_SHIFT 1 const bool write = reason & FORTIFY_READ_WRITE; // and note no need for !! part switch (reason >> FORTIFY_FUNC_SHIFT) { > + switch (reason >> 1) { > + case FORTIFY_FUNC_strncpy: > + name = "strncpy"; > + break; > + case FORTIFY_FUNC_strnlen: > + name = "strnlen"; > + break; > + case FORTIFY_FUNC_strlen: > + name = "strlen"; > + break; > + case FORTIFY_FUNC_strlcpy: > + name = "strlcpy"; > + break; > + case FORTIFY_FUNC_strscpy: > + name = "strscpy"; > + break; > + case FORTIFY_FUNC_strlcat: > + name = "strlcat"; > + break; > + case FORTIFY_FUNC_strcat: > + name = "strcat"; > + break; > + case FORTIFY_FUNC_strncat: > + name = "strncat"; > + break; > + case FORTIFY_FUNC_memset: > + name = "memset"; > + break; > + case FORTIFY_FUNC_memcpy: > + name = "memcpy"; > + break; > + case FORTIFY_FUNC_memmove: > + name = "memmove"; > + break; > + case FORTIFY_FUNC_memscan: > + name = "memscan"; > + break; > + case FORTIFY_FUNC_memcmp: > + name = "memcmp"; > + break; > + case FORTIFY_FUNC_memchr: > + name = "memchr"; > + break; > + case FORTIFY_FUNC_memchr_inv: > + name = "memchr_inv"; > + break; > + case FORTIFY_FUNC_kmemdup: > + name = "kmemdup"; > + break; > + case FORTIFY_FUNC_strcpy: > + name = "strcpy"; > + break; > + default: > + name = "unknown"; > + } ... > + WARN(1, "%s: detected buffer %s overflow\n", name, write ? "write" : "read"); Using str_read_write() ? Dunno if it's already there or needs to be added. I have some patches to move those str_*() to string_choices.h. We can also prepend yours with those.
Hi Kees, kernel test robot noticed the following build errors: [auto build test ERROR on kees/for-next/hardening] [also build test ERROR on kees/for-next/pstore kees/for-next/kspp akpm-mm/mm-everything linus/master v6.3-rc5 next-20230406] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Kees-Cook/kunit-tool-Enable-CONFIG_FORTIFY_SOURCE-under-UML/20230406-081014 base: https://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/hardening patch link: https://lore.kernel.org/r/20230406000212.3442647-6-keescook%40chromium.org patch subject: [PATCH 6/9] fortify: Split reporting and avoid passing string pointer config: arm-randconfig-r025-20230403 (https://download.01.org/0day-ci/archive/20230406/202304061930.4Au0PASm-lkp@intel.com/config) compiler: clang version 17.0.0 (https://github.com/llvm/llvm-project 67409911353323ca5edf2049ef0df54132fa1ca7) reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # install arm cross compiling tool for clang build # apt-get install binutils-arm-linux-gnueabi # https://github.com/intel-lab-lkp/linux/commit/4fd520e6ee549e1ffe8859e26e57ea64b48e78ea git remote add linux-review https://github.com/intel-lab-lkp/linux git fetch --no-tags linux-review Kees-Cook/kunit-tool-Enable-CONFIG_FORTIFY_SOURCE-under-UML/20230406-081014 git checkout 4fd520e6ee549e1ffe8859e26e57ea64b48e78ea # save the config file mkdir build_dir && cp config build_dir/.config COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=arm olddefconfig COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=arm SHELL=/bin/bash If you fix the issue, kindly add following tag where applicable | Reported-by: kernel test robot <lkp@intel.com> | Link: https://lore.kernel.org/oe-kbuild-all/202304061930.4Au0PASm-lkp@intel.com/ All errors (new ones prefixed by >>): >> ld.lld: error: undefined symbol: __fortify_panic >>> referenced by fortify-string.h:208 (include/linux/fortify-string.h:208) >>> arch/arm/boot/compressed/fdt_ro.o:(fdt_stringlist_count) >>> referenced by fortify-string.h:208 (include/linux/fortify-string.h:208) >>> arch/arm/boot/compressed/fdt_ro.o:(fdt_stringlist_search) >>> referenced by fortify-string.h:208 (include/linux/fortify-string.h:208) >>> arch/arm/boot/compressed/fdt_ro.o:(fdt_stringlist_get)
On Thu, Apr 6, 2023 at 2:02 AM Kees Cook <keescook@chromium.org> wrote: > > +void __fortify_report(u8 reason); > +void __fortify_panic(u8 reason) __cold __noreturn; (snip) > +void __fortify_report(u8 reason) (snip) > +void __fortify_panic(const u8 reason) I am curious: for some reason (no pun intended :) the `reason`s above are not `const` except this one, but then in a later patch they become `const` (including the declarations). So perhaps make everything `const` when they are introduced? Or is there some other reason? (e.g. I saw one patch that moved a function, so there it seemed to make sense to keep things as they are to make the copy 1:1). Cheers, Miguel
From: Kees Cook <keescook@chromium.org> Date: Wed, 5 Apr 2023 17:02:05 -0700 > In preparation for KUnit testing and further improvements in fortify > failure reporting, split out the report and encode the function and > access failure (read or write overflow) into a single int argument. This > mainly ends up saving some space in the data segment. For a defconfig > with FORTIFY_SOURCE enabled: > > $ size gcc/vmlinux.before gcc/vmlinux.after > text data bss dec hex filename > 26132309 9760658 2195460 38088427 2452eeb gcc/vmlinux.before > 26132386 9748382 2195460 38076228 244ff44 gcc/vmlinux.after > > Cc: Andy Shevchenko <andy@kernel.org> > Cc: Cezary Rojewski <cezary.rojewski@intel.com> > Cc: Puyou Lu <puyou.lu@gmail.com> > Cc: Mark Brown <broonie@kernel.org> > Cc: linux-hardening@vger.kernel.org > Signed-off-by: Kees Cook <keescook@chromium.org> > --- > include/linux/fortify-string.h | 72 +++++++++++++++++++++++----------- > lib/string_helpers.c | 70 +++++++++++++++++++++++++++++++-- > tools/objtool/check.c | 2 +- > 3 files changed, 118 insertions(+), 26 deletions(-) > > diff --git a/include/linux/fortify-string.h b/include/linux/fortify-string.h > index 41dbd641f55c..6db4052db459 100644 > --- a/include/linux/fortify-string.h > +++ b/include/linux/fortify-string.h > @@ -9,7 +9,34 @@ > #define __FORTIFY_INLINE extern __always_inline __gnu_inline __overloadable > #define __RENAME(x) __asm__(#x) > > -void fortify_panic(const char *name) __noreturn __cold; > +#define fortify_reason(func, write) (((func) << 1) | !!(write)) > + > +#define fortify_panic(func, write) \ > + __fortify_panic(fortify_reason(func, write)) > + > +#define FORTIFY_READ 0 > +#define FORTIFY_WRITE 1 > + > +#define FORTIFY_FUNC_strncpy 0 > +#define FORTIFY_FUNC_strnlen 1 > +#define FORTIFY_FUNC_strlen 2 > +#define FORTIFY_FUNC_strlcpy 3 > +#define FORTIFY_FUNC_strscpy 4 > +#define FORTIFY_FUNC_strlcat 5 > +#define FORTIFY_FUNC_strcat 6 > +#define FORTIFY_FUNC_strncat 7 > +#define FORTIFY_FUNC_memset 8 > +#define FORTIFY_FUNC_memcpy 9 > +#define FORTIFY_FUNC_memmove 10 > +#define FORTIFY_FUNC_memscan 11 > +#define FORTIFY_FUNC_memcmp 12 > +#define FORTIFY_FUNC_memchr 13 > +#define FORTIFY_FUNC_memchr_inv 14 > +#define FORTIFY_FUNC_kmemdup 15 > +#define FORTIFY_FUNC_strcpy 16 enum? > --- a/lib/string_helpers.c > +++ b/lib/string_helpers.c > @@ -1021,10 +1021,74 @@ EXPORT_SYMBOL(__read_overflow2_field); > void __write_overflow_field(size_t avail, size_t wanted) { } > EXPORT_SYMBOL(__write_overflow_field); > > -void fortify_panic(const char *name) > +void __fortify_report(u8 reason) > { > - pr_emerg("detected buffer overflow in %s\n", name); > + const char *name; > + const bool write = !!(reason & 0x1); > + > + switch (reason >> 1) { As already mentioned, I'd use bitfield helpers + couple definitions to not miss something when changing the way it's encoded #define FORTIFY_REASON_DIR(r) FIELD_GET(BIT(0), r) #define FORTIFY_REASON_FUNC(r) FIELD_GET(GENMASK(7, 1), r) (+ set pair) > + case FORTIFY_FUNC_strncpy: > + name = "strncpy"; > + break; > + case FORTIFY_FUNC_strnlen: > + name = "strnlen"; > + break; > + case FORTIFY_FUNC_strlen: > + name = "strlen"; > + break; > + case FORTIFY_FUNC_strlcpy: > + name = "strlcpy"; > + break; > + case FORTIFY_FUNC_strscpy: > + name = "strscpy"; > + break; > + case FORTIFY_FUNC_strlcat: > + name = "strlcat"; > + break; > + case FORTIFY_FUNC_strcat: > + name = "strcat"; > + break; > + case FORTIFY_FUNC_strncat: > + name = "strncat"; > + break; > + case FORTIFY_FUNC_memset: > + name = "memset"; > + break; > + case FORTIFY_FUNC_memcpy: > + name = "memcpy"; > + break; > + case FORTIFY_FUNC_memmove: > + name = "memmove"; > + break; > + case FORTIFY_FUNC_memscan: > + name = "memscan"; > + break; > + case FORTIFY_FUNC_memcmp: > + name = "memcmp"; > + break; > + case FORTIFY_FUNC_memchr: > + name = "memchr"; > + break; > + case FORTIFY_FUNC_memchr_inv: > + name = "memchr_inv"; > + break; > + case FORTIFY_FUNC_kmemdup: > + name = "kmemdup"; > + break; > + case FORTIFY_FUNC_strcpy: > + name = "strcpy"; > + break; > + default: > + name = "unknown"; > + } I know this is far from hotpath, but could we save some object code and do that via O(1) array lookup? Plus some macro to compress things: #define FORTIFY_ENTRY(name) \ [FORTIFY_FUNC_##name] = #name static const char * const fortify_funcs[] = { FORTIFY_ENTRY(strncpy), ... } // array bounds check here if you wish, I wouldn't bother as // we're panicking anyway name = fortify_funcs[reason >> 1]; > + WARN(1, "%s: detected buffer %s overflow\n", name, write ? "write" : "read"); > +} > +EXPORT_SYMBOL(__fortify_report); > + > +void __fortify_panic(const u8 reason) > +{ > + __fortify_report(reason); > BUG(); > } > -EXPORT_SYMBOL(fortify_panic); > +EXPORT_SYMBOL(__fortify_panic); > #endif /* CONFIG_FORTIFY_SOURCE */ Thanks, Olek
On Thu, Apr 06, 2023 at 05:23:54PM +0200, Alexander Lobakin wrote: > From: Kees Cook <keescook@chromium.org> > Date: Wed, 5 Apr 2023 17:02:05 -0700 > > > In preparation for KUnit testing and further improvements in fortify > > failure reporting, split out the report and encode the function and > > access failure (read or write overflow) into a single int argument. This > > mainly ends up saving some space in the data segment. For a defconfig > > with FORTIFY_SOURCE enabled: > > > > $ size gcc/vmlinux.before gcc/vmlinux.after > > text data bss dec hex filename > > 26132309 9760658 2195460 38088427 2452eeb gcc/vmlinux.before > > 26132386 9748382 2195460 38076228 244ff44 gcc/vmlinux.after > > > > Cc: Andy Shevchenko <andy@kernel.org> > > Cc: Cezary Rojewski <cezary.rojewski@intel.com> > > Cc: Puyou Lu <puyou.lu@gmail.com> > > Cc: Mark Brown <broonie@kernel.org> > > Cc: linux-hardening@vger.kernel.org > > Signed-off-by: Kees Cook <keescook@chromium.org> > > --- > > include/linux/fortify-string.h | 72 +++++++++++++++++++++++----------- > > lib/string_helpers.c | 70 +++++++++++++++++++++++++++++++-- > > tools/objtool/check.c | 2 +- > > 3 files changed, 118 insertions(+), 26 deletions(-) > > > > diff --git a/include/linux/fortify-string.h b/include/linux/fortify-string.h > > index 41dbd641f55c..6db4052db459 100644 > > --- a/include/linux/fortify-string.h > > +++ b/include/linux/fortify-string.h > > @@ -9,7 +9,34 @@ > > #define __FORTIFY_INLINE extern __always_inline __gnu_inline __overloadable > > #define __RENAME(x) __asm__(#x) > > > > -void fortify_panic(const char *name) __noreturn __cold; > > +#define fortify_reason(func, write) (((func) << 1) | !!(write)) > > + > > +#define fortify_panic(func, write) \ > > + __fortify_panic(fortify_reason(func, write)) > > + > > +#define FORTIFY_READ 0 > > +#define FORTIFY_WRITE 1 > > + > > +#define FORTIFY_FUNC_strncpy 0 > > +#define FORTIFY_FUNC_strnlen 1 > > +#define FORTIFY_FUNC_strlen 2 > > +#define FORTIFY_FUNC_strlcpy 3 > > +#define FORTIFY_FUNC_strscpy 4 > > +#define FORTIFY_FUNC_strlcat 5 > > +#define FORTIFY_FUNC_strcat 6 > > +#define FORTIFY_FUNC_strncat 7 > > +#define FORTIFY_FUNC_memset 8 > > +#define FORTIFY_FUNC_memcpy 9 > > +#define FORTIFY_FUNC_memmove 10 > > +#define FORTIFY_FUNC_memscan 11 > > +#define FORTIFY_FUNC_memcmp 12 > > +#define FORTIFY_FUNC_memchr 13 > > +#define FORTIFY_FUNC_memchr_inv 14 > > +#define FORTIFY_FUNC_kmemdup 15 > > +#define FORTIFY_FUNC_strcpy 16 > > enum? I opted to avoid an enum due to the binary operations used in "fortify_reason" to collapse it to a u8. It just seemed like more work to put in enums, and then do u8 casts, etc, all for a strictly "internal" set of magic numbers. > > > --- a/lib/string_helpers.c > > +++ b/lib/string_helpers.c > > @@ -1021,10 +1021,74 @@ EXPORT_SYMBOL(__read_overflow2_field); > > void __write_overflow_field(size_t avail, size_t wanted) { } > > EXPORT_SYMBOL(__write_overflow_field); > > > > -void fortify_panic(const char *name) > > +void __fortify_report(u8 reason) > > { > > - pr_emerg("detected buffer overflow in %s\n", name); > > + const char *name; > > + const bool write = !!(reason & 0x1); > > + > > + switch (reason >> 1) { > > As already mentioned, I'd use bitfield helpers + couple definitions to > not miss something when changing the way it's encoded > > #define FORTIFY_REASON_DIR(r) FIELD_GET(BIT(0), r) > #define FORTIFY_REASON_FUNC(r) FIELD_GET(GENMASK(7, 1), r) Yeah, good idea. Thanks for the FIELD_GET examples! > [...] > > + break; > > + default: > > + name = "unknown"; > > + } > > I know this is far from hotpath, but could we save some object code and > do that via O(1) array lookup? Plus some macro to compress things: > > #define FORTIFY_ENTRY(name) \ > [FORTIFY_FUNC_##name] = #name > > static const char * const fortify_funcs[] = { > FORTIFY_ENTRY(strncpy), > ... > } > > // array bounds check here if you wish, I wouldn't bother as > // we're panicking anyway > > name = fortify_funcs[reason >> 1]; Fair enough. I had considered it and then forgot about it for some reason. :)
On Thu, Apr 06, 2023 at 03:44:54PM +0200, Miguel Ojeda wrote: > On Thu, Apr 6, 2023 at 2:02 AM Kees Cook <keescook@chromium.org> wrote: > > > > +void __fortify_report(u8 reason); > > +void __fortify_panic(u8 reason) __cold __noreturn; > > (snip) > > > +void __fortify_report(u8 reason) > > (snip) > > > +void __fortify_panic(const u8 reason) > > I am curious: for some reason (no pun intended :) the `reason`s above > are not `const` except this one, but then in a later patch they become > `const` (including the declarations). > > So perhaps make everything `const` when they are introduced? Or is > there some other reason? (e.g. I saw one patch that moved a function, > so there it seemed to make sense to keep things as they are to make > the copy 1:1). I will adjust it -- this was an artifact of splitting up my patches. Thanks!
On Thu, Apr 06, 2023 at 01:20:52PM +0300, Andy Shevchenko wrote: > On Thu, Apr 6, 2023 at 3:02 AM Kees Cook <keescook@chromium.org> wrote: > > > > In preparation for KUnit testing and further improvements in fortify > > failure reporting, split out the report and encode the function and > > access failure (read or write overflow) into a single int argument. This > > mainly ends up saving some space in the data segment. For a defconfig > > with FORTIFY_SOURCE enabled: > > > > $ size gcc/vmlinux.before gcc/vmlinux.after > > text data bss dec hex filename > > 26132309 9760658 2195460 38088427 2452eeb gcc/vmlinux.before > > 26132386 9748382 2195460 38076228 244ff44 gcc/vmlinux.after > > ... > > > + const char *name; > > + const bool write = !!(reason & 0x1); > > Perhaps define that as > > FORTIFY_READ_WRITE BIT(0) > FORTIFY_FUNC_SHIFT 1 > > const bool write = reason & FORTIFY_READ_WRITE; // and note no need for !! part Yeah, that reads better. The FIELD_GET suggestion down-thread is probably how I'll go. > > switch (reason >> FORTIFY_FUNC_SHIFT) { > > > + switch (reason >> 1) { > > + case FORTIFY_FUNC_strncpy: > > + name = "strncpy"; > > + break; > > + case FORTIFY_FUNC_strnlen: > > + name = "strnlen"; > > + break; > > + case FORTIFY_FUNC_strlen: > > + name = "strlen"; > > + break; > > + case FORTIFY_FUNC_strlcpy: > > + name = "strlcpy"; > > + break; > > + case FORTIFY_FUNC_strscpy: > > + name = "strscpy"; > > + break; > > + case FORTIFY_FUNC_strlcat: > > + name = "strlcat"; > > + break; > > + case FORTIFY_FUNC_strcat: > > + name = "strcat"; > > + break; > > + case FORTIFY_FUNC_strncat: > > + name = "strncat"; > > + break; > > + case FORTIFY_FUNC_memset: > > + name = "memset"; > > + break; > > + case FORTIFY_FUNC_memcpy: > > + name = "memcpy"; > > + break; > > + case FORTIFY_FUNC_memmove: > > + name = "memmove"; > > + break; > > + case FORTIFY_FUNC_memscan: > > + name = "memscan"; > > + break; > > + case FORTIFY_FUNC_memcmp: > > + name = "memcmp"; > > + break; > > + case FORTIFY_FUNC_memchr: > > + name = "memchr"; > > + break; > > + case FORTIFY_FUNC_memchr_inv: > > + name = "memchr_inv"; > > + break; > > + case FORTIFY_FUNC_kmemdup: > > + name = "kmemdup"; > > + break; > > + case FORTIFY_FUNC_strcpy: > > + name = "strcpy"; > > + break; > > + default: > > + name = "unknown"; > > + } > > ... > > > + WARN(1, "%s: detected buffer %s overflow\n", name, write ? "write" : "read"); > > Using str_read_write() ? > > Dunno if it's already there or needs to be added. I have some patches > to move those str_*() to string_choices.h. We can also prepend yours > with those. Oh! Hah. I totally forgot about str_read_write. :) I will use that.
On Fri, Apr 7, 2023 at 1:57 AM Kees Cook <keescook@chromium.org> wrote: > On Thu, Apr 06, 2023 at 01:20:52PM +0300, Andy Shevchenko wrote: > > On Thu, Apr 6, 2023 at 3:02 AM Kees Cook <keescook@chromium.org> wrote: ... > > > + WARN(1, "%s: detected buffer %s overflow\n", name, write ? "write" : "read"); > > > > Using str_read_write() ? > > > > Dunno if it's already there or needs to be added. I have some patches > > to move those str_*() to string_choices.h. We can also prepend yours > > with those. > > Oh! Hah. I totally forgot about str_read_write. :) I will use that. Btw, makes sense to add #define str_write_read(v) str_read_write(!(v)) to the header, so we won't use negation in the parameter for better readability.
Hi Kees, kernel test robot noticed the following build warnings: [auto build test WARNING on kees/for-next/hardening] [also build test WARNING on kees/for-next/pstore kees/for-next/kspp akpm-mm/mm-everything linus/master v6.3-rc5 next-20230406] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Kees-Cook/kunit-tool-Enable-CONFIG_FORTIFY_SOURCE-under-UML/20230406-081014 base: https://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/hardening patch link: https://lore.kernel.org/r/20230406000212.3442647-6-keescook%40chromium.org patch subject: [PATCH 6/9] fortify: Split reporting and avoid passing string pointer config: arm64-randconfig-s053-20230406 (https://download.01.org/0day-ci/archive/20230407/202304071824.648116sH-lkp@intel.com/config) compiler: aarch64-linux-gcc (GCC) 12.1.0 reproduce: wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # apt-get install sparse # sparse version: v0.6.4-39-gce1a6720-dirty # https://github.com/intel-lab-lkp/linux/commit/4fd520e6ee549e1ffe8859e26e57ea64b48e78ea git remote add linux-review https://github.com/intel-lab-lkp/linux git fetch --no-tags linux-review Kees-Cook/kunit-tool-Enable-CONFIG_FORTIFY_SOURCE-under-UML/20230406-081014 git checkout 4fd520e6ee549e1ffe8859e26e57ea64b48e78ea # save the config file mkdir build_dir && cp config build_dir/.config COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=arm64 olddefconfig COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=arm64 SHELL=/bin/bash If you fix the issue, kindly add following tag where applicable | Reported-by: kernel test robot <lkp@intel.com> | Link: https://lore.kernel.org/oe-kbuild-all/202304071824.648116sH-lkp@intel.com/ sparse warnings: (new ones prefixed by >>) lib/string_helpers.c:1030:14: sparse: sparse: undefined identifier 'FORTIFY_FUNC_strncpy' lib/string_helpers.c:1033:14: sparse: sparse: undefined identifier 'FORTIFY_FUNC_strnlen' lib/string_helpers.c:1036:14: sparse: sparse: undefined identifier 'FORTIFY_FUNC_strlen' lib/string_helpers.c:1039:14: sparse: sparse: undefined identifier 'FORTIFY_FUNC_strlcpy' lib/string_helpers.c:1042:14: sparse: sparse: undefined identifier 'FORTIFY_FUNC_strscpy' lib/string_helpers.c:1045:14: sparse: sparse: undefined identifier 'FORTIFY_FUNC_strlcat' lib/string_helpers.c:1048:14: sparse: sparse: undefined identifier 'FORTIFY_FUNC_strcat' lib/string_helpers.c:1051:14: sparse: sparse: undefined identifier 'FORTIFY_FUNC_strncat' lib/string_helpers.c:1054:14: sparse: sparse: undefined identifier 'FORTIFY_FUNC_memset' lib/string_helpers.c:1057:14: sparse: sparse: undefined identifier 'FORTIFY_FUNC_memcpy' lib/string_helpers.c:1060:14: sparse: sparse: undefined identifier 'FORTIFY_FUNC_memmove' lib/string_helpers.c:1063:14: sparse: sparse: undefined identifier 'FORTIFY_FUNC_memscan' lib/string_helpers.c:1066:14: sparse: sparse: undefined identifier 'FORTIFY_FUNC_memcmp' lib/string_helpers.c:1069:14: sparse: sparse: undefined identifier 'FORTIFY_FUNC_memchr' lib/string_helpers.c:1072:14: sparse: sparse: undefined identifier 'FORTIFY_FUNC_memchr_inv' lib/string_helpers.c:1075:14: sparse: sparse: undefined identifier 'FORTIFY_FUNC_kmemdup' lib/string_helpers.c:1078:14: sparse: sparse: undefined identifier 'FORTIFY_FUNC_strcpy' >> lib/string_helpers.c:1030:14: sparse: sparse: incompatible types for 'case' statement lib/string_helpers.c:1033:14: sparse: sparse: incompatible types for 'case' statement lib/string_helpers.c:1036:14: sparse: sparse: incompatible types for 'case' statement lib/string_helpers.c:1039:14: sparse: sparse: incompatible types for 'case' statement lib/string_helpers.c:1042:14: sparse: sparse: incompatible types for 'case' statement lib/string_helpers.c:1045:14: sparse: sparse: incompatible types for 'case' statement lib/string_helpers.c:1048:14: sparse: sparse: incompatible types for 'case' statement lib/string_helpers.c:1051:14: sparse: sparse: incompatible types for 'case' statement lib/string_helpers.c:1054:14: sparse: sparse: incompatible types for 'case' statement lib/string_helpers.c:1057:14: sparse: sparse: incompatible types for 'case' statement lib/string_helpers.c:1060:14: sparse: sparse: incompatible types for 'case' statement lib/string_helpers.c:1063:14: sparse: sparse: incompatible types for 'case' statement lib/string_helpers.c:1066:14: sparse: sparse: incompatible types for 'case' statement lib/string_helpers.c:1069:14: sparse: sparse: incompatible types for 'case' statement lib/string_helpers.c:1072:14: sparse: sparse: incompatible types for 'case' statement lib/string_helpers.c:1075:14: sparse: sparse: incompatible types for 'case' statement lib/string_helpers.c:1078:14: sparse: sparse: incompatible types for 'case' statement lib/string_helpers.c:1030:14: sparse: sparse: Expected constant expression in case statement lib/string_helpers.c:1033:14: sparse: sparse: Expected constant expression in case statement lib/string_helpers.c:1036:14: sparse: sparse: Expected constant expression in case statement lib/string_helpers.c:1039:14: sparse: sparse: Expected constant expression in case statement lib/string_helpers.c:1042:14: sparse: sparse: Expected constant expression in case statement lib/string_helpers.c:1045:14: sparse: sparse: Expected constant expression in case statement lib/string_helpers.c:1048:14: sparse: sparse: Expected constant expression in case statement lib/string_helpers.c:1051:14: sparse: sparse: Expected constant expression in case statement lib/string_helpers.c:1054:14: sparse: sparse: Expected constant expression in case statement lib/string_helpers.c:1057:14: sparse: sparse: Expected constant expression in case statement lib/string_helpers.c:1060:14: sparse: sparse: Expected constant expression in case statement lib/string_helpers.c:1063:14: sparse: sparse: Expected constant expression in case statement lib/string_helpers.c:1066:14: sparse: sparse: Expected constant expression in case statement lib/string_helpers.c:1069:14: sparse: sparse: Expected constant expression in case statement lib/string_helpers.c:1072:14: sparse: sparse: Expected constant expression in case statement lib/string_helpers.c:1075:14: sparse: sparse: Expected constant expression in case statement lib/string_helpers.c:1078:14: sparse: sparse: Expected constant expression in case statement vim +/case +1030 lib/string_helpers.c 1023 1024 void __fortify_report(u8 reason) 1025 { 1026 const char *name; 1027 const bool write = !!(reason & 0x1); 1028 1029 switch (reason >> 1) { > 1030 case FORTIFY_FUNC_strncpy: 1031 name = "strncpy"; 1032 break; 1033 case FORTIFY_FUNC_strnlen: 1034 name = "strnlen"; 1035 break; 1036 case FORTIFY_FUNC_strlen: 1037 name = "strlen"; 1038 break; 1039 case FORTIFY_FUNC_strlcpy: 1040 name = "strlcpy"; 1041 break; 1042 case FORTIFY_FUNC_strscpy: 1043 name = "strscpy"; 1044 break; 1045 case FORTIFY_FUNC_strlcat: 1046 name = "strlcat"; 1047 break; 1048 case FORTIFY_FUNC_strcat: 1049 name = "strcat"; 1050 break; 1051 case FORTIFY_FUNC_strncat: 1052 name = "strncat"; 1053 break; > 1054 case FORTIFY_FUNC_memset: 1055 name = "memset"; 1056 break; 1057 case FORTIFY_FUNC_memcpy: 1058 name = "memcpy"; 1059 break; 1060 case FORTIFY_FUNC_memmove: 1061 name = "memmove"; 1062 break; 1063 case FORTIFY_FUNC_memscan: 1064 name = "memscan"; 1065 break; 1066 case FORTIFY_FUNC_memcmp: 1067 name = "memcmp"; 1068 break; 1069 case FORTIFY_FUNC_memchr: 1070 name = "memchr"; 1071 break; 1072 case FORTIFY_FUNC_memchr_inv: 1073 name = "memchr_inv"; 1074 break; 1075 case FORTIFY_FUNC_kmemdup: 1076 name = "kmemdup"; 1077 break; 1078 case FORTIFY_FUNC_strcpy: 1079 name = "strcpy"; 1080 break; 1081 default: 1082 name = "unknown"; 1083 } 1084 WARN(1, "%s: detected buffer %s overflow\n", name, write ? "write" : "read"); 1085 } 1086 EXPORT_SYMBOL(__fortify_report); 1087
On April 7, 2023 1:34:41 AM PDT, Andy Shevchenko <andy.shevchenko@gmail.com> wrote: >On Fri, Apr 7, 2023 at 1:57 AM Kees Cook <keescook@chromium.org> wrote: >> On Thu, Apr 06, 2023 at 01:20:52PM +0300, Andy Shevchenko wrote: >> > On Thu, Apr 6, 2023 at 3:02 AM Kees Cook <keescook@chromium.org> wrote: > >... > >> > > + WARN(1, "%s: detected buffer %s overflow\n", name, write ? "write" : "read"); >> > >> > Using str_read_write() ? >> > >> > Dunno if it's already there or needs to be added. I have some patches >> > to move those str_*() to string_choices.h. We can also prepend yours >> > with those. >> >> Oh! Hah. I totally forgot about str_read_write. :) I will use that. > >Btw, makes sense to add > > #define str_write_read(v) str_read_write(!(v)) > >to the header, so we won't use negation in the parameter for better readability. I ended up not going this far because the use of str_read_write() gets removed again in the last patch in the series.
On Thu, Apr 6, 2023, at 13:19, kernel test robot wrote: > If you fix the issue, kindly add following tag where applicable > | Reported-by: kernel test robot <lkp@intel.com> > | Link: > https://lore.kernel.org/oe-kbuild-all/202304061930.4Au0PASm-lkp@intel.com/ > > All errors (new ones prefixed by >>): > >>> ld.lld: error: undefined symbol: __fortify_panic > >>> referenced by fortify-string.h:208 (include/linux/fortify-string.h:208) > >>> arch/arm/boot/compressed/fdt_ro.o:(fdt_stringlist_count) > >>> referenced by fortify-string.h:208 (include/linux/fortify-string.h:208) > >>> arch/arm/boot/compressed/fdt_ro.o:(fdt_stringlist_search) > >>> referenced by fortify-string.h:208 (include/linux/fortify-string.h:208) > >>> arch/arm/boot/compressed/fdt_ro.o:(fdt_stringlist_get) I get a related build failure from the same commit: arch/arm/boot/compressed/misc.c:157:6: error: no previous prototype for '__fortify_panic' [-Werror=missing-prototypes] 157 | void __fortify_panic(const u8 reason, size_t avail, size_t size) Arnd
On Thu, Feb 22, 2024 at 02:00:26PM +0100, Arnd Bergmann wrote: > On Thu, Apr 6, 2023, at 13:19, kernel test robot wrote: > > > If you fix the issue, kindly add following tag where applicable > > | Reported-by: kernel test robot <lkp@intel.com> > > | Link: > > https://lore.kernel.org/oe-kbuild-all/202304061930.4Au0PASm-lkp@intel.com/ > > > > All errors (new ones prefixed by >>): > > > >>> ld.lld: error: undefined symbol: __fortify_panic > > >>> referenced by fortify-string.h:208 (include/linux/fortify-string.h:208) > > >>> arch/arm/boot/compressed/fdt_ro.o:(fdt_stringlist_count) > > >>> referenced by fortify-string.h:208 (include/linux/fortify-string.h:208) > > >>> arch/arm/boot/compressed/fdt_ro.o:(fdt_stringlist_search) > > >>> referenced by fortify-string.h:208 (include/linux/fortify-string.h:208) > > >>> arch/arm/boot/compressed/fdt_ro.o:(fdt_stringlist_get) > > I get a related build failure from the same commit: > > arch/arm/boot/compressed/misc.c:157:6: error: no previous prototype for '__fortify_panic' [-Werror=missing-prototypes] > 157 | void __fortify_panic(const u8 reason, size_t avail, size_t size) Whoops, thank you! This series got a refresh after you did the missing-prototypes work and I missed this one. I've fixed it and double-checked for any others. Hopefully this will be clean in the next -next. :) -Kees
On Thu, Feb 22, 2024 at 6:30 PM Kees Cook <keescook@chromium.org> wrote: > On Thu, Feb 22, 2024 at 02:00:26PM +0100, Arnd Bergmann wrote: > > On Thu, Apr 6, 2023, at 13:19, kernel test robot wrote: > > > > > If you fix the issue, kindly add following tag where applicable > > > | Reported-by: kernel test robot <lkp@intel.com> > > > | Link: > > > https://lore.kernel.org/oe-kbuild-all/202304061930.4Au0PASm-lkp@intel.com/ > > > > > > All errors (new ones prefixed by >>): > > > > > >>> ld.lld: error: undefined symbol: __fortify_panic > > > >>> referenced by fortify-string.h:208 (include/linux/fortify-string.h:208) > > > >>> arch/arm/boot/compressed/fdt_ro.o:(fdt_stringlist_count) > > > >>> referenced by fortify-string.h:208 (include/linux/fortify-string.h:208) > > > >>> arch/arm/boot/compressed/fdt_ro.o:(fdt_stringlist_search) > > > >>> referenced by fortify-string.h:208 (include/linux/fortify-string.h:208) > > > >>> arch/arm/boot/compressed/fdt_ro.o:(fdt_stringlist_get) > > > > I get a related build failure from the same commit: > > > > arch/arm/boot/compressed/misc.c:157:6: error: no previous prototype for '__fortify_panic' [-Werror=missing-prototypes] > > 157 | void __fortify_panic(const u8 reason, size_t avail, size_t size) > > Whoops, thank you! This series got a refresh after you did the > missing-prototypes work and I missed this one. I've fixed it and > double-checked for any others. Hopefully this will be clean in the next > -next. :) Thank you! (FWIW, I also hit it today)
diff --git a/include/linux/fortify-string.h b/include/linux/fortify-string.h index 41dbd641f55c..6db4052db459 100644 --- a/include/linux/fortify-string.h +++ b/include/linux/fortify-string.h @@ -9,7 +9,34 @@ #define __FORTIFY_INLINE extern __always_inline __gnu_inline __overloadable #define __RENAME(x) __asm__(#x) -void fortify_panic(const char *name) __noreturn __cold; +#define fortify_reason(func, write) (((func) << 1) | !!(write)) + +#define fortify_panic(func, write) \ + __fortify_panic(fortify_reason(func, write)) + +#define FORTIFY_READ 0 +#define FORTIFY_WRITE 1 + +#define FORTIFY_FUNC_strncpy 0 +#define FORTIFY_FUNC_strnlen 1 +#define FORTIFY_FUNC_strlen 2 +#define FORTIFY_FUNC_strlcpy 3 +#define FORTIFY_FUNC_strscpy 4 +#define FORTIFY_FUNC_strlcat 5 +#define FORTIFY_FUNC_strcat 6 +#define FORTIFY_FUNC_strncat 7 +#define FORTIFY_FUNC_memset 8 +#define FORTIFY_FUNC_memcpy 9 +#define FORTIFY_FUNC_memmove 10 +#define FORTIFY_FUNC_memscan 11 +#define FORTIFY_FUNC_memcmp 12 +#define FORTIFY_FUNC_memchr 13 +#define FORTIFY_FUNC_memchr_inv 14 +#define FORTIFY_FUNC_kmemdup 15 +#define FORTIFY_FUNC_strcpy 16 + +void __fortify_report(u8 reason); +void __fortify_panic(u8 reason) __cold __noreturn; void __read_overflow(void) __compiletime_error("detected read beyond size of object (1st parameter)"); void __read_overflow2(void) __compiletime_error("detected read beyond size of object (2nd parameter)"); void __read_overflow2_field(size_t avail, size_t wanted) __compiletime_warning("detected read beyond size of field (2nd parameter); maybe use struct_group()?"); @@ -147,7 +174,7 @@ char *strncpy(char * const POS p, const char *q, __kernel_size_t size) if (__compiletime_lessthan(p_size, size)) __write_overflow(); if (p_size < size) - fortify_panic(__func__); + fortify_panic(FORTIFY_FUNC_strncpy, FORTIFY_WRITE); return __underlying_strncpy(p, q, size); } @@ -178,7 +205,7 @@ __FORTIFY_INLINE __kernel_size_t strnlen(const char * const POS p, __kernel_size /* Do not check characters beyond the end of p. */ ret = __real_strnlen(p, maxlen < p_size ? maxlen : p_size); if (p_size <= ret && maxlen != ret) - fortify_panic(__func__); + fortify_panic(FORTIFY_FUNC_strnlen, FORTIFY_READ); return ret; } @@ -214,7 +241,7 @@ __kernel_size_t __fortify_strlen(const char * const POS p) return __underlying_strlen(p); ret = strnlen(p, p_size); if (p_size <= ret) - fortify_panic(__func__); + fortify_panic(FORTIFY_FUNC_strlen, FORTIFY_READ); return ret; } @@ -256,7 +283,7 @@ __FORTIFY_INLINE size_t strlcpy(char * const POS p, const char * const POS q, si } if (size) { if (len >= p_size) - fortify_panic(__func__); + fortify_panic(FORTIFY_FUNC_strlcpy, FORTIFY_WRITE); __underlying_memcpy(p, q, len); p[len] = '\0'; } @@ -334,7 +361,7 @@ __FORTIFY_INLINE ssize_t strscpy(char * const POS p, const char * const POS q, s * p_size. */ if (len > p_size) - fortify_panic(__func__); + fortify_panic(FORTIFY_FUNC_strscpy, FORTIFY_WRITE); /* * We can now safely call vanilla strscpy because we are protected from: @@ -392,7 +419,7 @@ size_t strlcat(char * const POS p, const char * const POS q, size_t avail) /* Give up if string is already overflowed. */ if (p_size <= p_len) - fortify_panic(__func__); + fortify_panic(FORTIFY_FUNC_strlcat, FORTIFY_READ); if (actual >= avail) { copy_len = avail - p_len - 1; @@ -401,7 +428,7 @@ size_t strlcat(char * const POS p, const char * const POS q, size_t avail) /* Give up if copy will overflow. */ if (p_size <= actual) - fortify_panic(__func__); + fortify_panic(FORTIFY_FUNC_strlcat, FORTIFY_WRITE); __underlying_memcpy(p + p_len, q, copy_len); p[actual] = '\0'; @@ -430,7 +457,7 @@ char *strcat(char * const POS p, const char *q) size_t p_size = __member_size(p); if (strlcat(p, q, p_size) >= p_size) - fortify_panic(__func__); + fortify_panic(FORTIFY_FUNC_strcat, FORTIFY_WRITE); return p; } @@ -466,7 +493,7 @@ char *strncat(char * const POS p, const char * const POS q, __kernel_size_t coun p_len = strlen(p); copy_len = strnlen(q, count); if (p_size < p_len + copy_len + 1) - fortify_panic(__func__); + fortify_panic(FORTIFY_FUNC_strncat, FORTIFY_WRITE); __underlying_memcpy(p + p_len, q, copy_len); p[p_len + copy_len] = '\0'; return p; @@ -507,7 +534,7 @@ __FORTIFY_INLINE void fortify_memset_chk(__kernel_size_t size, * lengths are unknown.) */ if (p_size != SIZE_MAX && p_size < size) - fortify_panic("memset"); + fortify_panic(FORTIFY_FUNC_memset, FORTIFY_WRITE); } #define __fortify_memset_chk(p, c, size, p_size, p_size_field) ({ \ @@ -561,7 +588,7 @@ __FORTIFY_INLINE bool fortify_memcpy_chk(__kernel_size_t size, const size_t q_size, const size_t p_size_field, const size_t q_size_field, - const char *func) + const u8 func) { if (__builtin_constant_p(size)) { /* @@ -605,9 +632,10 @@ __FORTIFY_INLINE bool fortify_memcpy_chk(__kernel_size_t size, * (The SIZE_MAX test is to optimize away checks where the buffer * lengths are unknown.) */ - if ((p_size != SIZE_MAX && p_size < size) || - (q_size != SIZE_MAX && q_size < size)) - fortify_panic(func); + if (p_size != SIZE_MAX && p_size < size) + fortify_panic(func, FORTIFY_WRITE); + else if (q_size != SIZE_MAX && q_size < size) + fortify_panic(func, FORTIFY_READ); /* * Warn when writing beyond destination field size. @@ -640,7 +668,7 @@ __FORTIFY_INLINE bool fortify_memcpy_chk(__kernel_size_t size, const size_t __q_size_field = (q_size_field); \ WARN_ONCE(fortify_memcpy_chk(__fortify_size, __p_size, \ __q_size, __p_size_field, \ - __q_size_field, #op), \ + __q_size_field, FORTIFY_FUNC_ ##op), \ #op ": detected field-spanning write (size %zu) of single %s (size %zu)\n", \ __fortify_size, \ "field \"" #p "\" at " __FILE__ ":" __stringify(__LINE__), \ @@ -707,7 +735,7 @@ __FORTIFY_INLINE void *memscan(void * const POS0 p, int c, __kernel_size_t size) if (__compiletime_lessthan(p_size, size)) __read_overflow(); if (p_size < size) - fortify_panic(__func__); + fortify_panic(FORTIFY_FUNC_memscan, FORTIFY_READ); return __real_memscan(p, c, size); } @@ -724,7 +752,7 @@ int memcmp(const void * const POS0 p, const void * const POS0 q, __kernel_size_t __read_overflow2(); } if (p_size < size || q_size < size) - fortify_panic(__func__); + fortify_panic(FORTIFY_FUNC_memcmp, FORTIFY_READ); return __underlying_memcmp(p, q, size); } @@ -736,7 +764,7 @@ void *memchr(const void * const POS0 p, int c, __kernel_size_t size) if (__compiletime_lessthan(p_size, size)) __read_overflow(); if (p_size < size) - fortify_panic(__func__); + fortify_panic(FORTIFY_FUNC_memchr, FORTIFY_READ); return __underlying_memchr(p, c, size); } @@ -748,7 +776,7 @@ __FORTIFY_INLINE void *memchr_inv(const void * const POS0 p, int c, size_t size) if (__compiletime_lessthan(p_size, size)) __read_overflow(); if (p_size < size) - fortify_panic(__func__); + fortify_panic(FORTIFY_FUNC_memchr_inv, FORTIFY_READ); return __real_memchr_inv(p, c, size); } @@ -761,7 +789,7 @@ __FORTIFY_INLINE void *kmemdup(const void * const POS0 p, size_t size, gfp_t gfp if (__compiletime_lessthan(p_size, size)) __read_overflow(); if (p_size < size) - fortify_panic(__func__); + fortify_panic(FORTIFY_FUNC_kmemdup, FORTIFY_READ); return __real_kmemdup(p, size, gfp); } @@ -798,7 +826,7 @@ char *strcpy(char * const POS p, const char * const POS q) __write_overflow(); /* Run-time check for dynamic size overflow. */ if (p_size < size) - fortify_panic(__func__); + fortify_panic(FORTIFY_FUNC_strcpy, FORTIFY_WRITE); __underlying_memcpy(p, q, size); return p; } diff --git a/lib/string_helpers.c b/lib/string_helpers.c index 230020a2e076..631c50657096 100644 --- a/lib/string_helpers.c +++ b/lib/string_helpers.c @@ -1021,10 +1021,74 @@ EXPORT_SYMBOL(__read_overflow2_field); void __write_overflow_field(size_t avail, size_t wanted) { } EXPORT_SYMBOL(__write_overflow_field); -void fortify_panic(const char *name) +void __fortify_report(u8 reason) { - pr_emerg("detected buffer overflow in %s\n", name); + const char *name; + const bool write = !!(reason & 0x1); + + switch (reason >> 1) { + case FORTIFY_FUNC_strncpy: + name = "strncpy"; + break; + case FORTIFY_FUNC_strnlen: + name = "strnlen"; + break; + case FORTIFY_FUNC_strlen: + name = "strlen"; + break; + case FORTIFY_FUNC_strlcpy: + name = "strlcpy"; + break; + case FORTIFY_FUNC_strscpy: + name = "strscpy"; + break; + case FORTIFY_FUNC_strlcat: + name = "strlcat"; + break; + case FORTIFY_FUNC_strcat: + name = "strcat"; + break; + case FORTIFY_FUNC_strncat: + name = "strncat"; + break; + case FORTIFY_FUNC_memset: + name = "memset"; + break; + case FORTIFY_FUNC_memcpy: + name = "memcpy"; + break; + case FORTIFY_FUNC_memmove: + name = "memmove"; + break; + case FORTIFY_FUNC_memscan: + name = "memscan"; + break; + case FORTIFY_FUNC_memcmp: + name = "memcmp"; + break; + case FORTIFY_FUNC_memchr: + name = "memchr"; + break; + case FORTIFY_FUNC_memchr_inv: + name = "memchr_inv"; + break; + case FORTIFY_FUNC_kmemdup: + name = "kmemdup"; + break; + case FORTIFY_FUNC_strcpy: + name = "strcpy"; + break; + default: + name = "unknown"; + } + WARN(1, "%s: detected buffer %s overflow\n", name, write ? "write" : "read"); +} +EXPORT_SYMBOL(__fortify_report); + +void __fortify_panic(const u8 reason) +{ + __fortify_report(reason); BUG(); } -EXPORT_SYMBOL(fortify_panic); +EXPORT_SYMBOL(__fortify_panic); #endif /* CONFIG_FORTIFY_SOURCE */ diff --git a/tools/objtool/check.c b/tools/objtool/check.c index f937be1afe65..2d0a67ce1c51 100644 --- a/tools/objtool/check.c +++ b/tools/objtool/check.c @@ -197,6 +197,7 @@ static bool __dead_end_function(struct objtool_file *file, struct symbol *func, * attribute isn't provided in ELF data. Keep 'em sorted. */ static const char * const global_noreturns[] = { + "__fortify_panic", "__invalid_creds", "__module_put_and_kthread_exit", "__reiserfs_panic", @@ -208,7 +209,6 @@ static bool __dead_end_function(struct objtool_file *file, struct symbol *func, "do_group_exit", "do_task_dead", "ex_handler_msr_mce", - "fortify_panic", "kthread_complete_and_exit", "kthread_exit", "kunit_try_catch_throw",
In preparation for KUnit testing and further improvements in fortify failure reporting, split out the report and encode the function and access failure (read or write overflow) into a single int argument. This mainly ends up saving some space in the data segment. For a defconfig with FORTIFY_SOURCE enabled: $ size gcc/vmlinux.before gcc/vmlinux.after text data bss dec hex filename 26132309 9760658 2195460 38088427 2452eeb gcc/vmlinux.before 26132386 9748382 2195460 38076228 244ff44 gcc/vmlinux.after Cc: Andy Shevchenko <andy@kernel.org> Cc: Cezary Rojewski <cezary.rojewski@intel.com> Cc: Puyou Lu <puyou.lu@gmail.com> Cc: Mark Brown <broonie@kernel.org> Cc: linux-hardening@vger.kernel.org Signed-off-by: Kees Cook <keescook@chromium.org> --- include/linux/fortify-string.h | 72 +++++++++++++++++++++++----------- lib/string_helpers.c | 70 +++++++++++++++++++++++++++++++-- tools/objtool/check.c | 2 +- 3 files changed, 118 insertions(+), 26 deletions(-)