]> git.proxmox.com Git - mirror_zfs.git/commitdiff
OpenZFS 9424 - ztest failure: "unprotected error in call to Lua API (Invalid value...
authorMatthew Ahrens <mahrens@delphix.com>
Mon, 7 Aug 2017 16:29:34 +0000 (09:29 -0700)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Wed, 11 Jul 2018 04:29:23 +0000 (21:29 -0700)
Ztest failed with the following crash.

    ::status

    debugging core file of ztest (64-bit) from clone-dc-slave-280-bc7947b1.dcenter
    file: /usr/bin/amd64/ztest
    initial argv: /usr/bin/amd64/ztest
    threading model: raw lwps
    status: process terminated by SIGABRT (Abort), pid=2150 uid=1025 code=-1
    panic message: failure for thread 0xfffffd7fff112a40, thread-id 1: unprotected error in call to Lua API (Invalid
    value type 'function' for key 'error')

    ::stack

    libc.so.1`_lwp_kill+0xa()
    libc.so.1`_assfail+0x182(fffffd7fffdfe8d0, 0, 0)
    libc.so.1`assfail+0x19(fffffd7fffdfe8d0, 0, 0)
    libzpool.so.1`vpanic+0x3d(fffffd7ffaa58c20fffffd7fffdfeb00)
    0xfffffd7ffaa28146()
    0xfffffd7ffaa0a109()
    libzpool.so.1`luaD_throw+0x86(3011a48, 2)
    0xfffffd7ffa9350d3()
    0xfffffd7ffa93e3f1()
    libzpool.so.1`zcp_lua_to_nvlist+0x33(3011a48, 1, 2686470fffffd7ffaa2e2c3)
    libzpool.so.1`zcp_convert_return_values+0xa4(3011a482686470fffffd7ffaa2e2c3fffffd7fffdfedd0)
    libzpool.so.1`zcp_pool_error+0x59(fffffd7fffdfedd01e0f450)
    libzpool.so.1`zcp_eval+0x6f8(1e0f450fffffd7ffaa483f8, 1, 0, 64000001d33b30)
    libzpool.so.1`dsl_destroy_snapshots_nvl+0x12c(2786b60, 0, 484750)
    libzpool.so.1`dsl_destroy_snapshot+0x4f(fffffd7fffdfef70, 0)
    ztest_dsl_dataset_cleanup+0xea(fffffd7fffdff4c0, 1)
    ztest_dataset_destroy+0x53(1)
    ztest_run+0x59f(fffffd7fff0e0498)
    main+0x7ff(1, fffffd7fffdffa88)
    _start+0x6c()

The problem is that zcp_convert_return_values() assumes that there's
exactly one value on the stack, but that isn't always true. It ends up
putting the wrong thing on the stack which is then consumed by
zcp_convert_return values, which either adds the wrong message to the
nvlist, or blows up.

The fix is to make sure that callers of zcp_convert_return_values()
clear the stack before pushing their error message, and
zcp_convert_return_values() should VERIFY that the stack is the expected
size.

Authored by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Sebastien Roy <sebastien.roy@delphix.com>
Reviewed by: Paul Dagnelie <pcd@delphix.com>
Reviewed by: Don Brady <don.brady@delphix.com>
Ported-by: Brian Behlendorf <behlendorf1@llnl.gov>
Approved by: Robert Mustacchi <rm@joyent.com>

OpenZFS-issue: https://www.illumos.org/issues/9424
OpenZFS-commit: https://github.com/openzfs/openzfs/commit/eb7e57429
Closes #7696

module/zfs/zcp.c

index 4751386217185710d8c38d31f3303453fa5f9c64..4894df11d5fb56a8643092d0cac3fed04030bfd8 100644 (file)
@@ -429,7 +429,7 @@ zcp_lua_to_nvlist_impl(lua_State *state, int index, nvlist_t *nvl,
 /*
  * Convert a lua value to an nvpair, adding it to an nvlist with the given key.
  */
-void
+static void
 zcp_lua_to_nvlist(lua_State *state, int index, nvlist_t *nvl, const char *key)
 {
        /*
@@ -441,7 +441,7 @@ zcp_lua_to_nvlist(lua_State *state, int index, nvlist_t *nvl, const char *key)
                (void) lua_error(state);
 }
 
-int
+static int
 zcp_lua_to_nvlist_helper(lua_State *state)
 {
        nvlist_t *nv = (nvlist_t *)lua_touserdata(state, 2);
@@ -450,11 +450,12 @@ zcp_lua_to_nvlist_helper(lua_State *state)
        return (0);
 }
 
-void
+static void
 zcp_convert_return_values(lua_State *state, nvlist_t *nvl,
     const char *key, zcp_eval_arg_t *evalargs)
 {
        int err;
+       VERIFY3U(1, ==, lua_gettop(state));
        lua_pushcfunction(state, zcp_lua_to_nvlist_helper);
        lua_pushlightuserdata(state, (char *)key);
        lua_pushlightuserdata(state, nvl);
@@ -900,6 +901,7 @@ zcp_eval_impl(dmu_tx_t *tx, boolean_t sync, zcp_eval_arg_t *evalargs)
                            ZCP_RET_RETURN, evalargs);
                } else if (return_count > 1) {
                        evalargs->ea_result = SET_ERROR(ECHRNG);
+                       lua_settop(state, 0);
                        (void) lua_pushfstring(state, "Multiple return "
                            "values not supported");
                        zcp_convert_return_values(state, evalargs->ea_outnvl,
@@ -967,6 +969,7 @@ static void
 zcp_pool_error(zcp_eval_arg_t *evalargs, const char *poolname)
 {
        evalargs->ea_result = SET_ERROR(ECHRNG);
+       lua_settop(evalargs->ea_state, 0);
        (void) lua_pushfstring(evalargs->ea_state, "Could not open pool: %s",
            poolname);
        zcp_convert_return_values(evalargs->ea_state, evalargs->ea_outnvl,