[PATCH v2 4/4] aarch64: Fix LD_AUDIT with GCS in permissive mode

Yury Khrustalev yury.khrustalev@arm.com
Thu Jan 8 14:27:34 GMT 2026


On Thu, Jan 08, 2026 at 11:19:35AM -0300, Adhemerval Zanella Netto wrote:
> 
> On 08/01/26 09:06, Yury Khrustalev wrote:
> > On Wed, Jan 07, 2026 at 01:52:39PM -0300, Adhemerval Zanella wrote:
> >> 
> >> ...
> >> 
> >>  static bool
> >> -check_gcs (struct link_map *l, const char *program, bool enforced)
> >> +check_gcs (struct link_map *l, const char *program, bool enforced, int mode)
> >>  {
> >>  #ifdef SHARED
> >>    /* Ignore GCS marking on ld.so: its properties are not processed.  */
> >> @@ -61,8 +61,10 @@ check_gcs (struct link_map *l, const char *program, bool enforced)
> >>    /* Binary is marked, all good.  */
> >>    if (l->l_mach.gcs)
> >>      return true;
> >> -  /* Binary is not marked and loaded via dlopen: abort.  */
> >> -  if (program == NULL)
> >> +  /* Binary is not marked and loaded via dlopen: abort.  Also, do not
> >> +     fail is optional mode is being used with audit modules without
> >> +     GCS support.  */
> >> +  if (program == NULL && (mode & __RTLD_AUDIT) == 0)
> >>      fail (l, program);
> > 
> > In this case we skip failing when 'program == NULL' (which is identical
> > to "we are inside dlopen()" in this context) when the 'mode' param has
> > the __RTLD_AUDIT bit set. In this case, if we enforce GCS, then the
> > failure will happen at the next step below (as expected).
> > 
> > Previously, we always failed in the dlopen() case because we presumed
> > that dlopen() is used only after startup has completed and GCS is
> > already either enabled or not, and if we intended to enforce it, we must
> > prevent dlopen() from opening an unmarked. This assumption was incorrect
> > in the LD_AUDIT use case because in this situation dlopen() is used to
> > load special shared object before all other dependencies. At this point
> > we can honour GCS_POLICY_OPTIONAL if it was selected. The result is that
> > GCS might be disabled if at least one of the shared objects loaded at
> > startup is not GCS-compatible (which includes LD_AUDIT objects).
> > 
> > My only concern is that this logic is somewhat fragile. Is it possible
> > to forge the __RTLD_AUDIT in the dlopen() flags and as a result trick
> > dlopen() into loading an unmarked object when GCS is enabled?
> 
> Not with current provided dlfcn.h API, where we explicit signal an error for
> invalid/internal flags:
> 
> dlfcn/dlopen.c
> 
>  46 static void
>  47 dlopen_doit (void *a)
>  48 {
>  49   struct dlopen_args *args = (struct dlopen_args *) a;
>  50
>  51   if (args->mode & ~(RTLD_BINDING_MASK | RTLD_NOLOAD | RTLD_DEEPBIND
>  52                      | RTLD_GLOBAL | RTLD_LOCAL | RTLD_NODELETE
>  53                      | __RTLD_SPROF))
>  54     _dl_signal_error (0, NULL, NULL, _("invalid mode parameter"));
> 
> The __RTLD_AUDIT is only used and supported internally, and audit modules
> are only supposed to be loaded at program statup (either by LD_AUDIT, ld.so
> --audit, or DT_AUDIT/DT_DEPAUDIT).

I see, thanks for clarification, it clears my concern.

Thanks,
Yury



More information about the Libc-alpha mailing list