public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
To: Siddhesh Poyarekar <siddhesh@sourceware.org>, libc-alpha@sourceware.org
Cc: fweimer@redhat.com, jakub@redhat.com
Subject: Re: [PATCH 1/2] string: _FORTIFY_SOURCE=3 using __builtin_dynamic_object_size
Date: Mon, 28 Dec 2020 13:44:04 -0300	[thread overview]
Message-ID: <3582945f-21f4-3640-426b-0a9e39329d04@linaro.org> (raw)
In-Reply-To: <20201219063314.1409576-2-siddhesh@sourceware.org>



On 19/12/2020 03:33, Siddhesh Poyarekar via Libc-alpha wrote:
> Introduce a new _FORTIFY_SOURCE level of 3 to enable additional
> fortifications that may have a potential performance impact.  At the
> moment this level of fortification involves the use of the
> __builtin_dynamic_object_size builtin whenever the compiler supports
> it.
> 
> This change enhances fortified string functions to use
> __builtin_dynamic_object_size under _FORTIFY_SOURCE=3 whenever the
> compiler supports it.


For previous discussion I couldn't really grap what is the GCC intention
regarding this new builtin. Would it willing to implement with the same
semantic as LLVM has done or depending of result when glibc starts to 
provide it GCC will either change its semantic or not implement at all?

If the former, using _FORTIFY_SOURCE=3 should be fine.  However, if it
is the latter I think it would be better to add it as another and different
FORTIFY flag ( _FORTIFY_SOURCE_DYNAMIC or something like that).  

I really want to avoid the issue where developers would not see the
expected code generation when using _FORTIFY_SOURCE=3 with gcc or the worse,
where _FORTIFY_SOURCE=3 would have different semantic depending of the 
compiler used.

> 
> __builtin_dynamic_object_size
> -----------------------------
> 
> __builtin_dynamic_object_size is an LLVM builtin that is similar to
> __builtin_object_size.  In addition to what __builtin_object_size
> does, i.e. replace the builtin call with a constant object size,
> __builtin_dynamic_object_size will replace the call site with an
> expression that evaluates to the object size, thus expanding its
> applicability.  In practice, __builtin_dynamic_object_size evaluates
> these expressions through malloc/calloc calls that it can associate
> with the object being evaluated.
> 
> A simple motivating example is below; -D_FORTIFY_SOURCE=2 would miss
> this and emit memcpy, but -D_FORTIFY_SOURCE=3 with the help of
> __builtin_dynamic_object_size is able to emit __memcpy_chk with the
> allocation size expression passed into the function:
> 
> void *copy_obj (const void *src, size_t alloc, size_t copysize)
> {
>   void *obj = malloc (alloc);
>   memcpy (obj, src, copysize);
> 
>   return obj;
> }
> 
> Limitations
> -----------
> 
> If the object was allocated elsewhere that the compiler cannot see, or
> if it was allocated in the function with a function that the compiler
> does not recognize as an allocator then __builtin_dynamic_object_size
> also returns -1.
> 
> Further, the expression used to compute object size may be non-trivial
> and may potentially incur a noticeable performance impact.  These
> fortifications are hence enabled at a new _FORTIFY_SOURCE level to
> allow developers to make a choice on the tradeoff according to their
> environment.
> 
> Other Changes
> -------------
> 
> The _FORTIFY_SOURCE macro soup in features.h now warns about
> unsupported fortification levels.  For example, it will warn about
> _FORTIFY_SOURCE=3 and over for llvm older than 9.0 and for gcc and
> _FORTIFY_SOURCE=4 will result in a warning on all compilers with an
> indication of which level has been selected.

This should be in a different patch, where glibc would handle not support
_FORTIFY_SOURCE levels and emit the expected warnings.

