[PATCH 2/6] tools/nolibc: disable function sanitizer for _start_c()

Thomas Weißschuh posted 6 patches 8 months ago
There is a newer version of this series
[PATCH 2/6] tools/nolibc: disable function sanitizer for _start_c()
Posted by Thomas Weißschuh 8 months ago
Both constructors and main() may be executed with different function
signatures than they are actually using.
This is intentional but trips up UBSAN.

Disable the function sanitizer of UBSAN in _start_c().

Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
 tools/include/nolibc/crt.h | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/tools/include/nolibc/crt.h b/tools/include/nolibc/crt.h
index c4b10103bbec50f1a3a0a4562e34fdbd1b43ce6f..961cfe777c3564e705dfdd581de828b374d05b0b 100644
--- a/tools/include/nolibc/crt.h
+++ b/tools/include/nolibc/crt.h
@@ -7,6 +7,8 @@
 #ifndef _NOLIBC_CRT_H
 #define _NOLIBC_CRT_H
 
+#include "compiler.h"
+
 char **environ __attribute__((weak));
 const unsigned long *_auxv __attribute__((weak));
 
@@ -25,6 +27,9 @@ extern void (*const __fini_array_end[])(void) __attribute__((weak));
 
 void _start_c(long *sp);
 __attribute__((weak,used))
