Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lua: remove default search path for output modules - v1 #12563

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions doc/userguide/output/lua-output.rst
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ Example:
file:close(file)
end

.. _lua-output-yaml:

YAML
----

Expand All @@ -87,6 +89,15 @@ scripts like so:
- lua:
enabled: yes
scripts-dir: /etc/suricata/lua-output/

# By default the Lua module search paths are empty. If you plan
# to use external modules these paths will need to be set. The
# examples below are likely suitable for finding modules
# installed with a package manager on a 64 bit Linux system, but
# may need tweaking.
#path: "/usr/share/lua/5.4/?.lua;/usr/share/lua/5.4/?/init.lua;/usr/lib64/lua/5.4/?.lua;/usr/lib64/lua/5.4/?/init.lua;./?.lua;./?/init.lua"
#cpath: "/usr/lib64/lua/5.4/?.so;/usr/lib64/lua/5.4/loadall.so;./?.so"

scripts:
- tcp-data.lua
- flow.lua
Expand Down
6 changes: 6 additions & 0 deletions doc/userguide/upgrade.rst
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,12 @@ Major changes
Suricata 8.0, ``stream.checksum-validation`` no longer affects the checksum rule keywords.
E.g., ``ipv4-csum: valid`` will only match if the check sum is valid, even when engine
checksum validations are disabled.
- Lua detection scripts (rules) now run in a sandboxed
environment. See :ref:`lua-detection`.
- Lua output scripts have no default module search path, a search path
will need to be set before external modules can be loaded. See the
new default configuration file or :ref:`lua-output-yaml` for more
details.

Removals
~~~~~~~~
Expand Down
76 changes: 58 additions & 18 deletions src/output-lua.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,12 @@
#include "output-lua.h"

#include "util-lua-builtins.h"
#include "util-print.h"
#include "util-unittest.h"
#include "util-debug.h"
#include "output.h"
#include "app-layer-htp.h"
#include "app-layer.h"
#include "app-layer-ssl.h"
#include "app-layer-ssh.h"
#include "app-layer-parser.h"
#include "util-privs.h"
#include "util-buffer.h"
#include "util-proto-name.h"
#include "util-logopenfile.h"
#include "util-time.h"
#include "util-lua.h"
#include "util-lua-common.h"
Expand All @@ -58,7 +51,14 @@
* it's parent_ctx->data ptr.
*/
typedef struct LogLuaMasterCtx_ {
char path[PATH_MAX]; /**< contains script-dir */
/** \brief Path to script directory. */
char script_dir[PATH_MAX];

/** \brief Lua search path for Lua modules. */
char path[PATH_MAX];

/** \brief Lua search path for C modules. */
char cpath[PATH_MAX];
} LogLuaMasterCtx;

