Branch: Tag:

2019-02-06

2019-02-06 22:22:42 by Henrik Grubbström (Grubba) <grubba@grubba.org>

EFUNs: Hide mutex keys and crypto contexts from backtraces.

Having unexpected references to mutex keys may cause hangs and
complaints about attempting to lock mutexes recursively.

Fixes [PIKE-156].

2:   || This file is part of Pike. For copyright information see COPYRIGHT.   || Pike is distributed under GPL, LGPL and MPL. See the file COPYING   || for more information. + || $Id$   */      #include "global.h"
2267:    pop_stack();    }    + /*! @class FakeObject +  *! +  *! Used as a place holder in eg backtraces for objects that +  *! are unsuitable to have references to in backtraces. +  *! +  *! Examples of such objects are instances of @[Thread.MutexKey], +  *! and @[Nettle.Cipher.State]. +  *! +  *! @seealso +  *! @[backtrace()] +  */ + PIKECLASS FakeObject +  program_flags PROGRAM_CONSTANT; + { +  PIKEVAR program prog flags ID_PRIVATE|ID_PROTECTED|ID_HIDDEN; +  +  PIKEFUN void create(program|function|void prog) +  flags ID_PROTECTED; +  { +  struct program *p = prog ? program_from_svalue(prog):NULL; +  do_free_program(THIS->prog); +  THIS->prog = p; +  if (p) add_ref(p); +  } +  +  PIKEFUN string _sprintf(int c, mapping|void ignored) +  flags ID_PROTECTED; +  { +  push_text("%O()"); +  if (THIS->prog) { +  ref_push_program(THIS->prog); +  } else { +  ref_push_program(Pike_fp->current_program); +  } +  f_sprintf(2); +  } + } +  + /*! @endclass +  */ +  + static struct object *clone_fake_object(struct program *p) + { +  if (p) ref_push_program(p); +  else push_undefined(); +  return clone_object(FakeObject_program, 1); + } +     /* Generates a number 0<=c<limit from random bits taken from the    int_buffer. Follows the NIST SP800-90A method for converting bit    sequences into bound numbers, described in section B.5.1.1, and
3245:    f->locals[numargs].u.array->item,    varargs, BIT_MIXED);    } +  if (bf->args->type_field & BIT_OBJECT) { +  ptrdiff_t i; +  for (i = 0; i < bf->args->size; i++) { +  struct svalue *s = ITEM(bf->args) + i; +  if ((TYPEOF(*s) == T_OBJECT) && +  s->u.object->prog && +  (s->u.object->prog->flags & +  (PROGRAM_DESTRUCT_IMMEDIATE|PROGRAM_CLEAR_STORAGE))) { +  /* It is typically a bad idea to have extra references +  * to objects with these flags. The flags are usually +  * used by stuff like mutex keys and encryption keys +  * respectively. +  */ +  struct object *o = clone_fake_object(s->u.object->prog); +  free_object(s->u.object); +  SET_SVAL(*s, T_OBJECT, 0, object, o);    }    }    } -  +  } +  } +  }    res->type_field = BIT_OBJECT;    /* NOTE: res has already been pushed on the stack. */   }