diff options
author | Matthew Ahrens <[email protected]> | 2020-07-27 16:11:47 -0700 |
---|---|---|
committer | GitHub <[email protected]> | 2020-07-27 16:11:47 -0700 |
commit | 3eabed74c0fca5dd9f96d2cca13c4a1a16d5c094 (patch) | |
tree | dac524f95cbf222459729fa6af23b2df2d39ac85 /module/lua/lstate.h | |
parent | e64cc4954c7862db6a6b4dc978a091ebc3f870da (diff) |
Fix lua stack overflow on recursive call to gsub()
The `zfs program` subcommand invokes a LUA interpreter to run ZFS
"channel programs". This interpreter runs in a constrained environment,
with defined memory limits. The LUA stack (used for LUA functions that
call each other) is allocated in the kernel's heap, and is limited by
the `-m MEMORY-LIMIT` flag and the `zfs_lua_max_memlimit` module
parameter. The C stack is used by certain LUA features that are
implemented in C. The C stack is limited by `LUAI_MAXCCALLS=20`, which
limits call depth.
Some LUA C calls use more stack space than others, and `gsub()` uses an
unusually large amount. With a programming trick, it can be invoked
recursively using the C stack (rather than the LUA stack). This
overflows the 16KB Linux kernel stack after about 11 iterations, less
than the limit of 20.
One solution would be to decrease `LUAI_MAXCCALLS`. This could be made
to work, but it has a few drawbacks:
1. The existing test suite does not pass with `LUAI_MAXCCALLS=10`.
2. There may be other LUA functions that use a lot of stack space, and
the stack space may change depending on compiler version and options.
This commit addresses the problem by adding a new limit on the amount of
free space (in bytes) remaining on the C stack while running the LUA
interpreter: `LUAI_MINCSTACK=4096`. If there is less than this amount
of stack space remaining, a LUA runtime error is generated.
Reviewed-by: George Wilson <[email protected]>
Reviewed-by: Brian Behlendorf <[email protected]>
Reviewed-by: Ryan Moeller <[email protected]>
Reviewed-by: Allan Jude <[email protected]>
Reviewed-by: Serapheim Dimitropoulos <[email protected]>
Signed-off-by: Matthew Ahrens <[email protected]>
Closes #10611
Closes #10613
Diffstat (limited to 'module/lua/lstate.h')
-rw-r--r-- | module/lua/lstate.h | 1 |
1 files changed, 1 insertions, 0 deletions
diff --git a/module/lua/lstate.h b/module/lua/lstate.h index 22e575e9a..b636396a6 100644 --- a/module/lua/lstate.h +++ b/module/lua/lstate.h @@ -166,6 +166,7 @@ struct lua_State { unsigned short nCcalls; /* number of nested C calls */ lu_byte hookmask; lu_byte allowhook; + lu_byte runerror; /* handling a runtime error */ int basehookcount; int hookcount; lua_Hook hook; |