lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On 24/06/2019 19.16, Viacheslav Usov wrote:
The following code, [simplified]

getmetatable(io.stdin).__gc = nil

prevents the built-in IO library's finalizers from running on all
the handles created subsequently…

I believe this […] is a problem because Lua code should not be able to make C libraries leak resources.

I do not think this is a problem.  If you mess with other people's
code's internals, don't be surprised if it breaks.

It boils down to this:  Do you trust the user to not intentionally break
things?

If yes, there is no problem.

If no, they shouldn't be running ANY kind of turing-complete code, or at
the very least you should mercilessly sandbox them.


[reordered]
With the sample code in PiL and well-known Lua libraries having this
problem as illustrated above, we seem to have a well-established unsafe paradigm and the question is how we can get out of this trouble.

For all people running the standard Lua interpreter, there is no
problem.  Even if everything was "protected" by __metatable, a simple

  debug.getmetatable(io.stdin).__gc = nil

would still produce the same behavior.  Even if you're in a somewhat
protected environment without debug.*, if you can load C modules, you
can still (re-)expose `lua_getmetatable`.

If even that is prevented, I'm gonna call that a sandbox.  Most likely a
broken / insecure one, but a sandbox – NOT a standard Lua environment.


The ultimate problem is […that…] the metatable is modifiable.

This is a GOOD thing.  I can't remember how often I had to add __index,
__pairs, __tostring, … or added custom metamethods to make some other
library work with my code.



I do not think the problem is addressed in the manual (__metatable is, in my opinion, not mentioned where it should, nor is its purpose stressed at all).

Basically every time someone used __metatable, that broke or seriously
interfered with my metaprogramming.

Most often, the value set as __meta"table" is NOT EVEN A TABLE.  Which
means that any custom function that uses a metamethod for customization
(like tostring / __tostring, pairs / __pairs do) cannot rely on the
interface enforced by setmetatable (the metatable MUST be nil or a
table) but has to explicitly check if someone messed with that, before
it can proceed to check if the custom metamethod is available.

Even if it is a table, you'll have a hard(er) time adding your own
metamethods (in such a way that BOTH Lua and C code can see them), which
means those "protected" values will either be second-class citizens that
need yet another dummy wrapper around them (making everything bigger and
slower) or you'll have to poke at it with debug.getmetatable (if you
can)…  Both are painful.

(
And yes, you *could* set a __metatable worthy of its name that permits
reading all non-critical fields, that permits adding safe fields
(anything that's not Lua core) and thus does not impede metaprogramming.
(A bit of __index, __pairs, __newindex and maybe one or two sets of
names as blacklist / graylist would do the job.)  But let's be honest,
no one is going to bother doing that when (it seems to them that)
__metatable = "HAHA protected!" achieves what they care about.  (Also,
that would be a metatable on the __metatable in a metatable, the former
potentially also protected by a __metatable…  I guess some people's
heads would just explode.)
)

-- nobody