Skip to content

Commit

Permalink
Catch runaway forked children from Lua scriptlets centrally
Browse files Browse the repository at this point in the history
Commit 2d418ad added a safety catch
for runaway children from package scriptlets, but we have many other
ways to run Lua scriptlets too, and runaway children are equally harmful
in them all. Catch them all centrally by wrapping lua_pcall() instead.

Besides handling more cases, there are a couple of more subtle
improvements here: rpmlog() in a child process is undefined behavior
due to the locking it does, but also nonsensical - rpmlog() is more than
fprintf() and any warnings/errors it collects end up in the wrong process.
Check and log from the parent instead.

Finally, make it a warning instead of an error because we're not failing
the scriptlet because of this, and make the message more generic as
besides exec(), this can be avoided by waiting for the child in
the script too.
  • Loading branch information
pmatilai authored and ffesti committed Mar 13, 2023
1 parent 45103f8 commit a810765
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 13 deletions.
6 changes: 0 additions & 6 deletions lib/rpmscript.c
Original file line number Diff line number Diff line change
Expand Up @@ -160,17 +160,11 @@ static rpmRC runLuaScript(rpmPlugins plugins, ARGV_const_t prefixes,
if (cwd != -1) {
mode_t oldmask = umask(0);
umask(oldmask);
pid_t pid = getpid();

if (chdir("/") == 0 &&
rpmluaRunScript(lua, script, sname, NULL, *argvp) == 0) {
rc = RPMRC_OK;
}
if (pid != getpid()) {
/* Terminate child process forked in lua scriptlet */
rpmlog(RPMLOG_ERR, _("No exec() called after fork() in lua scriptlet\n"));
_exit(EXIT_FAILURE);
}
/* This failing would be fatal, return something different for it... */
if (fchdir(cwd)) {
rpmlog(RPMLOG_ERR, _("Unable to restore current directory: %m"));
Expand Down
33 changes: 26 additions & 7 deletions rpmio/rpmlua.c
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,25 @@ static int luaopt(int c, const char *oarg, int oint, void *data)
return 0;
}

static int rpm_pcall(lua_State *L, int nargs, int nresults, int errfunc)
{
pid_t pid = getpid();
int status;

int rc = lua_pcall(L, nargs, nresults, errfunc);

/* Terminate unhandled fork from Lua script */
if (pid != getpid())
_exit(1);

if (waitpid(0, &status, WNOHANG) == 0) {
rpmlog(RPMLOG_WARNING,
_("runaway fork() in Lua script\n"));
}

return rc;
}

int rpmluaRunScript(rpmlua lua, const char *script, const char *name,
const char *opts, ARGV_t args)
{
Expand Down Expand Up @@ -290,7 +309,7 @@ int rpmluaRunScript(rpmlua lua, const char *script, const char *name,
}
}

if (lua_pcall(L, 2, LUA_MULTRET, 0) != 0) {
if (rpm_pcall(L, 2, LUA_MULTRET, 0) != 0) {
rpmlog(RPMLOG_ERR, _("lua script failed: %s\n"),
lua_tostring(L, -1));
lua_pop(L, 1);
Expand All @@ -301,7 +320,7 @@ int rpmluaRunScript(rpmlua lua, const char *script, const char *name,
if (nret > 0 && lua->printbuf) {
lua_getglobal(L, "print");
lua_insert(L, -(nret + 1));
if (lua_pcall(L, nret, 0, 0) != 0) {
if (rpm_pcall(L, nret, 0, 0) != 0) {
rpmlog(RPMLOG_ERR, _("result print failed: %s\n"),
lua_tostring(L, -1));
lua_pop(L, 1);
Expand All @@ -326,7 +345,7 @@ int rpmluaRunScriptFile(rpmlua lua, const char *filename)
lua_tostring(L, -1));
lua_pop(L, 1);
ret = -1;
} else if (lua_pcall(L, 0, 0, 0) != 0) {
} else if (rpm_pcall(L, 0, 0, 0) != 0) {
rpmlog(RPMLOG_ERR, _("lua script failed: %s\n"),
lua_tostring(L, -1));
lua_pop(L, 1);
Expand Down Expand Up @@ -392,7 +411,7 @@ static void _rpmluaInteractive(lua_State *L, rpmluarl rlcb)
break;
}
if (rc == 0)
rc = lua_pcall(L, 0, 0, 0);
rc = rpm_pcall(L, 0, 0, 0);
if (rc != 0) {
fprintf(stderr, "%s\n", lua_tostring(L, -1));
lua_pop(L, 1);
Expand Down Expand Up @@ -448,7 +467,7 @@ char *rpmluaCallStringFunction(rpmlua lua, const char *function, rpmhookArgs arg
}

/* run the call */
if (lua_pcall(L, args->argc, 1, 0) != 0) {
if (rpm_pcall(L, args->argc, 1, 0) != 0) {
rpmlog(RPMLOG_ERR, "%s: %s\n", function, lua_tostring(L, -1));
lua_pop(L, 1);
return NULL;
Expand All @@ -462,7 +481,7 @@ char *rpmluaCallStringFunction(rpmlua lua, const char *function, rpmhookArgs arg
} else {
lua_getglobal(L, "tostring");
lua_insert(L, -2);
if (lua_pcall(L, 1, 1, 0) != 0) {
if (rpm_pcall(L, 1, 1, 0) != 0) {
rpmlog(RPMLOG_ERR, "%s: %s\n", function, lua_tostring(L, -1));
lua_pop(L, 1);
return NULL;
Expand Down Expand Up @@ -664,7 +683,7 @@ static int rpmluaHookWrapper(rpmhookArgs args, void *data)
}
lua_rawseti(L, -2, i+1);
}
if (lua_pcall(L, 1, 1, 0) != 0) {
if (rpm_pcall(L, 1, 1, 0) != 0) {
rpmlog(RPMLOG_ERR, _("lua hook failed: %s\n"),
lua_tostring(L, -1));
lua_pop(L, 1);
Expand Down

0 comments on commit a810765

Please sign in to comment.