Skip to content

Conversation

@Desour
Copy link
Member

@Desour Desour commented Mar 6, 2022

  • Goal of the PR: Improvement of the SSM sandbox security.
  • How does the PR work:
    • debug.getmetatable and debug.setmetatable are overwritten in builtin to use the "__metatable_debug" field like getmetatable and setmetatable use the "__metatable" field.
    • Userdata metatables have now the same value for "__metatable_debug" as for "__metatable". This prevents mods from doing nasty stuff like overwriting or replacing "__gc" metatable fields.
      (The "__metatable" fields had basically no effect.)
    • (We still have to leave debug.g/setmetatable in the sandbox because we want to allow to overwrite the string metatable.)
  • Does it resolve any reported issue: Idk.
  • If not a bug fix, why is this PR needed? What usecases does it solve? It can be considered a (security-related) bugfix.

To do

This PR is a Ready for Review.

How to test

  • Check that your mods still work.
  • Read the code.
  • Read the doc changes.

@Desour Desour force-pushed the restrict_debug_gsetmetatable branch from 0719b5c to cb1491d Compare March 6, 2022 20:02
@Desour
Copy link
Member Author

Desour commented Mar 7, 2022

Now they are not overwritten iff mod security is off. In that case, _G is the insecure env, and we don't want to restrict it.

@sfan5 sfan5 added @ Script API Feature ✨ PRs that add or enhance a feature labels Mar 8, 2022
@rubenwardy rubenwardy added the Roadmap: Needs approval The change is not part of the current roadmap and needs to be approved by coredevs beforehand label Apr 24, 2022
@rubenwardy
Copy link
Contributor

I find this change highly questionable. Shouldn't we just remove these functions from the sandbox if there's concern over security?

@Desour
Copy link
Member Author

Desour commented Apr 24, 2022

I didn't know how often these functions are used. IIRC there was a discussion in irc about this, where someone (you?) said that they're (almost?) nowhere used. (Ie. mesecons just uses the normal getmetatable on strings.) Hence, I'm fine with completely removing them. I kept this PR open as a reminder that the issue still exists. Also IIRC there was someone who wanted the functions to stay to do some weird stuff with functions.

@sfan5
Copy link
Collaborator

sfan5 commented Apr 24, 2022

To properly discuss this it'd be useful if someone (@appgurueu?) could sum up on what types [gs]etmetable and debug\.[gs]etmetatable work.

@appgurueu
Copy link
Contributor

To properly discuss this it'd be useful if someone (@appgurueu?) could sum up on what types [gs]etmetable and debug\.[gs]etmetatable work.

setmetatable only works on tables and respects the __metatable field, erroring if called on tables that have it set in their metatable. getmetatable also works on other types (strings, for example). It is possible to retrieve metatables set via debug.setmetatable using just getmetatable. getmetatable respects the __metatable field and returns its value instead if set, whereas debug.getmetatable and debug.setmetatable do not respect this field, operating on the raw metatable instead. The debug.* functions also work on pretty much all types and allow replacing/changing/setting string, number, boolean, nil metatables as well as function (for all functions). Full userdata, like tables, has individual metatables per instance, which can be set/get using the debug metatable funcs.

Example:

> t = setmetatable({}, {__metatable = 42})
> =getmetatable(t)
42
> =debug.getmetatable(t)
table: 0x55d51c5c4060
> setmetatable(t, {})
stdin:1: cannot change a protected metatable
stack traceback:
	[C]: in function 'setmetatable'
	stdin:1: in main chunk
	[C]: ?
> debug.setmetatable(t, {})

Further resources: pgimeno's metatable tutorial and the Lua reference manual

]]

-- Overwrite debug.getmetatable and debug.setmetatable, so that they have the same
-- semantics with the metatable field "__metatable_debug" as getmetatable and
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not respect the __metatable field?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To give more control. And theoretically there could be a mod that does some hacky, but valid, stuff with another mod's object.

If we want to keep debug.setmetatable just for non-table objects and nothing else, using __metatable might be better.

@rubenwardy rubenwardy removed the Roadmap: Needs approval The change is not part of the current roadmap and needs to be approved by coredevs beforehand label May 5, 2022
@Desour
Copy link
Member Author

Desour commented May 29, 2022

Underlying issue (#12216) was fixed, closing.

@Desour Desour closed this May 29, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Feature ✨ PRs that add or enhance a feature Possible close @ Script API

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants