Commit 60cfc58e authored by Garrett Regier's avatar Garrett Regier

Prevent the accidental escaping of globals with Lua plugins

This implements a strict mode which prevents the
creation of globals, except when using rawset().
This can be disabled for incompatible code by setting
__STRICT to false.

https://bugzilla.gnome.org/show_bug.cgi?id=742557
parent d2bed913
......@@ -541,6 +541,7 @@ libpeas/Makefile
libpeas-gtk/Makefile
loaders/Makefile
loaders/lua5.1/Makefile
loaders/lua5.1/resources/Makefile
loaders/python/Makefile
loaders/python3/Makefile
data/Makefile
......
# Lua 5.1 plugin loader
SUBDIRS = resources
loaderdir = $(libdir)/libpeas-1.0/loaders
AM_CPPFLAGS = \
......@@ -30,23 +32,15 @@ liblua51loader_la_LIBADD = \
$(PEAS_LIBS) \
$(LUA51_LIBS)
%.luac: %.lua
$(AM_V_GEN) $(LUA51_BIN) $(srcdir)/peas-lua-compile.lua $< $@
all-local: peas-lua-internal.luac
loader_resources_deps = $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir) --generate-dependencies $(srcdir)/peas-lua.gresource.xml)
peas-lua-resources.c: $(srcdir)/peas-lua.gresource.xml $(loader_resources_deps)
$(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --internal --target=$@ --sourcedir=$(srcdir) --generate-source $(srcdir)/peas-lua.gresource.xml
loader_resources_deps = $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir)/resources --generate-dependencies $(srcdir)/resources/peas-lua.gresource.xml)
peas-lua-resources.c: $(srcdir)/resources/peas-lua.gresource.xml $(loader_resources_deps)
$(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --internal --target=$@ --sourcedir=$(srcdir)/resources --generate-source $(srcdir)/resources/peas-lua.gresource.xml
EXTRA_DIST = \
peas-lua-compile.lua \
peas-lua.gresource.xml \
$(loader_resources_deps)
CLEANFILES = \
peas-lua-internal.luac \
peas-lua-resources.c
CLEANFILES = peas-lua-resources.c
gcov_sources = $(liblua51loader_la_SOURCES)
include $(top_srcdir)/Makefile.gcov
......@@ -25,10 +25,7 @@
#include "peas-lua-internal.h"
#include <gio/gio.h>
#include <lauxlib.h>
#include <lualib.h>
#include "peas-lua-utils.h"
......@@ -60,54 +57,15 @@ failed_fn (lua_State *L)
gboolean
peas_lua_internal_setup (lua_State *L)
{
GBytes *internal_lua;
const gchar *code;
gsize code_len;
/* We don't use the byte-compiled Lua source
* because glib-compile-resources cannot output
* depends for generated files.
*
* There are also concerns that the bytecode is
* not stable enough between different Lua versions.
*
* https://bugzilla.gnome.org/show_bug.cgi?id=673101
*/
internal_lua = g_resources_lookup_data ("/org/gnome/libpeas/loaders/"
"lua5.1/internal.lua",
G_RESOURCE_LOOKUP_FLAGS_NONE,
NULL);
g_return_val_if_fail (internal_lua != NULL, FALSE);
code = g_bytes_get_data (internal_lua, &code_len);
/* Filenames are prefixed with '@' */
if (luaL_loadbuffer (L, code, code_len, "@peas-lua-internal.lua") != 0)
{
g_warning ("Failed to load internal Lua code: %s",
lua_tostring (L, -1));
/* Pop error */
lua_pop (L, 1);
g_bytes_unref (internal_lua);
return FALSE;
}
g_bytes_unref (internal_lua);
if (!peas_lua_utils_call (L, 0, 1))
if (!peas_lua_utils_load_resource (L, "internal.lua", 0, 1))
{
g_warning ("Failed to run internal Lua code: %s",
lua_tostring (L, -1));
/* Pop error */
lua_pop (L, 1);
/* Already warned */
return FALSE;
}
if (!lua_istable (L, -1))
{
g_warning ("Invalid result from internal Lua code: %s",
g_warning ("Invalid result from 'internal.lua' resource: %s",
lua_tostring (L, -1));
/* Pop result */
......
......@@ -25,10 +25,9 @@
#include "peas-lua-utils.h"
#include <string.h>
#include <gio/gio.h>
#include <lauxlib.h>
#include <lualib.h>
gboolean
......@@ -175,3 +174,70 @@ peas_lua_utils_call (lua_State *L,
lua_remove (L, -1 - (success ? n_results : 1));
return success;
}
gboolean
peas_lua_utils_load_resource (lua_State *L,
const gchar *name,
guint n_args,
guint n_results)
{
gchar *resource_path;
GBytes *lua_resource;
const gchar *code;
gsize code_len;
gchar *lua_filename;
/* We don't use the byte-compiled Lua source
* because glib-compile-resources cannot output
* depends for generated files.
*
* There are also concerns that the bytecode is
* not stable enough between different Lua versions.
*
* https://bugzilla.gnome.org/show_bug.cgi?id=673101
*/
resource_path = g_strconcat ("/org/gnome/libpeas/loaders/lua5.1/",
name, NULL);
lua_resource = g_resources_lookup_data (resource_path,
G_RESOURCE_LOOKUP_FLAGS_NONE,
NULL);
g_free (resource_path);
if (lua_resource == NULL)
{
g_warning ("Failed to find '%s' resource", name);
return FALSE;
}
code = g_bytes_get_data (lua_resource, &code_len);
/* Filenames are prefixed with '@' */
lua_filename = g_strconcat ("@peas-lua-", name, NULL);
if (luaL_loadbuffer (L, code, code_len, lua_filename) != 0)
{
g_warning ("Failed to load '%s' resource: %s",
name, lua_tostring (L, -1));
/* Pop error */
lua_pop (L, 1);
g_free (lua_filename);
g_bytes_unref (lua_resource);
return FALSE;
}
g_free (lua_filename);
g_bytes_unref (lua_resource);
if (!peas_lua_utils_call (L, n_args, n_results))
{
g_warning ("Failed to run '%s' resource: %s",
name, lua_tostring (L, -1));
/* Pop error */
lua_pop (L, 1);
return FALSE;
}
return TRUE;
}
......@@ -40,6 +40,11 @@ gboolean peas_lua_utils_call (lua_State *L,
guint n_args,
guint n_results);
gboolean peas_lua_utils_load_resource (lua_State *L,
const gchar *name,
guint n_args,
guint n_results);
G_END_DECLS
#endif /* __PEAS_LUA_UTILS_H__ */
......@@ -285,7 +285,8 @@ peas_plugin_loader_lua_initialize (PeasPluginLoader *loader)
luaL_openlibs (L);
if (!peas_lua_utils_require (L, "lgi") ||
if (!peas_lua_utils_load_resource (L, "strict.lua", 0, 0) ||
!peas_lua_utils_require (L, "lgi") ||
!peas_lua_utils_check_version (L,
LGI_MAJOR_VERSION,
LGI_MINOR_VERSION,
......
LUAC_FILES = \
peas-lua-internal.luac \
peas-lua-strict.luac
%.luac: %.lua
$(AM_V_GEN) $(LUA51_BIN) $(srcdir)/peas-lua-compile.lua $< $@
all-local: $(LUAC_FILES)
CLEANFILES = \
$(LUAC_FILES)
......@@ -159,4 +159,4 @@ end
return Hooks.new()
-- ex:set ts=4 et sw=4 ai:
-- ex:ts=4:et:
--
-- Copyright (C) 2015 - Garrett Regier
--
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU Library General Public License as published by
-- the Free Software Foundation; either version 2 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU Library General Public License for more details.
--
-- You should have received a copy of the GNU Library General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 51 Franklin Street, Fifth Floor,
-- Boston, MA 02110-1301, USA.
--
-- Modified version of: http://metalua.luaforge.net/src/lib/strict.lua.html
__STRICT = true
local mt = getmetatable(_G)
if mt == nil then
mt = {}
setmetatable(_G, mt)
end
function mt:__newindex(name, value)
if __STRICT then
local what = debug.getinfo(2, 'S').what
if what ~= 'C' then
error("Attempted to create global variable '" ..
tostring(name) .. "'", 2)
end
end
rawset(self, name, value)
end
function mt:__index(name)
if not __STRICT or debug.getinfo(2, 'S').what == 'C' then
return rawget(self, name)
end
error("Attempted to access nonexistent " ..
"global variable '" .. tostring(name) .. "'", 2)
end
-- ex:ts=4:et:
......@@ -2,5 +2,6 @@
<gresources>
<gresource prefix="/org/gnome/libpeas/loaders/lua5.1">
<file alias="internal.lua">peas-lua-internal.lua</file>
<file alias="strict.lua">peas-lua-strict.lua</file>
</gresource>
</gresources>
......@@ -80,6 +80,27 @@ function ExtensionLuaPlugin:do_call_multi_args(in_, inout)
return inout, in_
end
-- Test strict mode
local UNIQUE = {}
local function assert_error(success, result)
assert(not success, result)
end
assert_error(pcall(function() _G[UNIQUE] = true end))
assert(pcall(function()
rawset(_G, UNIQUE, true)
assert(_G[UNIQUE] == true)
_G[UNIQUE] = nil
end))
assert_error(pcall(function() _G[UNIQUE] = true end))
assert(pcall(function()
__STRICT = false
_G[UNIQUE] = true
_G[UNIQUE] = nil
__STRICT = true
end))
return { ExtensionLuaPlugin }
-- ex:set ts=4 et sw=4 ai:
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment