(root)/
glibc-2.38/
elf/
dl-audit.c
       1  /* Audit common functions.
       2     Copyright (C) 2021-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <assert.h>
      20  #include <link.h>
      21  #include <ldsodefs.h>
      22  #include <dl-machine.h>
      23  #include <dl-runtime.h>
      24  #include <dl-fixup-attribute.h>
      25  #include <sys/param.h>
      26  
      27  void
      28  _dl_audit_activity_map (struct link_map *l, int action)
      29  {
      30    struct audit_ifaces *afct = GLRO(dl_audit);
      31    for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
      32      {
      33        if (afct->activity != NULL)
      34  	afct->activity (&link_map_audit_state (l, cnt)->cookie, action);
      35        afct = afct->next;
      36      }
      37  }
      38  
      39  void
      40  _dl_audit_activity_nsid (Lmid_t nsid, int action)
      41  {
      42    /* If head is NULL, the namespace has become empty, and the audit interface
      43       does not give us a way to signal LA_ACT_CONSISTENT for it because the
      44       first loaded module is used to identify the namespace.  */
      45    struct link_map *head = GL(dl_ns)[nsid]._ns_loaded;
      46    if (__glibc_likely (GLRO(dl_naudit) == 0)
      47        || head == NULL || head->l_auditing)
      48      return;
      49  
      50    _dl_audit_activity_map (head, action);
      51  }
      52  
      53  const char *
      54  _dl_audit_objsearch (const char *name, struct link_map *l, unsigned int code)
      55  {
      56    if (l == NULL || l->l_auditing || code == 0)
      57      return name;
      58  
      59    struct audit_ifaces *afct = GLRO(dl_audit);
      60    for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
      61      {
      62        if (afct->objsearch != NULL)
      63  	{
      64  	  struct auditstate *state = link_map_audit_state (l, cnt);
      65  	  name = afct->objsearch (name, &state->cookie, code);
      66  	  if (name == NULL)
      67  	    return NULL;
      68  	}
      69        afct = afct->next;
      70     }
      71  
      72    return name;
      73  }
      74  
      75  void
      76  _dl_audit_objopen (struct link_map *l, Lmid_t nsid)
      77  {
      78    if (__glibc_likely (GLRO(dl_naudit) == 0))
      79      return;
      80  
      81    struct audit_ifaces *afct = GLRO(dl_audit);
      82    for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
      83      {
      84        if (afct->objopen != NULL)
      85  	{
      86  	  struct auditstate *state = link_map_audit_state (l, cnt);
      87  	  state->bindflags = afct->objopen (l, nsid, &state->cookie);
      88  	  l->l_audit_any_plt |= state->bindflags != 0;
      89  	}
      90  
      91        afct = afct->next;
      92     }
      93  }
      94  
      95  void
      96  _dl_audit_objclose (struct link_map *l)
      97  {
      98    if (__glibc_likely (GLRO(dl_naudit) == 0)
      99        || GL(dl_ns)[l->l_ns]._ns_loaded->l_auditing)
     100      return;
     101  
     102    struct audit_ifaces *afct = GLRO(dl_audit);
     103    for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
     104      {
     105        if (afct->objclose != NULL)
     106  	{
     107  	  struct auditstate *state= link_map_audit_state (l, cnt);
     108  	  /* Return value is ignored.  */
     109  	  afct->objclose (&state->cookie);
     110  	}
     111  
     112        afct = afct->next;
     113      }
     114  }
     115  
     116  void
     117  _dl_audit_preinit (struct link_map *l)
     118  {
     119    if (__glibc_likely (GLRO(dl_naudit) == 0))
     120      return;
     121  
     122    struct audit_ifaces *afct = GLRO(dl_audit);
     123    for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
     124      {
     125        if (afct->preinit != NULL)
     126  	afct->preinit (&link_map_audit_state (l, cnt)->cookie);
     127        afct = afct->next;
     128      }
     129  }
     130  
     131  void
     132  _dl_audit_symbind_alt (struct link_map *l, const ElfW(Sym) *ref, void **value,
     133  		       lookup_t result)
     134  {
     135    if ((l->l_audit_any_plt | result->l_audit_any_plt) == 0)
     136      return;
     137  
     138    const char *strtab = (const char *) D_PTR (result, l_info[DT_STRTAB]);
     139    /* Compute index of the symbol entry in the symbol table of the DSO with
     140       the definition.  */
     141    unsigned int ndx = (ref - (ElfW(Sym) *) D_PTR (result, l_info[DT_SYMTAB]));
     142  
     143    unsigned int altvalue = 0;
     144    /* Synthesize a symbol record where the st_value field is the result.  */
     145    ElfW(Sym) sym = *ref;
     146    sym.st_value = (ElfW(Addr)) *value;
     147  
     148    struct audit_ifaces *afct = GLRO(dl_audit);
     149    for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
     150      {
     151        struct auditstate *match_audit = link_map_audit_state (l, cnt);
     152        struct auditstate *result_audit = link_map_audit_state (result, cnt);
     153        if (afct->symbind != NULL
     154  	  && ((match_audit->bindflags & LA_FLG_BINDFROM) != 0
     155  	      || ((result_audit->bindflags & LA_FLG_BINDTO)
     156  		  != 0)))
     157  	{
     158  	  unsigned int flags = altvalue | LA_SYMB_DLSYM;
     159  	  uintptr_t new_value = afct->symbind (&sym, ndx,
     160  					       &match_audit->cookie,
     161  					       &result_audit->cookie,
     162  					       &flags, strtab + ref->st_name);
     163  	  if (new_value != (uintptr_t) sym.st_value)
     164  	    {
     165  	      altvalue = LA_SYMB_ALTVALUE;
     166  	      sym.st_value = new_value;
     167  	    }
     168  
     169  	  afct = afct->next;
     170  	}
     171  
     172        *value = (void *) sym.st_value;
     173      }
     174  }
     175  rtld_hidden_def (_dl_audit_symbind_alt)
     176  
     177  void
     178  _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result,
     179  		   const void *reloc, const ElfW(Sym) *defsym,
     180  		   DL_FIXUP_VALUE_TYPE *value, lookup_t result, bool lazy)
     181  {
     182    bool for_jmp_slot = reloc_result == NULL;
     183  
     184    /* Compute index of the symbol entry in the symbol table of the DSO
     185       with the definition.  */
     186    unsigned int boundndx = defsym - (ElfW(Sym) *) D_PTR (result,
     187  							l_info[DT_SYMTAB]);
     188    if (!for_jmp_slot)
     189      {
     190        reloc_result->bound = result;
     191        reloc_result->boundndx = boundndx;
     192      }
     193  
     194    if ((l->l_audit_any_plt | result->l_audit_any_plt) == 0)
     195      {
     196        /* Set all bits since this symbol binding is not interesting.  */
     197        if (!for_jmp_slot)
     198  	reloc_result->enterexit = (1u << DL_NNS) - 1;
     199        return;
     200      }
     201  
     202    /* Synthesize a symbol record where the st_value field is the result.  */
     203    ElfW(Sym) sym = *defsym;
     204    sym.st_value = DL_FIXUP_VALUE_ADDR (*value);
     205  
     206    /* Keep track whether there is any interest in tracing the call in the lower
     207       two bits.  */
     208    assert (DL_NNS * 2 <= sizeof (reloc_result->flags) * 8);
     209    assert ((LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT) == 3);
     210    uint32_t enterexit = LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT;
     211  
     212    const char *strtab2 = (const void *) D_PTR (result, l_info[DT_STRTAB]);
     213  
     214    unsigned int flags = 0;
     215    struct audit_ifaces *afct = GLRO(dl_audit);
     216    uintptr_t new_value = (uintptr_t) sym.st_value;
     217    for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
     218      {
     219        /* XXX Check whether both DSOs must request action or only one */
     220        struct auditstate *l_state = link_map_audit_state (l, cnt);
     221        struct auditstate *result_state = link_map_audit_state (result, cnt);
     222        if ((l_state->bindflags & LA_FLG_BINDFROM) != 0
     223  	  && (result_state->bindflags & LA_FLG_BINDTO) != 0)
     224  	{
     225  	  if (afct->symbind != NULL)
     226  	    {
     227  	      flags |= for_jmp_slot ? LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT
     228  				    : 0;
     229  	      new_value = afct->symbind (&sym, boundndx,
     230  					 &l_state->cookie,
     231  					 &result_state->cookie, &flags,
     232  					 strtab2 + defsym->st_name);
     233  	      if (new_value != (uintptr_t) sym.st_value)
     234  		{
     235  		  flags |= LA_SYMB_ALTVALUE;
     236  		  sym.st_value = for_jmp_slot
     237  		    ? DL_FIXUP_BINDNOW_ADDR_VALUE (new_value) : new_value;
     238  		}
     239  	    }
     240  
     241  	  /* Remember the results for every audit library and store a summary
     242  	     in the first two bits.  */
     243  	  enterexit &= flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT);
     244  	  enterexit |= ((flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT))
     245  			<< ((cnt + 1) * 2));
     246  	}
     247        else
     248  	/* If the bind flags say this auditor is not interested, set the bits
     249  	   manually.  */
     250  	enterexit |= ((LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT)
     251  		      << ((cnt + 1) * 2));
     252        afct = afct->next;
     253      }
     254  
     255    if (!for_jmp_slot)
     256      {
     257        reloc_result->enterexit = enterexit;
     258        reloc_result->flags = flags;
     259      }
     260  
     261    if (flags & LA_SYMB_ALTVALUE)
     262      DL_FIXUP_BINDNOW_RELOC (l, reloc, value, new_value, sym.st_value, lazy);
     263  }
     264  
     265  void
     266  _dl_audit_pltenter (struct link_map *l, struct reloc_result *reloc_result,
     267  		    DL_FIXUP_VALUE_TYPE *value, void *regs, long int *framesize)
     268  {
     269    /* Don't do anything if no auditor wants to intercept this call.  */
     270    if (GLRO(dl_naudit) == 0
     271        || (reloc_result->enterexit & LA_SYMB_NOPLTENTER))
     272      return;
     273  
     274    /* Sanity check:  DL_FIXUP_VALUE_CODE_ADDR (value) should have been
     275       initialized earlier in this function or in another thread.  */
     276    assert (DL_FIXUP_VALUE_CODE_ADDR (*value) != 0);
     277    ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound,
     278  					    l_info[DT_SYMTAB])
     279  		       + reloc_result->boundndx);
     280  
     281    /* Set up the sym parameter.  */
     282    ElfW(Sym) sym = *defsym;
     283    sym.st_value = DL_FIXUP_VALUE_ADDR (*value);
     284  
     285    /* Get the symbol name.  */
     286    const char *strtab = (const void *) D_PTR (reloc_result->bound,
     287  					     l_info[DT_STRTAB]);
     288    const char *symname = strtab + sym.st_name;
     289  
     290    /* Keep track of overwritten addresses.  */
     291    unsigned int flags = reloc_result->flags;
     292  
     293    struct audit_ifaces *afct = GLRO(dl_audit);
     294    for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
     295      {
     296        if (afct->ARCH_LA_PLTENTER != NULL
     297  	  && (reloc_result->enterexit
     298  	      & (LA_SYMB_NOPLTENTER << (2 * (cnt + 1)))) == 0)
     299  	{
     300  	  long int new_framesize = -1;
     301  	  struct auditstate *l_state = link_map_audit_state (l, cnt);
     302  	  struct auditstate *bound_state
     303  	    = link_map_audit_state (reloc_result->bound, cnt);
     304  	  uintptr_t new_value
     305  	    = afct->ARCH_LA_PLTENTER (&sym, reloc_result->boundndx,
     306  				      &l_state->cookie, &bound_state->cookie,
     307  				      regs, &flags, symname, &new_framesize);
     308  	  if (new_value != (uintptr_t) sym.st_value)
     309  	    {
     310  	      flags |= LA_SYMB_ALTVALUE;
     311  	      sym.st_value = new_value;
     312  	    }
     313  
     314  	  /* Remember the results for every audit library and store a summary
     315  	     in the first two bits.  */
     316  	  reloc_result->enterexit |= ((flags & (LA_SYMB_NOPLTENTER
     317  						| LA_SYMB_NOPLTEXIT))
     318  				      << (2 * (cnt + 1)));
     319  
     320  	  if ((reloc_result->enterexit & (LA_SYMB_NOPLTEXIT
     321  					  << (2 * (cnt + 1))))
     322  	      == 0 && new_framesize != -1 && *framesize != -2)
     323  	    {
     324  	      /* If this is the first call providing information, use it.  */
     325  	      if (*framesize == -1)
     326  		*framesize = new_framesize;
     327  	      /* If two pltenter calls provide conflicting information, use
     328  		 the larger value.  */
     329  	      else if (new_framesize != *framesize)
     330  		*framesize = MAX (new_framesize, *framesize);
     331  	    }
     332  	}
     333  
     334        afct = afct->next;
     335      }
     336  
     337    *value = DL_FIXUP_ADDR_VALUE (sym.st_value);
     338  }
     339  
     340  void
     341  DL_ARCH_FIXUP_ATTRIBUTE
     342  _dl_audit_pltexit (struct link_map *l, ElfW(Word) reloc_arg,
     343  		   const void *inregs, void *outregs)
     344  {
     345    const uintptr_t pltgot = (uintptr_t) D_PTR (l, l_info[DT_PLTGOT]);
     346  
     347    /* This is the address in the array where we store the result of previous
     348       relocations.  */
     349    // XXX Maybe the bound information must be stored on the stack since
     350    // XXX with bind_not a new value could have been stored in the meantime.
     351    struct reloc_result *reloc_result =
     352      &l->l_reloc_result[reloc_index (pltgot, reloc_arg, sizeof (PLTREL))];
     353    ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound,
     354  					    l_info[DT_SYMTAB])
     355  		       + reloc_result->boundndx);
     356  
     357    /* Set up the sym parameter.  */
     358    ElfW(Sym) sym = *defsym;
     359    sym.st_value = DL_FIXUP_VALUE_ADDR (reloc_result->addr);
     360  
     361    /* Get the symbol name.  */
     362    const char *strtab = (const void *) D_PTR (reloc_result->bound,
     363  					     l_info[DT_STRTAB]);
     364    const char *symname = strtab + sym.st_name;
     365  
     366    struct audit_ifaces *afct = GLRO(dl_audit);
     367    for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
     368      {
     369        if (afct->ARCH_LA_PLTEXIT != NULL
     370  	  && (reloc_result->enterexit
     371  	      & (LA_SYMB_NOPLTEXIT >> (2 * cnt))) == 0)
     372  	{
     373  	  struct auditstate *l_state = link_map_audit_state (l, cnt);
     374  	  struct auditstate *bound_state
     375  	    = link_map_audit_state (reloc_result->bound, cnt);
     376  	  afct->ARCH_LA_PLTEXIT (&sym, reloc_result->boundndx,
     377  				 &l_state->cookie, &bound_state->cookie,
     378  				 inregs, outregs, symname);
     379  	}
     380  
     381        afct = afct->next;
     382      }
     383  }