> 
> Co-authored-by: Paul Eggert <eggert@cs.ucla.edu>
> ---
>  NEWS                            |  6 ++++++
>  include/features.h              |  8 ++++++++
>  include/string.h                |  5 +++--
>  manual/creature.texi            |  3 ++-
>  misc/sys/cdefs.h                |  9 +++++++++
>  string/bits/string_fortified.h  | 22 +++++++++++-----------
>  string/bits/strings_fortified.h |  4 ++--
>  7 files changed, 41 insertions(+), 16 deletions(-)
> 
> diff --git a/NEWS b/NEWS
> index 86e05fb023..8e02dbd0f7 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -28,6 +28,12 @@ Major new features:
>    The 32-bit RISC-V port requires at least Linux 5.4, GCC 7.1 and binutils
>    2.28.
>  
> +* A new fortification level _FORTIFY_SOURCE=3 is available.  At this level,
> +  glibc may use additional checks that may have an additional performance
> +  overhead.  At present these checks are available only on LLVM 9 and later.
> +  The latest GCC available at this time (10.2) does not support this level of
> +  fortification.
> +
>  Deprecated and removed features, and other changes affecting compatibility:
>  
>  * The mallinfo function is marked deprecated.  Callers should call

Ok.

> diff --git a/include/features.h b/include/features.h
> index f3e62d3362..066eb0eecd 100644
> --- a/include/features.h
> +++ b/include/features.h
> @@ -397,7 +397,15 @@
>  #  warning _FORTIFY_SOURCE requires compiling with optimization (-O)
>  # elif !__GNUC_PREREQ (4, 1)
>  #  warning _FORTIFY_SOURCE requires GCC 4.1 or later
> +# elif _FORTIFY_SOURCE > 2 && __glibc_clang_prereq (9, 0)
> +#  if _FORTIFY_SOURCE > 3
> +#   warning _FORTIFY_SOURCE > 3 is treated like 3 on this platform
> +#  endif
> +#  define __USE_FORTIFY_LEVEL 3
>  # elif _FORTIFY_SOURCE > 1
> +#  if _FORTIFY_SOURCE > 2
> +#   warning _FORTIFY_SOURCE > 2 is treated like 2 on this platform
> +#  endif
>  #  define __USE_FORTIFY_LEVEL 2
>  # else
>  #  define __USE_FORTIFY_LEVEL 1

As before, I think the _FORTIFY_LEVEL value check and warning should be in
separated patch.

> diff --git a/include/string.h b/include/string.h
> index 7d344d77d4..841ee05a1d 100644
> --- a/include/string.h
> +++ b/include/string.h
> @@ -123,10 +123,11 @@ libc_hidden_proto (__strerror_l)
>  void __explicit_bzero_chk_internal (void *, size_t, size_t)
>    __THROW __nonnull ((1)) attribute_hidden;
>  # define explicit_bzero(buf, len) \
> -  __explicit_bzero_chk_internal (buf, len, __bos0 (buf))
> +  __explicit_bzero_chk_internal (buf, len, __objsize0 (buf))
>  #elif !IS_IN (nonlib)
>  void __explicit_bzero_chk (void *, size_t, size_t) __THROW __nonnull ((1));
> -# define explicit_bzero(buf, len) __explicit_bzero_chk (buf, len, __bos0 (buf))
> +# define explicit_bzero(buf, len) __explicit_bzero_chk (buf, len,	      \
> +							__objsize0 (buf))
>  #endif
>  
>  libc_hidden_builtin_proto (memchr)
> diff --git a/manual/creature.texi b/manual/creature.texi
> index be5050468b..31208ccb2b 100644
> --- a/manual/creature.texi
> +++ b/manual/creature.texi
> @@ -254,7 +254,8 @@ included.
>  @standards{GNU, (none)}
>  If this macro is defined to @math{1}, security hardening is added to
>  various library functions.  If defined to @math{2}, even stricter
> -checks are applied.
> +checks are applied. If defined to @math{3}, @theglibc{} may also use
> +checks that may have an additional performance overhead.
>  @end defvr
>  
>  @defvr Macro _REENTRANT
> diff --git a/misc/sys/cdefs.h b/misc/sys/cdefs.h
> index a06f1cfd91..ca51a5c3ad 100644
> --- a/misc/sys/cdefs.h
> +++ b/misc/sys/cdefs.h
> @@ -127,6 +127,15 @@
>  #define __bos(ptr) __builtin_object_size (ptr, __USE_FORTIFY_LEVEL > 1)
>  #define __bos0(ptr) __builtin_object_size (ptr, 0)
>  
> +/* Use __builtin_dynamic_object_size at _FORTIFY_SOURCE=3 when available.  */
> +#if __USE_FORTIFY_LEVEL == 3 && __glibc_clang_prereq (9, 0)
> +# define __objsize0(__o) __builtin_dynamic_object_size (__o, 0)
> +# define __objsize(__o) __builtin_dynamic_object_size (__o, 1)
> +#else
> +# define __objsize0(__o) __bos0 (__o)
> +# define __objsize(__o) __bos (__o)
> +#endif
> +
>  #if __GNUC_PREREQ (4,3)

