Ejemplo n.º 1
0
int serialize_table(lua_sandbox* lsb, serialization_data* data, size_t parent)
{
    int result = 0;
    lua_checkstack(lsb->m_lua, 2);
    lua_pushnil(lsb->m_lua);
    while (result == 0 && lua_next(lsb->m_lua, -2) != 0) {
        result = serialize_kvp(lsb, data, parent);
        lua_pop(lsb->m_lua, 1); // Remove the value leaving the key on top for
                                // the next interation.
    }
    return result;
}
Ejemplo n.º 2
0
int preserve_global_data(lua_sandbox* lsb, const char* data_file)
{
    static const char* G = "_G";
    lua_getglobal(lsb->m_lua, G);
    if (!lua_istable(lsb->m_lua, -1)) {
        snprintf(lsb->m_error_message, ERROR_SIZE,
                 "preserve_global_data cannot access the global table");
        return 1;
    }

    FILE* fh = fopen(data_file, "wb");
    if (fh == NULL) {
        snprintf(lsb->m_error_message, ERROR_SIZE,
                 "preserve_global_data could not open: %s", data_file);
        return 1;
    }

    int result = 0;
    serialization_data data;
    data.m_fh = fh;
    data.m_keys.m_size = OUTPUT_SIZE;
    data.m_keys.m_pos = 0;
    data.m_keys.m_data = malloc(data.m_keys.m_size);
    data.m_tables.m_size = 64;
    data.m_tables.m_pos = 0;
    data.m_tables.m_array = malloc(data.m_tables.m_size * sizeof(table_ref));
    if (data.m_tables.m_array == NULL || data.m_keys.m_data == NULL) {
        snprintf(lsb->m_error_message, ERROR_SIZE,
                 "preserve_global_data out of memory");
        result = 1;
    } else {
        dynamic_snprintf(&data.m_keys, "%s", G);
        data.m_keys.m_pos += 1;
        data.m_globals = lua_topointer(lsb->m_lua, -1);
        lua_checkstack(lsb->m_lua, 2);
        lua_pushnil(lsb->m_lua);
        while (result == 0 && lua_next(lsb->m_lua, -2) != 0) {
            result = serialize_kvp(lsb, &data, 0);
            lua_pop(lsb->m_lua, 1);
        }
        lua_pop(lsb->m_lua, lua_gettop(lsb->m_lua));
        // Wipe the entire Lua stack.  Since incremental cleanup on failure
        // was added the stack should only contain table _G.
    }
    free(data.m_tables.m_array);
    free(data.m_keys.m_data);
    fclose(fh);
    if (result != 0) {
        remove(data_file);
    }
    return result;
}
static lsb_err_value
serialize_table(lsb_lua_sandbox *lsb, serialization_data *data, size_t parent)
{
  lsb_err_value ret = NULL;
  lua_checkstack(lsb->lua, 2);
  lua_pushnil(lsb->lua);
  while (!ret && lua_next(lsb->lua, -2) != 0) {
    ret = serialize_kvp(lsb, data, parent);
    lua_pop(lsb->lua, 1); // Remove the value leaving the key on top for
                          // the next interation.
  }
  return ret;
}
lsb_err_value preserve_global_data(lsb_lua_sandbox *lsb)
{

  if (!lsb->lua || !lsb->state_file) {
    return NULL;
  }
  lua_sethook(lsb->lua, NULL, 0, 0);

  // make sure the string library is loaded before we start
  lua_getglobal(lsb->lua, LUA_STRLIBNAME);
  if (!lua_istable(lsb->lua, -1)) {
    lua_getglobal(lsb->lua, "require");
    if (!lua_iscfunction(lsb->lua, -1)) {
      snprintf(lsb->error_message, LSB_ERROR_SIZE,
               "preserve_global_data 'require' function not found");
      return LSB_ERR_LUA;
    }
    lua_pushstring(lsb->lua, LUA_STRLIBNAME);
    if (lua_pcall(lsb->lua, 1, 1, 0)) {
      int len = snprintf(lsb->error_message, LSB_ERROR_SIZE,
                         "preserve_global_data failed loading 'string'");
      if (len >= LSB_ERROR_SIZE || len < 0) {
        lsb->error_message[LSB_ERROR_SIZE - 1] = 0;
      }
      return LSB_ERR_LUA;
    }
  }
  lua_pop(lsb->lua, 1);

  lua_pushvalue(lsb->lua, LUA_GLOBALSINDEX);

  FILE *fh = fopen(lsb->state_file, "wb" CLOSE_ON_EXEC);
  if (fh == NULL) {
    int len = snprintf(lsb->error_message, LSB_ERROR_SIZE,
                       "preserve_global_data could not open: %s",
                       lsb->state_file);
    if (len >= LSB_ERROR_SIZE || len < 0) {
      lsb->error_message[LSB_ERROR_SIZE - 1] = 0;
    }
    return LSB_ERR_LUA;;
  }

  lsb_err_value ret = NULL;
  serialization_data data;
  data.fh = fh;

// Clear the sandbox limits during preservation.
#ifdef LUA_JIT
  lua_gc(lsb->lua, LUA_GCSETMEMLIMIT, 0);
#else
//  size_t limit = lsb->usage[LSB_UT_MEMORY][LSB_US_LIMIT];
  lsb->usage[LSB_UT_MEMORY][LSB_US_LIMIT] = 0;
#endif
//  size_t cur_output_size = lsb->output.size;
//  size_t max_output_size = lsb->output.maxsize;
  lsb->output.maxsize = 0;
// end clear

  data.tables.size = 64;
  data.tables.pos = 0;
  data.tables.array = malloc(data.tables.size * sizeof(table_ref));
  if (data.tables.array == NULL || lsb_init_output_buffer(&data.keys, 0)) {
    snprintf(lsb->error_message, LSB_ERROR_SIZE,
             "preserve_global_data out of memory");
    ret = LSB_ERR_UTIL_OOM;
  } else {
    fprintf(data.fh, "if %s and %s ~= %d then return end\n",
            preservation_version,
            preservation_version,
            get_preservation_version(lsb->lua));
    ret = lsb_outputs(&data.keys, "_G", 2);
    if (!ret) {
      data.keys.pos += 1; // preserve the NUL in this use case
      data.globals = lua_topointer(lsb->lua, -1);
      lua_checkstack(lsb->lua, 2);
      lua_pushnil(lsb->lua);
      while (!ret && lua_next(lsb->lua, -2) != 0) {
        ret = serialize_kvp(lsb, &data, 0);
        lua_pop(lsb->lua, 1);
      }
    }
    lua_pop(lsb->lua, lua_gettop(lsb->lua));
    // Wipe the entire Lua stack.  Since incremental cleanup on failure
    // was added the stack should only contain table _G.
  }
  free(data.tables.array);
  lsb_free_output_buffer(&data.keys);
  fclose(fh);
  if (ret) remove(lsb->state_file);

// Uncomment if we start preserving state when not destroying the sandbox
// Note: serialization uses the output buffer, inprogress output can be
// destroyed if the user was collecting output between calls.
/*
// Restore the sandbox limits after preservation
#ifdef LUA_JIT
  lua_gc(lsb->lua, LUA_GCSETMEMLIMIT,
         lsb->usage[LSB_UT_MEMORY][LSB_US_LIMIT]);
#else
  lua_gc(lsb->lua, LUA_GCCOLLECT, 0);
  lsb->usage[LSB_UT_MEMORY][LSB_US_LIMIT] = limit;
  lsb->usage[LSB_UT_MEMORY][LSB_US_MAXIMUM] =
    lsb->usage[LSB_UT_MEMORY][LSB_US_CURRENT];
#endif
  lsb->output.maxsize = max_output_size;
  lsb_clear_output_buffer(lsb->output);
  if (lsb->output.size > cur_output_size) {
    void* ptr = realloc(lsb->output.data, cur_output_size);
    if (!ptr) return 1;
    lsb->output.data = ptr;
    lsb->output.size = cur_output_size;
  }
// end restore
*/
  return ret;
}