+#if __nolibc_has_feature(undefined_behavior_sanitizer)
+	__attribute__((no_sanitize("function")))
+#endif
 void _start_c(long *sp)
 {
 	long argc;

-- 
2.49.0

Re: [PATCH 2/6] tools/nolibc: disable function sanitizer for _start_c()
Posted by Willy Tarreau 8 months ago
On Wed, Apr 16, 2025 at 08:40:17PM +0200, Thomas Weißschuh wrote:
> Both constructors and main() may be executed with different function
> signatures than they are actually using.
> This is intentional but trips up UBSAN.
> 
> Disable the function sanitizer of UBSAN in _start_c().
> 
> Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
> ---
>  tools/include/nolibc/crt.h | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/tools/include/nolibc/crt.h b/tools/include/nolibc/crt.h
> index c4b10103bbec50f1a3a0a4562e34fdbd1b43ce6f..961cfe777c3564e705dfdd581de828b374d05b0b 100644
> --- a/tools/include/nolibc/crt.h
> +++ b/tools/include/nolibc/crt.h
> @@ -7,6 +7,8 @@
>  #ifndef _NOLIBC_CRT_H
>  #define _NOLIBC_CRT_H
>  
> +#include "compiler.h"
> +
>  char **environ __attribute__((weak));
>  const unsigned long *_auxv __attribute__((weak));
>  
> @@ -25,6 +27,9 @@ extern void (*const __fini_array_end[])(void) __attribute__((weak));
>  
>  void _start_c(long *sp);
>  __attribute__((weak,used))
> +#if __nolibc_has_feature(undefined_behavior_sanitizer)
> +	__attribute__((no_sanitize("function")))
> +#endif

I'm wondering if it wouldn't be more reliable with:

  #if __nolibc_has_attribute(no_sanitize)
	__attribute__((no_sanitize("function")))
  #endif

Because in the end, what you want is to always place that attribute
whenever it's supported, no ?

>  void _start_c(long *sp)
>  {
>  	long argc;

Willy
Re: [PATCH 2/6] tools/nolibc: disable function sanitizer for _start_c()
Posted by Thomas Weißschuh 8 months ago
On 2025-04-19 11:06:31+0200, Willy Tarreau wrote:
> On Wed, Apr 16, 2025 at 08:40:17PM +0200, Thomas Weißschuh wrote:
> > Both constructors and main() may be executed with different function
> > signatures than they are actually using.
> > This is intentional but trips up UBSAN.
> > 
> > Disable the function sanitizer of UBSAN in _start_c().
> > 
> > Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
> > ---
> >  tools/include/nolibc/crt.h | 5 +++++
> >  1 file changed, 5 insertions(+)
> > 
> > diff --git a/tools/include/nolibc/crt.h b/tools/include/nolibc/crt.h
> > index c4b10103bbec50f1a3a0a4562e34fdbd1b43ce6f..961cfe777c3564e705dfdd581de828b374d05b0b 100644
> > --- a/tools/include/nolibc/crt.h
> > +++ b/tools/include/nolibc/crt.h
> > @@ -7,6 +7,8 @@
> >  #ifndef _NOLIBC_CRT_H
> >  #define _NOLIBC_CRT_H
> >  
> > +#include "compiler.h"
> > +
> >  char **environ __attribute__((weak));
> >  const unsigned long *_auxv __attribute__((weak));
> >  
> > @@ -25,6 +27,9 @@ extern void (*const __fini_array_end[])(void) __attribute__((weak));
> >  
> >  void _start_c(long *sp);
> >  __attribute__((weak,used))
> > +#if __nolibc_has_feature(undefined_behavior_sanitizer)
> > +	__attribute__((no_sanitize("function")))
> > +#endif
> 
> I'm wondering if it wouldn't be more reliable with:
> 
>   #if __nolibc_has_attribute(no_sanitize)
> 	__attribute__((no_sanitize("function")))
>   #endif
> 
> Because in the end, what you want is to always place that attribute
> whenever it's supported, no ?

That doesn't work because GCC does knows no_sanitize but not
no_sanitize("function").
Also no_sanitize is not specific to UBSAN but works for all sanitizers.

> 
> >  void _start_c(long *sp)
> >  {
> >  	long argc;
> 
> Willy
Re: [PATCH 2/6] tools/nolibc: disable function sanitizer for _start_c()
Posted by Willy Tarreau 8 months ago
On Sat, Apr 19, 2025 at 12:10:24PM +0200, Thomas Weißschuh wrote:
> On 2025-04-19 11:06:31+0200, Willy Tarreau wrote:
> > On Wed, Apr 16, 2025 at 08:40:17PM +0200, Thomas Weißschuh wrote:
> > > Both constructors and main() may be executed with different function
> > > signatures than they are actually using.
> > > This is intentional but trips up UBSAN.
> > > 
> > > Disable the function sanitizer of UBSAN in _start_c().
> > > 
> > > Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
> > > ---
> > >  tools/include/nolibc/crt.h | 5 +++++
> > >  1 file changed, 5 insertions(+)
> > > 
> > > diff --git a/tools/include/nolibc/crt.h b/tools/include/nolibc/crt.h
> > > index c4b10103bbec50f1a3a0a4562e34fdbd1b43ce6f..961cfe777c3564e705dfdd581de828b374d05b0b 100644
> > > --- a/tools/include/nolibc/crt.h
> > > +++ b/tools/include/nolibc/crt.h
> > > @@ -7,6 +7,8 @@
> > >  #ifndef _NOLIBC_CRT_H
> > >  #define _NOLIBC_CRT_H
> > >  
> > > +#include "compiler.h"
> > > +
> > >  char **environ __attribute__((weak));
> > >  const unsigned long *_auxv __attribute__((weak));
> > >  
> > > @@ -25,6 +27,9 @@ extern void (*const __fini_array_end[])(void) __attribute__((weak));
> > >  
> > >  void _start_c(long *sp);
> > >  __attribute__((weak,used))
> > > +#if __nolibc_has_feature(undefined_behavior_sanitizer)
> > > +	__attribute__((no_sanitize("function")))
> > > +#endif
> > 
> > I'm wondering if it wouldn't be more reliable with:
> > 
> >   #if __nolibc_has_attribute(no_sanitize)
> > 	__attribute__((no_sanitize("function")))
> >   #endif
> > 
> > Because in the end, what you want is to always place that attribute
> > whenever it's supported, no ?
> 
> That doesn't work because GCC does knows no_sanitize but not
> no_sanitize("function").
> Also no_sanitize is not specific to UBSAN but works for all sanitizers.

OK, thanks for explaining!

Willy