I think from previous version that Florian suggested renamed this internal macros
to __glibc_objsize[0].

>  # define __warnattr(msg) __attribute__((__warning__ (msg)))
>  # define __errordecl(name, msg) \
> diff --git a/string/bits/string_fortified.h b/string/bits/string_fortified.h
> index 4c1aeb45f1..c9f9197aef 100644
> --- a/string/bits/string_fortified.h
> +++ b/string/bits/string_fortified.h
> @@ -26,13 +26,13 @@ __fortify_function void *
>  __NTH (memcpy (void *__restrict __dest, const void *__restrict __src,
>  	       size_t __len))
>  {
> -  return __builtin___memcpy_chk (__dest, __src, __len, __bos0 (__dest));
> +  return __builtin___memcpy_chk (__dest, __src, __len, __objsize0 (__dest));
>  }
>  
>  __fortify_function void *
>  __NTH (memmove (void *__dest, const void *__src, size_t __len))
>  {
> -  return __builtin___memmove_chk (__dest, __src, __len, __bos0 (__dest));
> +  return __builtin___memmove_chk (__dest, __src, __len, __objsize0 (__dest));
>  }
>  
>  #ifdef __USE_GNU
> @@ -40,7 +40,7 @@ __fortify_function void *
>  __NTH (mempcpy (void *__restrict __dest, const void *__restrict __src,
>  		size_t __len))
>  {
> -  return __builtin___mempcpy_chk (__dest, __src, __len, __bos0 (__dest));
> +  return __builtin___mempcpy_chk (__dest, __src, __len, __objsize0 (__dest));
>  }
>  #endif
>  
> @@ -53,7 +53,7 @@ __NTH (mempcpy (void *__restrict __dest, const void *__restrict __src,
>  __fortify_function void *
>  __NTH (memset (void *__dest, int __ch, size_t __len))
>  {
> -  return __builtin___memset_chk (__dest, __ch, __len, __bos0 (__dest));
> +  return __builtin___memset_chk (__dest, __ch, __len, __objsize0 (__dest));
>  }
>  
>  #ifdef __USE_MISC
> @@ -65,21 +65,21 @@ void __explicit_bzero_chk (void *__dest, size_t __len, size_t __destlen)
>  __fortify_function void
>  __NTH (explicit_bzero (void *__dest, size_t __len))
>  {
> -  __explicit_bzero_chk (__dest, __len, __bos0 (__dest));
> +  __explicit_bzero_chk (__dest, __len, __objsize0 (__dest));
>  }
>  #endif
>  
>  __fortify_function char *
>  __NTH (strcpy (char *__restrict __dest, const char *__restrict __src))
>  {
> -  return __builtin___strcpy_chk (__dest, __src, __bos (__dest));
> +  return __builtin___strcpy_chk (__dest, __src, __objsize (__dest));
>  }
>  
>  #ifdef __USE_GNU
>  __fortify_function char *
>  __NTH (stpcpy (char *__restrict __dest, const char *__restrict __src))
>  {
> -  return __builtin___stpcpy_chk (__dest, __src, __bos (__dest));
> +  return __builtin___stpcpy_chk (__dest, __src, __objsize (__dest));
>  }
>  #endif
>  
> @@ -88,14 +88,14 @@ __fortify_function char *
>  __NTH (strncpy (char *__restrict __dest, const char *__restrict __src,
>  		size_t __len))
>  {
> -  return __builtin___strncpy_chk (__dest, __src, __len, __bos (__dest));
> +  return __builtin___strncpy_chk (__dest, __src, __len, __objsize (__dest));
>  }
>  
>  #if __GNUC_PREREQ (4, 7) || __glibc_clang_prereq (2, 6)
>  __fortify_function char *
>  __NTH (stpncpy (char *__dest, const char *__src, size_t __n))
>  {
> -  return __builtin___stpncpy_chk (__dest, __src, __n, __bos (__dest));
> +  return __builtin___stpncpy_chk (__dest, __src, __n, __objsize (__dest));
>  }
>  #else
>  extern char *__stpncpy_chk (char *__dest, const char *__src, size_t __n,
> @@ -118,7 +118,7 @@ __NTH (stpncpy (char *__dest, const char *__src, size_t __n))
>  __fortify_function char *
>  __NTH (strcat (char *__restrict __dest, const char *__restrict __src))
>  {
> -  return __builtin___strcat_chk (__dest, __src, __bos (__dest));
> +  return __builtin___strcat_chk (__dest, __src, __objsize (__dest));
>  }
>  
>  
> @@ -126,7 +126,7 @@ __fortify_function char *
>  __NTH (strncat (char *__restrict __dest, const char *__restrict __src,
>  		size_t __len))
>  {
> -  return __builtin___strncat_chk (__dest, __src, __len, __bos (__dest));
> +  return __builtin___strncat_chk (__dest, __src, __len, __objsize (__dest));
>  }
>  
>  #endif /* bits/string_fortified.h */

Ok.

> diff --git a/string/bits/strings_fortified.h b/string/bits/strings_fortified.h
> index d4091f4f69..122199e036 100644
> --- a/string/bits/strings_fortified.h
> +++ b/string/bits/strings_fortified.h
> @@ -22,13 +22,13 @@
>  __fortify_function void
>  __NTH (bcopy (const void *__src, void *__dest, size_t __len))
>  {
> -  (void) __builtin___memmove_chk (__dest, __src, __len, __bos0 (__dest));
> +  (void) __builtin___memmove_chk (__dest, __src, __len, __objsize0 (__dest));
>  }
>  
>  __fortify_function void
>  __NTH (bzero (void *__dest, size_t __len))
>  {
> -  (void) __builtin___memset_chk (__dest, '\0', __len, __bos0 (__dest));
> +  (void) __builtin___memset_chk (__dest, '\0', __len, __objsize0 (__dest));
>  }
>  
>  #endif
> 

Ok.

  reply	other threads:[~2020-12-28 16:44 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-12-19  6:33 [PATCH v6 0/2] _FORTIFY_SOURCE=3 Siddhesh Poyarekar
2020-12-19  6:33 ` [PATCH 1/2] string: _FORTIFY_SOURCE=3 using __builtin_dynamic_object_size Siddhesh Poyarekar
2020-12-28 16:44   ` Adhemerval Zanella [this message]
2020-12-29 15:14     ` Siddhesh Poyarekar
2020-12-19  6:33 ` [PATCH 2/2] nonstring: " Siddhesh Poyarekar
2020-12-28 17:36   ` Adhemerval Zanella
2020-12-29 14:04     ` Siddhesh Poyarekar
2020-12-29 14:26     ` Jakub Jelinek
2020-12-22 13:00 ` [PATCH v6 0/2] _FORTIFY_SOURCE=3 Siddhesh Poyarekar
2020-12-22 21:49   ` Adhemerval Zanella
  -- strict thread matches above, loose matches on Subject: below --
2020-12-10 18:13 [PATCH " Siddhesh Poyarekar
2020-12-10 18:13 ` [PATCH 1/2] string: _FORTIFY_SOURCE=3 using __builtin_dynamic_object_size Siddhesh Poyarekar
2020-12-10 19:10   ` Paul Eggert
2020-12-11  1:36     ` Siddhesh Poyarekar
2020-12-11  2:42       ` Paul Eggert

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=3582945f-21f4-3640-426b-0a9e39329d04@linaro.org \
    --to=adhemerval.zanella@linaro.org \
    --cc=fweimer@redhat.com \
    --cc=jakub@redhat.com \
    --cc=libc-alpha@sourceware.org \
    --cc=siddhesh@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).