typedef struct LogLuaCtx_ {
Expand Down Expand Up @@ -403,6 +403,33 @@ typedef struct LogLuaScriptOptions_ {
int stats;
} LogLuaScriptOptions;

/** \brief Setup or clear Lua module search paths.
*
* If search paths are provided by the configuration, set them up,
* otherwise clear the default search paths.
*/
static void LuaSetPaths(lua_State *L, LogLuaMasterCtx *ctx)
{
lua_getglobal(L, "package");

if (strlen(ctx->path) > 0) {
lua_pushstring(L, ctx->path);
} else {
lua_pushstring(L, "");
}
lua_setfield(L, -2, "path");

if (strlen(ctx->cpath) > 0) {
lua_pushstring(L, ctx->cpath);
} else {
lua_pushstring(L, "");
}
lua_setfield(L, -2, "cpath");

/* Pop package. */
lua_pop(L, 1);
}

/** \brief load and evaluate the script
*
* This function parses the script, checks if all the required functions
Expand All @@ -413,12 +440,14 @@ typedef struct LogLuaScriptOptions_ {
* \param options struct to pass script requirements/options back to caller
* \retval errcode 0 ok, -1 error
*/
static int LuaScriptInit(const char *filename, LogLuaScriptOptions *options) {
static int LuaScriptInit(const char *filename, LogLuaScriptOptions *options, LogLuaMasterCtx *ctx)
{
lua_State *luastate = LuaGetState();
if (luastate == NULL)
goto error;
luaL_openlibs(luastate);
SCLuaRequirefBuiltIns(luastate);
LuaSetPaths(luastate, ctx);

int status = luaL_loadfile(luastate, filename);
if (status) {
Expand Down Expand Up @@ -544,7 +573,7 @@ static int LuaScriptInit(const char *filename, LogLuaScriptOptions *options) {
*
* \retval state Returns the set up luastate on success, NULL on error
*/
static lua_State *LuaScriptSetup(const char *filename)
static lua_State *LuaScriptSetup(const char *filename, LogLuaMasterCtx *ctx)
{
lua_State *luastate = LuaGetState();
if (luastate == NULL) {
Expand All @@ -554,6 +583,7 @@ static lua_State *LuaScriptSetup(const char *filename)

luaL_openlibs(luastate);
SCLuaRequirefBuiltIns(luastate);
LuaSetPaths(luastate, ctx);

int status = luaL_loadfile(luastate, filename);
if (status) {
Expand Down Expand Up @@ -622,12 +652,11 @@ static OutputInitResult OutputLuaLogInitSub(ConfNode *conf, OutputCtx *parent_ct

SCMutexInit(&lua_ctx->m, NULL);

const char *dir = "";
if (parent_ctx && parent_ctx->data) {
LogLuaMasterCtx *mc = parent_ctx->data;
dir = mc->path;
}
BUG_ON(parent_ctx == NULL);
LogLuaMasterCtx *mc = parent_ctx->data;
BUG_ON(mc == NULL);

const char *dir = mc->script_dir;
char path[PATH_MAX] = "";
int ret = snprintf(path, sizeof(path),"%s%s%s", dir, strlen(dir) ? "/" : "", conf->val);
if (ret < 0 || ret == sizeof(path)) {
Expand All @@ -637,7 +666,7 @@ static OutputInitResult OutputLuaLogInitSub(ConfNode *conf, OutputCtx *parent_ct
SCLogDebug("script full path %s", path);

SCMutexLock(&lua_ctx->m);
lua_ctx->luastate = LuaScriptSetup(path);
lua_ctx->luastate = LuaScriptSetup(path, mc);
SCMutexUnlock(&lua_ctx->m);
if (lua_ctx->luastate == NULL)
goto error;
Expand Down Expand Up @@ -702,7 +731,18 @@ static OutputInitResult OutputLuaLogInit(ConfNode *conf)
return result;
}
LogLuaMasterCtx *master_config = output_ctx->data;
strlcpy(master_config->path, dir, sizeof(master_config->path));
strlcpy(master_config->script_dir, dir, sizeof(master_config->script_dir));

const char *lua_path = ConfNodeLookupChildValue(conf, "path");
if (lua_path && strlen(lua_path) > 0) {
strlcpy(master_config->path, lua_path, sizeof(master_config->path));
}

const char *lua_cpath = ConfNodeLookupChildValue(conf, "cpath");
if (lua_cpath && strlen(lua_cpath) > 0) {
strlcpy(master_config->cpath, lua_cpath, sizeof(master_config->cpath));
}

TAILQ_INIT(&output_ctx->submodules);

/* check the enables scripts and set them up as submodules */
Expand All @@ -716,7 +756,7 @@ static OutputInitResult OutputLuaLogInit(ConfNode *conf)
snprintf(path, sizeof(path),"%s%s%s", dir, strlen(dir) ? "/" : "", script->val);
SCLogDebug("script full path %s", path);

int r = LuaScriptInit(path, &opts);
int r = LuaScriptInit(path, &opts, master_config);
if (r != 0) {
SCLogError("couldn't initialize script");
goto error;
Expand Down
9 changes: 9 additions & 0 deletions suricata.yaml.in
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,15 @@ outputs:
# https://docs.suricata.io/en/latest/output/lua-output.html
- lua:
enabled: no

# By default the Lua module search paths are empty. If you plan
# to use external modules these paths will need to be set. The
# examples below are likely suitable for finding modules
# installed with a package manager on a 64 bit Linux system, but
# may need tweaking.
#path: "/usr/share/lua/5.4/?.lua;/usr/share/lua/5.4/?/init.lua;/usr/lib64/lua/5.4/?.lua;/usr/lib64/lua/5.4/?/init.lua;./?.lua;./?/init.lua"
#cpath: "/usr/lib64/lua/5.4/?.so;/usr/lib64/lua/5.4/loadall.so;./?.so"

#scripts-dir: /etc/suricata/lua-output/
scripts:
# - script1.lua
Expand Down
Loading