17899f917SBaptiste Daroussin /*-
27899f917SBaptiste Daroussin * SPDX-License-Identifier: BSD-2-Clause
37899f917SBaptiste Daroussin *
47899f917SBaptiste Daroussin * Copyright (c) 2020, Ryan Moeller <freqlabs@FreeBSD.org>
57899f917SBaptiste Daroussin * Copyright (c) 2020, Kyle Evans <kevans@FreeBSD.org>
67899f917SBaptiste Daroussin *
77899f917SBaptiste Daroussin * Redistribution and use in source and binary forms, with or without
87899f917SBaptiste Daroussin * modification, are permitted provided that the following conditions
97899f917SBaptiste Daroussin * are met:
107899f917SBaptiste Daroussin * 1. Redistributions of source code must retain the above copyright
117899f917SBaptiste Daroussin * notice, this list of conditions and the following disclaimer.
127899f917SBaptiste Daroussin * 2. Redistributions in binary form must reproduce the above copyright
137899f917SBaptiste Daroussin * notice, this list of conditions and the following disclaimer in the
147899f917SBaptiste Daroussin * documentation and/or other materials provided with the distribution.
157899f917SBaptiste Daroussin *
167899f917SBaptiste Daroussin * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
177899f917SBaptiste Daroussin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
187899f917SBaptiste Daroussin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
197899f917SBaptiste Daroussin * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
207899f917SBaptiste Daroussin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
217899f917SBaptiste Daroussin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
227899f917SBaptiste Daroussin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
237899f917SBaptiste Daroussin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
247899f917SBaptiste Daroussin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
257899f917SBaptiste Daroussin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
267899f917SBaptiste Daroussin * SUCH DAMAGE.
277899f917SBaptiste Daroussin */
287899f917SBaptiste Daroussin
297899f917SBaptiste Daroussin #include <sys/param.h>
307899f917SBaptiste Daroussin #include <sys/jail.h>
317899f917SBaptiste Daroussin #include <errno.h>
327899f917SBaptiste Daroussin #include <jail.h>
337899f917SBaptiste Daroussin #include <stdbool.h>
347899f917SBaptiste Daroussin #include <stdlib.h>
357899f917SBaptiste Daroussin #include <string.h>
367899f917SBaptiste Daroussin
377899f917SBaptiste Daroussin #include <lua.h>
387899f917SBaptiste Daroussin #include <lauxlib.h>
397899f917SBaptiste Daroussin #include <lualib.h>
407899f917SBaptiste Daroussin
417899f917SBaptiste Daroussin #define JAIL_METATABLE "jail iterator metatable"
427899f917SBaptiste Daroussin
437899f917SBaptiste Daroussin /*
447899f917SBaptiste Daroussin * Taken from RhodiumToad's lspawn implementation, let static analyzers make
457899f917SBaptiste Daroussin * better decisions about the behavior after we raise an error.
467899f917SBaptiste Daroussin */
477899f917SBaptiste Daroussin #if defined(LUA_VERSION_NUM) && defined(LUA_API)
487899f917SBaptiste Daroussin LUA_API int (lua_error) (lua_State *L) __dead2;
497899f917SBaptiste Daroussin #endif
507899f917SBaptiste Daroussin #if defined(LUA_ERRFILE) && defined(LUALIB_API)
517899f917SBaptiste Daroussin LUALIB_API int (luaL_argerror) (lua_State *L, int arg, const char *extramsg) __dead2;
527899f917SBaptiste Daroussin LUALIB_API int (luaL_typeerror) (lua_State *L, int arg, const char *tname) __dead2;
537899f917SBaptiste Daroussin LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...) __dead2;
547899f917SBaptiste Daroussin #endif
557899f917SBaptiste Daroussin
567899f917SBaptiste Daroussin int luaopen_jail(lua_State *);
577899f917SBaptiste Daroussin
587899f917SBaptiste Daroussin typedef bool (*getparam_filter)(const char *, void *);
597899f917SBaptiste Daroussin
607899f917SBaptiste Daroussin static void getparam_table(lua_State *L, int paramindex,
617899f917SBaptiste Daroussin struct jailparam *params, size_t paramoff, size_t *params_countp,
627899f917SBaptiste Daroussin getparam_filter keyfilt, void *udata);
637899f917SBaptiste Daroussin
647899f917SBaptiste Daroussin struct l_jail_iter {
657899f917SBaptiste Daroussin struct jailparam *params;
667899f917SBaptiste Daroussin size_t params_count;
677899f917SBaptiste Daroussin int jid;
687899f917SBaptiste Daroussin };
697899f917SBaptiste Daroussin
707899f917SBaptiste Daroussin static bool
l_jail_filter(const char * param_name,void * data __unused)717899f917SBaptiste Daroussin l_jail_filter(const char *param_name, void *data __unused)
727899f917SBaptiste Daroussin {
737899f917SBaptiste Daroussin
747899f917SBaptiste Daroussin /*
757899f917SBaptiste Daroussin * Allowing lastjid will mess up our iteration over all jails on the
767899f917SBaptiste Daroussin * system, as this is a special parameter that indicates where the search
777899f917SBaptiste Daroussin * starts from. We'll always add jid and name, so just silently remove
787899f917SBaptiste Daroussin * these.
797899f917SBaptiste Daroussin */
807899f917SBaptiste Daroussin return (strcmp(param_name, "lastjid") != 0 &&
817899f917SBaptiste Daroussin strcmp(param_name, "jid") != 0 &&
827899f917SBaptiste Daroussin strcmp(param_name, "name") != 0);
837899f917SBaptiste Daroussin }
847899f917SBaptiste Daroussin
857899f917SBaptiste Daroussin static int
l_jail_iter_next(lua_State * L)867899f917SBaptiste Daroussin l_jail_iter_next(lua_State *L)
877899f917SBaptiste Daroussin {
887899f917SBaptiste Daroussin struct l_jail_iter *iter, **iterp;
897899f917SBaptiste Daroussin struct jailparam *jp;
907899f917SBaptiste Daroussin int serrno;
917899f917SBaptiste Daroussin
927899f917SBaptiste Daroussin iterp = (struct l_jail_iter **)luaL_checkudata(L, 1, JAIL_METATABLE);
937899f917SBaptiste Daroussin iter = *iterp;
947899f917SBaptiste Daroussin luaL_argcheck(L, iter != NULL, 1, "closed jail iterator");
957899f917SBaptiste Daroussin
967899f917SBaptiste Daroussin jp = iter->params;
977899f917SBaptiste Daroussin /* Populate lastjid; we must keep it in params[0] for our sake. */
987899f917SBaptiste Daroussin if (jailparam_import_raw(&jp[0], &iter->jid, sizeof(iter->jid))) {
997899f917SBaptiste Daroussin jailparam_free(jp, iter->params_count);
1007899f917SBaptiste Daroussin free(jp);
1017899f917SBaptiste Daroussin free(iter);
1027899f917SBaptiste Daroussin *iterp = NULL;
1037899f917SBaptiste Daroussin return (luaL_error(L, "jailparam_import_raw: %s", jail_errmsg));
1047899f917SBaptiste Daroussin }
1057899f917SBaptiste Daroussin
1067899f917SBaptiste Daroussin /* The list of requested params was populated back in l_list(). */
1077899f917SBaptiste Daroussin iter->jid = jailparam_get(jp, iter->params_count, 0);
1087899f917SBaptiste Daroussin if (iter->jid == -1) {
1097899f917SBaptiste Daroussin /*
1107899f917SBaptiste Daroussin * We probably got an ENOENT to signify the end of the jail
1117899f917SBaptiste Daroussin * listing, but just in case we didn't; stash it off and start
1127899f917SBaptiste Daroussin * cleaning up. We'll handle non-ENOENT errors later.
1137899f917SBaptiste Daroussin */
1147899f917SBaptiste Daroussin serrno = errno;
1157899f917SBaptiste Daroussin jailparam_free(jp, iter->params_count);
1167899f917SBaptiste Daroussin free(iter->params);
1177899f917SBaptiste Daroussin free(iter);
1187899f917SBaptiste Daroussin *iterp = NULL;
1197899f917SBaptiste Daroussin if (serrno != ENOENT)
1207899f917SBaptiste Daroussin return (luaL_error(L, "jailparam_get: %s",
1217899f917SBaptiste Daroussin strerror(serrno)));
1227899f917SBaptiste Daroussin return (0);
1237899f917SBaptiste Daroussin }
1247899f917SBaptiste Daroussin
1257899f917SBaptiste Daroussin /*
1267899f917SBaptiste Daroussin * Finally, we'll fill in the return table with whatever parameters the
1277899f917SBaptiste Daroussin * user requested, in addition to the ones we forced with exception to
1287899f917SBaptiste Daroussin * lastjid.
1297899f917SBaptiste Daroussin */
1307899f917SBaptiste Daroussin lua_newtable(L);
1317899f917SBaptiste Daroussin for (size_t i = 0; i < iter->params_count; ++i) {
1327899f917SBaptiste Daroussin char *value;
1337899f917SBaptiste Daroussin
1347899f917SBaptiste Daroussin jp = &iter->params[i];
1357899f917SBaptiste Daroussin if (strcmp(jp->jp_name, "lastjid") == 0)
1367899f917SBaptiste Daroussin continue;
1377899f917SBaptiste Daroussin value = jailparam_export(jp);
1387899f917SBaptiste Daroussin lua_pushstring(L, value);
1397899f917SBaptiste Daroussin lua_setfield(L, -2, jp->jp_name);
1407899f917SBaptiste Daroussin free(value);
1417899f917SBaptiste Daroussin }
1427899f917SBaptiste Daroussin
1437899f917SBaptiste Daroussin return (1);
1447899f917SBaptiste Daroussin }
1457899f917SBaptiste Daroussin
1467899f917SBaptiste Daroussin static int
l_jail_iter_close(lua_State * L)1477899f917SBaptiste Daroussin l_jail_iter_close(lua_State *L)
1487899f917SBaptiste Daroussin {
1497899f917SBaptiste Daroussin struct l_jail_iter *iter, **iterp;
1507899f917SBaptiste Daroussin
1517899f917SBaptiste Daroussin /*
1527899f917SBaptiste Daroussin * Since we're using this as the __gc method as well, there's a good
1537899f917SBaptiste Daroussin * chance that it's already been cleaned up by iterating to the end of
1547899f917SBaptiste Daroussin * the list.
1557899f917SBaptiste Daroussin */
1567899f917SBaptiste Daroussin iterp = (struct l_jail_iter **)lua_touserdata(L, 1);
1577899f917SBaptiste Daroussin iter = *iterp;
1587899f917SBaptiste Daroussin if (iter == NULL)
1597899f917SBaptiste Daroussin return (0);
1607899f917SBaptiste Daroussin
1617899f917SBaptiste Daroussin jailparam_free(iter->params, iter->params_count);
1627899f917SBaptiste Daroussin free(iter->params);
1637899f917SBaptiste Daroussin free(iter);
1647899f917SBaptiste Daroussin *iterp = NULL;
1657899f917SBaptiste Daroussin return (0);
1667899f917SBaptiste Daroussin }
1677899f917SBaptiste Daroussin
1687899f917SBaptiste Daroussin static int
l_list(lua_State * L)1697899f917SBaptiste Daroussin l_list(lua_State *L)
1707899f917SBaptiste Daroussin {
1717899f917SBaptiste Daroussin struct l_jail_iter *iter;
1727899f917SBaptiste Daroussin int nargs;
1737899f917SBaptiste Daroussin
1747899f917SBaptiste Daroussin nargs = lua_gettop(L);
1757899f917SBaptiste Daroussin if (nargs >= 1)
1767899f917SBaptiste Daroussin luaL_checktype(L, 1, LUA_TTABLE);
1777899f917SBaptiste Daroussin
1787899f917SBaptiste Daroussin iter = malloc(sizeof(*iter));
1797899f917SBaptiste Daroussin if (iter == NULL)
1807899f917SBaptiste Daroussin return (luaL_error(L, "malloc: %s", strerror(errno)));
1817899f917SBaptiste Daroussin
1827899f917SBaptiste Daroussin /*
1837899f917SBaptiste Daroussin * lastjid, jid, name + length of the table. This may be too much if
1847899f917SBaptiste Daroussin * we have duplicated one of those fixed parameters.
1857899f917SBaptiste Daroussin */
1867899f917SBaptiste Daroussin iter->params_count = 3 + (nargs != 0 ? lua_rawlen(L, 1) : 0);
1877899f917SBaptiste Daroussin iter->params = malloc(iter->params_count * sizeof(*iter->params));
1887899f917SBaptiste Daroussin if (iter->params == NULL) {
1897899f917SBaptiste Daroussin free(iter);
1907899f917SBaptiste Daroussin return (luaL_error(L, "malloc params: %s", strerror(errno)));
1917899f917SBaptiste Daroussin }
1927899f917SBaptiste Daroussin
1937899f917SBaptiste Daroussin /* The :next() method will populate lastjid before jail_getparam(). */
1947899f917SBaptiste Daroussin if (jailparam_init(&iter->params[0], "lastjid") == -1) {
1957899f917SBaptiste Daroussin free(iter->params);
1967899f917SBaptiste Daroussin free(iter);
1977899f917SBaptiste Daroussin return (luaL_error(L, "jailparam_init: %s", jail_errmsg));
1987899f917SBaptiste Daroussin }
1997899f917SBaptiste Daroussin /* These two will get populated by jail_getparam(). */
2007899f917SBaptiste Daroussin if (jailparam_init(&iter->params[1], "jid") == -1) {
2017899f917SBaptiste Daroussin jailparam_free(iter->params, 1);
2027899f917SBaptiste Daroussin free(iter->params);
2037899f917SBaptiste Daroussin free(iter);
2047899f917SBaptiste Daroussin return (luaL_error(L, "jailparam_init: %s",
2057899f917SBaptiste Daroussin jail_errmsg));
2067899f917SBaptiste Daroussin }
2077899f917SBaptiste Daroussin if (jailparam_init(&iter->params[2], "name") == -1) {
2087899f917SBaptiste Daroussin jailparam_free(iter->params, 2);
2097899f917SBaptiste Daroussin free(iter->params);
2107899f917SBaptiste Daroussin free(iter);
2117899f917SBaptiste Daroussin return (luaL_error(L, "jailparam_init: %s",
2127899f917SBaptiste Daroussin jail_errmsg));
2137899f917SBaptiste Daroussin }
2147899f917SBaptiste Daroussin
2157899f917SBaptiste Daroussin /*
2167899f917SBaptiste Daroussin * We only need to process additional arguments if we were given any.
2177899f917SBaptiste Daroussin * That is, we don't descend into getparam_table if we're passed nothing
2187899f917SBaptiste Daroussin * or an empty table.
2197899f917SBaptiste Daroussin */
2207899f917SBaptiste Daroussin iter->jid = 0;
2217899f917SBaptiste Daroussin if (iter->params_count != 3)
2227899f917SBaptiste Daroussin getparam_table(L, 1, iter->params, 2, &iter->params_count,
2237899f917SBaptiste Daroussin l_jail_filter, NULL);
2247899f917SBaptiste Daroussin
2257899f917SBaptiste Daroussin /*
2267899f917SBaptiste Daroussin * Part of the iterator magic. We give it an iterator function with a
2277899f917SBaptiste Daroussin * metatable defining next() and close() that can be used for manual
2287899f917SBaptiste Daroussin * iteration. iter->jid is how we track which jail we last iterated, to
2297899f917SBaptiste Daroussin * be supplied as "lastjid".
2307899f917SBaptiste Daroussin */
2317899f917SBaptiste Daroussin lua_pushcfunction(L, l_jail_iter_next);
2327899f917SBaptiste Daroussin *(struct l_jail_iter **)lua_newuserdata(L,
2337899f917SBaptiste Daroussin sizeof(struct l_jail_iter **)) = iter;
2347899f917SBaptiste Daroussin luaL_getmetatable(L, JAIL_METATABLE);
2357899f917SBaptiste Daroussin lua_setmetatable(L, -2);
2367899f917SBaptiste Daroussin return (2);
2377899f917SBaptiste Daroussin }
2387899f917SBaptiste Daroussin
2397899f917SBaptiste Daroussin static void
register_jail_metatable(lua_State * L)2407899f917SBaptiste Daroussin register_jail_metatable(lua_State *L)
2417899f917SBaptiste Daroussin {
2427899f917SBaptiste Daroussin luaL_newmetatable(L, JAIL_METATABLE);
2437899f917SBaptiste Daroussin lua_newtable(L);
2447899f917SBaptiste Daroussin lua_pushcfunction(L, l_jail_iter_next);
2457899f917SBaptiste Daroussin lua_setfield(L, -2, "next");
2467899f917SBaptiste Daroussin lua_pushcfunction(L, l_jail_iter_close);
2477899f917SBaptiste Daroussin lua_setfield(L, -2, "close");
2487899f917SBaptiste Daroussin
2497899f917SBaptiste Daroussin lua_setfield(L, -2, "__index");
2507899f917SBaptiste Daroussin
2517899f917SBaptiste Daroussin lua_pushcfunction(L, l_jail_iter_close);
2527899f917SBaptiste Daroussin lua_setfield(L, -2, "__gc");
2537899f917SBaptiste Daroussin
2547899f917SBaptiste Daroussin lua_pop(L, 1);
2557899f917SBaptiste Daroussin }
2567899f917SBaptiste Daroussin
2577899f917SBaptiste Daroussin static int
l_getid(lua_State * L)2587899f917SBaptiste Daroussin l_getid(lua_State *L)
2597899f917SBaptiste Daroussin {
2607899f917SBaptiste Daroussin const char *name;
2617899f917SBaptiste Daroussin int jid;
2627899f917SBaptiste Daroussin
2637899f917SBaptiste Daroussin name = luaL_checkstring(L, 1);
2647899f917SBaptiste Daroussin jid = jail_getid(name);
2657899f917SBaptiste Daroussin if (jid == -1) {
2667899f917SBaptiste Daroussin lua_pushnil(L);
2677899f917SBaptiste Daroussin lua_pushstring(L, jail_errmsg);
2687899f917SBaptiste Daroussin return (2);
2697899f917SBaptiste Daroussin }
2707899f917SBaptiste Daroussin lua_pushinteger(L, jid);
2717899f917SBaptiste Daroussin return (1);
2727899f917SBaptiste Daroussin }
2737899f917SBaptiste Daroussin
2747899f917SBaptiste Daroussin static int
l_getname(lua_State * L)2757899f917SBaptiste Daroussin l_getname(lua_State *L)
2767899f917SBaptiste Daroussin {
2777899f917SBaptiste Daroussin char *name;
2787899f917SBaptiste Daroussin int jid;
2797899f917SBaptiste Daroussin
2807899f917SBaptiste Daroussin jid = luaL_checkinteger(L, 1);
2817899f917SBaptiste Daroussin name = jail_getname(jid);
2827899f917SBaptiste Daroussin if (name == NULL) {
2837899f917SBaptiste Daroussin lua_pushnil(L);
2847899f917SBaptiste Daroussin lua_pushstring(L, jail_errmsg);
2857899f917SBaptiste Daroussin return (2);
2867899f917SBaptiste Daroussin }
2877899f917SBaptiste Daroussin lua_pushstring(L, name);
2887899f917SBaptiste Daroussin free(name);
2897899f917SBaptiste Daroussin return (1);
2907899f917SBaptiste Daroussin }
2917899f917SBaptiste Daroussin
2927899f917SBaptiste Daroussin static int
l_allparams(lua_State * L)2937899f917SBaptiste Daroussin l_allparams(lua_State *L)
2947899f917SBaptiste Daroussin {
2957899f917SBaptiste Daroussin struct jailparam *params;
2967899f917SBaptiste Daroussin int params_count;
2977899f917SBaptiste Daroussin
2987899f917SBaptiste Daroussin params_count = jailparam_all(¶ms);
2997899f917SBaptiste Daroussin if (params_count == -1) {
3007899f917SBaptiste Daroussin lua_pushnil(L);
3017899f917SBaptiste Daroussin lua_pushstring(L, jail_errmsg);
3027899f917SBaptiste Daroussin return (2);
3037899f917SBaptiste Daroussin }
3047899f917SBaptiste Daroussin lua_newtable(L);
3057899f917SBaptiste Daroussin for (int i = 0; i < params_count; ++i) {
3067899f917SBaptiste Daroussin lua_pushstring(L, params[i].jp_name);
3077899f917SBaptiste Daroussin lua_rawseti(L, -2, i + 1);
3087899f917SBaptiste Daroussin }
3097899f917SBaptiste Daroussin jailparam_free(params, params_count);
3107899f917SBaptiste Daroussin free(params);
3117899f917SBaptiste Daroussin return (1);
3127899f917SBaptiste Daroussin }
3137899f917SBaptiste Daroussin
3147899f917SBaptiste Daroussin static void
getparam_table(lua_State * L,int paramindex,struct jailparam * params,size_t params_off,size_t * params_countp,getparam_filter keyfilt,void * udata)3157899f917SBaptiste Daroussin getparam_table(lua_State *L, int paramindex, struct jailparam *params,
3167899f917SBaptiste Daroussin size_t params_off, size_t *params_countp, getparam_filter keyfilt,
3177899f917SBaptiste Daroussin void *udata)
3187899f917SBaptiste Daroussin {
3197899f917SBaptiste Daroussin size_t params_count;
3207899f917SBaptiste Daroussin int skipped;
3217899f917SBaptiste Daroussin
3227899f917SBaptiste Daroussin params_count = *params_countp;
3237899f917SBaptiste Daroussin skipped = 0;
3247899f917SBaptiste Daroussin for (size_t i = 1 + params_off; i < params_count; ++i) {
3257899f917SBaptiste Daroussin const char *param_name;
3267899f917SBaptiste Daroussin
3277899f917SBaptiste Daroussin lua_rawgeti(L, -1, i - params_off);
3287899f917SBaptiste Daroussin param_name = lua_tostring(L, -1);
3297899f917SBaptiste Daroussin if (param_name == NULL) {
3307899f917SBaptiste Daroussin jailparam_free(params, i - skipped);
3317899f917SBaptiste Daroussin free(params);
3327899f917SBaptiste Daroussin luaL_argerror(L, paramindex,
3337899f917SBaptiste Daroussin "param names must be strings");
3347899f917SBaptiste Daroussin }
3357899f917SBaptiste Daroussin lua_pop(L, 1);
3367899f917SBaptiste Daroussin if (keyfilt != NULL && !keyfilt(param_name, udata)) {
3377899f917SBaptiste Daroussin ++skipped;
3387899f917SBaptiste Daroussin continue;
3397899f917SBaptiste Daroussin }
3407899f917SBaptiste Daroussin if (jailparam_init(¶ms[i - skipped], param_name) == -1) {
3417899f917SBaptiste Daroussin jailparam_free(params, i - skipped);
3427899f917SBaptiste Daroussin free(params);
3437899f917SBaptiste Daroussin luaL_error(L, "jailparam_init: %s", jail_errmsg);
3447899f917SBaptiste Daroussin }
3457899f917SBaptiste Daroussin }
3467899f917SBaptiste Daroussin *params_countp -= skipped;
3477899f917SBaptiste Daroussin }
3487899f917SBaptiste Daroussin
3497899f917SBaptiste Daroussin struct getparams_filter_args {
3507899f917SBaptiste Daroussin int filter_type;
3517899f917SBaptiste Daroussin };
3527899f917SBaptiste Daroussin
3537899f917SBaptiste Daroussin static bool
l_getparams_filter(const char * param_name,void * udata)3547899f917SBaptiste Daroussin l_getparams_filter(const char *param_name, void *udata)
3557899f917SBaptiste Daroussin {
3567899f917SBaptiste Daroussin struct getparams_filter_args *gpa;
3577899f917SBaptiste Daroussin
3587899f917SBaptiste Daroussin gpa = udata;
3597899f917SBaptiste Daroussin
3607899f917SBaptiste Daroussin /* Skip name or jid, whichever was given. */
3617899f917SBaptiste Daroussin if (gpa->filter_type == LUA_TSTRING) {
3627899f917SBaptiste Daroussin if (strcmp(param_name, "name") == 0)
3637899f917SBaptiste Daroussin return (false);
3647899f917SBaptiste Daroussin } else /* type == LUA_TNUMBER */ {
3657899f917SBaptiste Daroussin if (strcmp(param_name, "jid") == 0)
3667899f917SBaptiste Daroussin return (false);
3677899f917SBaptiste Daroussin }
3687899f917SBaptiste Daroussin
3697899f917SBaptiste Daroussin return (true);
3707899f917SBaptiste Daroussin }
3717899f917SBaptiste Daroussin
3727899f917SBaptiste Daroussin static int
l_getparams(lua_State * L)3737899f917SBaptiste Daroussin l_getparams(lua_State *L)
3747899f917SBaptiste Daroussin {
3757899f917SBaptiste Daroussin const char *name;
3767899f917SBaptiste Daroussin struct jailparam *params;
3777899f917SBaptiste Daroussin size_t params_count;
3787899f917SBaptiste Daroussin struct getparams_filter_args gpa;
3797899f917SBaptiste Daroussin int flags, jid, type;
3807899f917SBaptiste Daroussin
3817899f917SBaptiste Daroussin type = lua_type(L, 1);
3827899f917SBaptiste Daroussin luaL_argcheck(L, type == LUA_TSTRING || type == LUA_TNUMBER, 1,
3837899f917SBaptiste Daroussin "expected a jail name (string) or id (integer)");
3847899f917SBaptiste Daroussin luaL_checktype(L, 2, LUA_TTABLE);
3857899f917SBaptiste Daroussin params_count = 1 + lua_rawlen(L, 2);
3867899f917SBaptiste Daroussin flags = luaL_optinteger(L, 3, 0);
3877899f917SBaptiste Daroussin
3887899f917SBaptiste Daroussin params = malloc(params_count * sizeof(struct jailparam));
3897899f917SBaptiste Daroussin if (params == NULL)
3907899f917SBaptiste Daroussin return (luaL_error(L, "malloc: %s", strerror(errno)));
3917899f917SBaptiste Daroussin
3927899f917SBaptiste Daroussin /*
3937899f917SBaptiste Daroussin * Set the jail name or id param as determined by the first arg.
3947899f917SBaptiste Daroussin */
3957899f917SBaptiste Daroussin
3967899f917SBaptiste Daroussin if (type == LUA_TSTRING) {
3977899f917SBaptiste Daroussin if (jailparam_init(¶ms[0], "name") == -1) {
3987899f917SBaptiste Daroussin free(params);
3997899f917SBaptiste Daroussin return (luaL_error(L, "jailparam_init: %s",
4007899f917SBaptiste Daroussin jail_errmsg));
4017899f917SBaptiste Daroussin }
4027899f917SBaptiste Daroussin name = lua_tostring(L, 1);
4037899f917SBaptiste Daroussin if (jailparam_import(¶ms[0], name) == -1) {
4047899f917SBaptiste Daroussin jailparam_free(params, 1);
4057899f917SBaptiste Daroussin free(params);
4067899f917SBaptiste Daroussin return (luaL_error(L, "jailparam_import: %s",
4077899f917SBaptiste Daroussin jail_errmsg));
4087899f917SBaptiste Daroussin }
4097899f917SBaptiste Daroussin } else /* type == LUA_TNUMBER */ {
4107899f917SBaptiste Daroussin if (jailparam_init(¶ms[0], "jid") == -1) {
4117899f917SBaptiste Daroussin free(params);
4127899f917SBaptiste Daroussin return (luaL_error(L, "jailparam_init: %s",
4137899f917SBaptiste Daroussin jail_errmsg));
4147899f917SBaptiste Daroussin }
4157899f917SBaptiste Daroussin jid = lua_tointeger(L, 1);
4167899f917SBaptiste Daroussin if (jailparam_import_raw(¶ms[0], &jid, sizeof(jid)) == -1) {
4177899f917SBaptiste Daroussin jailparam_free(params, 1);
4187899f917SBaptiste Daroussin free(params);
4197899f917SBaptiste Daroussin return (luaL_error(L, "jailparam_import_raw: %s",
4207899f917SBaptiste Daroussin jail_errmsg));
4217899f917SBaptiste Daroussin }
4227899f917SBaptiste Daroussin }
4237899f917SBaptiste Daroussin
4247899f917SBaptiste Daroussin /*
4257899f917SBaptiste Daroussin * Set the remaining param names being requested.
4267899f917SBaptiste Daroussin */
4277899f917SBaptiste Daroussin gpa.filter_type = type;
4287899f917SBaptiste Daroussin getparam_table(L, 2, params, 0, ¶ms_count, l_getparams_filter, &gpa);
4297899f917SBaptiste Daroussin
4307899f917SBaptiste Daroussin /*
4317899f917SBaptiste Daroussin * Get the values and convert to a table.
4327899f917SBaptiste Daroussin */
4337899f917SBaptiste Daroussin
4347899f917SBaptiste Daroussin jid = jailparam_get(params, params_count, flags);
4357899f917SBaptiste Daroussin if (jid == -1) {
4367899f917SBaptiste Daroussin jailparam_free(params, params_count);
4377899f917SBaptiste Daroussin free(params);
4387899f917SBaptiste Daroussin lua_pushnil(L);
4397899f917SBaptiste Daroussin lua_pushstring(L, jail_errmsg);
4407899f917SBaptiste Daroussin return (2);
4417899f917SBaptiste Daroussin }
4427899f917SBaptiste Daroussin lua_pushinteger(L, jid);
4437899f917SBaptiste Daroussin
4447899f917SBaptiste Daroussin lua_newtable(L);
4457899f917SBaptiste Daroussin for (size_t i = 0; i < params_count; ++i) {
4467899f917SBaptiste Daroussin char *value;
4477899f917SBaptiste Daroussin
448*30e6e008SIgor Ostapenko if (params[i].jp_flags & JP_KEYVALUE &&
449*30e6e008SIgor Ostapenko params[i].jp_valuelen == 0) {
450*30e6e008SIgor Ostapenko /* Communicate back a missing key. */
451*30e6e008SIgor Ostapenko lua_pushnil(L);
452*30e6e008SIgor Ostapenko } else {
4537899f917SBaptiste Daroussin value = jailparam_export(¶ms[i]);
4547899f917SBaptiste Daroussin lua_pushstring(L, value);
4557899f917SBaptiste Daroussin free(value);
456*30e6e008SIgor Ostapenko }
457*30e6e008SIgor Ostapenko
4587899f917SBaptiste Daroussin lua_setfield(L, -2, params[i].jp_name);
4597899f917SBaptiste Daroussin }
4607899f917SBaptiste Daroussin
4617899f917SBaptiste Daroussin jailparam_free(params, params_count);
4627899f917SBaptiste Daroussin free(params);
4637899f917SBaptiste Daroussin
4647899f917SBaptiste Daroussin return (2);
4657899f917SBaptiste Daroussin }
4667899f917SBaptiste Daroussin
4677899f917SBaptiste Daroussin static int
l_setparams(lua_State * L)4687899f917SBaptiste Daroussin l_setparams(lua_State *L)
4697899f917SBaptiste Daroussin {
4707899f917SBaptiste Daroussin const char *name;
4717899f917SBaptiste Daroussin struct jailparam *params;
4727899f917SBaptiste Daroussin size_t params_count;
4737899f917SBaptiste Daroussin int flags, jid, type;
4747899f917SBaptiste Daroussin
4757899f917SBaptiste Daroussin type = lua_type(L, 1);
4767899f917SBaptiste Daroussin luaL_argcheck(L, type == LUA_TSTRING || type == LUA_TNUMBER, 1,
4777899f917SBaptiste Daroussin "expected a jail name (string) or id (integer)");
4787899f917SBaptiste Daroussin luaL_checktype(L, 2, LUA_TTABLE);
4797899f917SBaptiste Daroussin
4807899f917SBaptiste Daroussin lua_pushnil(L);
4817899f917SBaptiste Daroussin for (params_count = 1; lua_next(L, 2) != 0; ++params_count)
4827899f917SBaptiste Daroussin lua_pop(L, 1);
4837899f917SBaptiste Daroussin
4847899f917SBaptiste Daroussin flags = luaL_optinteger(L, 3, 0);
4857899f917SBaptiste Daroussin
4867899f917SBaptiste Daroussin params = malloc(params_count * sizeof(struct jailparam));
4877899f917SBaptiste Daroussin if (params == NULL)
4887899f917SBaptiste Daroussin return (luaL_error(L, "malloc: %s", strerror(errno)));
4897899f917SBaptiste Daroussin
4907899f917SBaptiste Daroussin /*
4917899f917SBaptiste Daroussin * Set the jail name or id param as determined by the first arg.
4927899f917SBaptiste Daroussin */
4937899f917SBaptiste Daroussin
4947899f917SBaptiste Daroussin if (type == LUA_TSTRING) {
4957899f917SBaptiste Daroussin if (jailparam_init(¶ms[0], "name") == -1) {
4967899f917SBaptiste Daroussin free(params);
4977899f917SBaptiste Daroussin return (luaL_error(L, "jailparam_init: %s",
4987899f917SBaptiste Daroussin jail_errmsg));
4997899f917SBaptiste Daroussin }
5007899f917SBaptiste Daroussin name = lua_tostring(L, 1);
5017899f917SBaptiste Daroussin if (jailparam_import(¶ms[0], name) == -1) {
5027899f917SBaptiste Daroussin jailparam_free(params, 1);
5037899f917SBaptiste Daroussin free(params);
5047899f917SBaptiste Daroussin return (luaL_error(L, "jailparam_import: %s",
5057899f917SBaptiste Daroussin jail_errmsg));
5067899f917SBaptiste Daroussin }
5077899f917SBaptiste Daroussin } else /* type == LUA_TNUMBER */ {
5087899f917SBaptiste Daroussin if (jailparam_init(¶ms[0], "jid") == -1) {
5097899f917SBaptiste Daroussin free(params);
5107899f917SBaptiste Daroussin return (luaL_error(L, "jailparam_init: %s",
5117899f917SBaptiste Daroussin jail_errmsg));
5127899f917SBaptiste Daroussin }
5137899f917SBaptiste Daroussin jid = lua_tointeger(L, 1);
5147899f917SBaptiste Daroussin if (jailparam_import_raw(¶ms[0], &jid, sizeof(jid)) == -1) {
5157899f917SBaptiste Daroussin jailparam_free(params, 1);
5167899f917SBaptiste Daroussin free(params);
5177899f917SBaptiste Daroussin return (luaL_error(L, "jailparam_import_raw: %s",
5187899f917SBaptiste Daroussin jail_errmsg));
5197899f917SBaptiste Daroussin }
5207899f917SBaptiste Daroussin }
5217899f917SBaptiste Daroussin
5227899f917SBaptiste Daroussin /*
5237899f917SBaptiste Daroussin * Set the rest of the provided params.
5247899f917SBaptiste Daroussin */
5257899f917SBaptiste Daroussin
5267899f917SBaptiste Daroussin lua_pushnil(L);
5277899f917SBaptiste Daroussin for (size_t i = 1; i < params_count && lua_next(L, 2) != 0; ++i) {
5287899f917SBaptiste Daroussin const char *value;
5297899f917SBaptiste Daroussin
5307899f917SBaptiste Daroussin name = lua_tostring(L, -2);
5317899f917SBaptiste Daroussin if (name == NULL) {
5327899f917SBaptiste Daroussin jailparam_free(params, i);
5337899f917SBaptiste Daroussin free(params);
5347899f917SBaptiste Daroussin return (luaL_argerror(L, 2,
5357899f917SBaptiste Daroussin "param names must be strings"));
5367899f917SBaptiste Daroussin }
5377899f917SBaptiste Daroussin if (jailparam_init(¶ms[i], name) == -1) {
5387899f917SBaptiste Daroussin jailparam_free(params, i);
5397899f917SBaptiste Daroussin free(params);
5407899f917SBaptiste Daroussin return (luaL_error(L, "jailparam_init: %s",
5417899f917SBaptiste Daroussin jail_errmsg));
5427899f917SBaptiste Daroussin }
5437899f917SBaptiste Daroussin
5447899f917SBaptiste Daroussin value = lua_tostring(L, -1);
545*30e6e008SIgor Ostapenko /* Allow passing NULL for key removal. */
546*30e6e008SIgor Ostapenko if (value == NULL && !(params[i].jp_flags & JP_KEYVALUE)) {
5477899f917SBaptiste Daroussin jailparam_free(params, i + 1);
5487899f917SBaptiste Daroussin free(params);
5497899f917SBaptiste Daroussin return (luaL_argerror(L, 2,
5507899f917SBaptiste Daroussin "param values must be strings"));
5517899f917SBaptiste Daroussin }
5527899f917SBaptiste Daroussin if (jailparam_import(¶ms[i], value) == -1) {
5537899f917SBaptiste Daroussin jailparam_free(params, i + 1);
5547899f917SBaptiste Daroussin free(params);
5557899f917SBaptiste Daroussin return (luaL_error(L, "jailparam_import: %s",
5567899f917SBaptiste Daroussin jail_errmsg));
5577899f917SBaptiste Daroussin }
5587899f917SBaptiste Daroussin
5597899f917SBaptiste Daroussin lua_pop(L, 1);
5607899f917SBaptiste Daroussin }
5617899f917SBaptiste Daroussin
5627899f917SBaptiste Daroussin /*
5637899f917SBaptiste Daroussin * Attempt to set the params.
5647899f917SBaptiste Daroussin */
5657899f917SBaptiste Daroussin
5667899f917SBaptiste Daroussin jid = jailparam_set(params, params_count, flags);
5677899f917SBaptiste Daroussin if (jid == -1) {
5687899f917SBaptiste Daroussin jailparam_free(params, params_count);
5697899f917SBaptiste Daroussin free(params);
5707899f917SBaptiste Daroussin lua_pushnil(L);
5717899f917SBaptiste Daroussin lua_pushstring(L, jail_errmsg);
5727899f917SBaptiste Daroussin return (2);
5737899f917SBaptiste Daroussin }
5747899f917SBaptiste Daroussin lua_pushinteger(L, jid);
5757899f917SBaptiste Daroussin
5767899f917SBaptiste Daroussin jailparam_free(params, params_count);
5777899f917SBaptiste Daroussin free(params);
5787899f917SBaptiste Daroussin return (1);
5797899f917SBaptiste Daroussin }
5807899f917SBaptiste Daroussin
5817899f917SBaptiste Daroussin static int
l_attach(lua_State * L)5827899f917SBaptiste Daroussin l_attach(lua_State *L)
5837899f917SBaptiste Daroussin {
5847899f917SBaptiste Daroussin int jid, type;
5857899f917SBaptiste Daroussin
5867899f917SBaptiste Daroussin type = lua_type(L, 1);
5877899f917SBaptiste Daroussin luaL_argcheck(L, type == LUA_TSTRING || type == LUA_TNUMBER, 1,
5887899f917SBaptiste Daroussin "expected a jail name (string) or id (integer)");
5897899f917SBaptiste Daroussin
5907899f917SBaptiste Daroussin if (lua_isstring(L, 1)) {
5917899f917SBaptiste Daroussin /* Resolve it to a jid. */
5927899f917SBaptiste Daroussin jid = jail_getid(lua_tostring(L, 1));
5937899f917SBaptiste Daroussin if (jid == -1) {
5947899f917SBaptiste Daroussin lua_pushnil(L);
5957899f917SBaptiste Daroussin lua_pushstring(L, jail_errmsg);
5967899f917SBaptiste Daroussin return (2);
5977899f917SBaptiste Daroussin }
5987899f917SBaptiste Daroussin } else {
5997899f917SBaptiste Daroussin jid = lua_tointeger(L, 1);
6007899f917SBaptiste Daroussin }
6017899f917SBaptiste Daroussin
6027899f917SBaptiste Daroussin if (jail_attach(jid) == -1) {
6037899f917SBaptiste Daroussin lua_pushnil(L);
6047899f917SBaptiste Daroussin lua_pushstring(L, strerror(errno));
6057899f917SBaptiste Daroussin return (2);
6067899f917SBaptiste Daroussin }
6077899f917SBaptiste Daroussin
6087899f917SBaptiste Daroussin lua_pushboolean(L, 1);
6097899f917SBaptiste Daroussin return (1);
6107899f917SBaptiste Daroussin }
6117899f917SBaptiste Daroussin
6127899f917SBaptiste Daroussin static int
l_remove(lua_State * L)6137899f917SBaptiste Daroussin l_remove(lua_State *L)
6147899f917SBaptiste Daroussin {
6157899f917SBaptiste Daroussin int jid, type;
6167899f917SBaptiste Daroussin
6177899f917SBaptiste Daroussin type = lua_type(L, 1);
6187899f917SBaptiste Daroussin luaL_argcheck(L, type == LUA_TSTRING || type == LUA_TNUMBER, 1,
6197899f917SBaptiste Daroussin "expected a jail name (string) or id (integer)");
6207899f917SBaptiste Daroussin
6217899f917SBaptiste Daroussin if (lua_isstring(L, 1)) {
6227899f917SBaptiste Daroussin /* Resolve it to a jid. */
6237899f917SBaptiste Daroussin jid = jail_getid(lua_tostring(L, 1));
6247899f917SBaptiste Daroussin if (jid == -1) {
6257899f917SBaptiste Daroussin lua_pushnil(L);
6267899f917SBaptiste Daroussin lua_pushstring(L, jail_errmsg);
6277899f917SBaptiste Daroussin return (2);
6287899f917SBaptiste Daroussin }
6297899f917SBaptiste Daroussin } else {
6307899f917SBaptiste Daroussin jid = lua_tointeger(L, 1);
6317899f917SBaptiste Daroussin }
6327899f917SBaptiste Daroussin
6337899f917SBaptiste Daroussin if (jail_remove(jid) == -1) {
6347899f917SBaptiste Daroussin lua_pushnil(L);
6357899f917SBaptiste Daroussin lua_pushstring(L, strerror(errno));
6367899f917SBaptiste Daroussin return (2);
6377899f917SBaptiste Daroussin }
6387899f917SBaptiste Daroussin
6397899f917SBaptiste Daroussin lua_pushboolean(L, 1);
6407899f917SBaptiste Daroussin return (1);
6417899f917SBaptiste Daroussin }
6427899f917SBaptiste Daroussin
6437899f917SBaptiste Daroussin static const struct luaL_Reg l_jail[] = {
6447899f917SBaptiste Daroussin /** Get id of a jail by name.
6457899f917SBaptiste Daroussin * @param name jail name (string)
6467899f917SBaptiste Daroussin * @return jail id (integer)
6477899f917SBaptiste Daroussin * or nil, error (string) on error
6487899f917SBaptiste Daroussin */
6497899f917SBaptiste Daroussin {"getid", l_getid},
6507899f917SBaptiste Daroussin /** Get name of a jail by id.
6517899f917SBaptiste Daroussin * @param jid jail id (integer)
6527899f917SBaptiste Daroussin * @return jail name (string)
6537899f917SBaptiste Daroussin * or nil, error (string) on error
6547899f917SBaptiste Daroussin */
6557899f917SBaptiste Daroussin {"getname", l_getname},
6567899f917SBaptiste Daroussin /** Get a list of all known jail parameters.
6577899f917SBaptiste Daroussin * @return list of jail parameter names (table of strings)
6587899f917SBaptiste Daroussin * or nil, error (string) on error
6597899f917SBaptiste Daroussin */
6607899f917SBaptiste Daroussin {"allparams", l_allparams},
6617899f917SBaptiste Daroussin /** Get the listed params for a given jail.
6627899f917SBaptiste Daroussin * @param jail jail name (string) or id (integer)
6637899f917SBaptiste Daroussin * @param params list of parameter names (table of strings)
6647899f917SBaptiste Daroussin * @param flags optional flags (integer)
6657899f917SBaptiste Daroussin * @return jid (integer), params (table of [string] = string)
6667899f917SBaptiste Daroussin * or nil, error (string) on error
6677899f917SBaptiste Daroussin */
6687899f917SBaptiste Daroussin {"getparams", l_getparams},
6697899f917SBaptiste Daroussin /** Set params for a given jail.
6707899f917SBaptiste Daroussin * @param jail jail name (string) or id (integer)
6717899f917SBaptiste Daroussin * @param params params and values (table of [string] = string)
6727899f917SBaptiste Daroussin * @param flags optional flags (integer)
6737899f917SBaptiste Daroussin * @return jid (integer)
6747899f917SBaptiste Daroussin * or nil, error (string) on error
6757899f917SBaptiste Daroussin */
6767899f917SBaptiste Daroussin {"setparams", l_setparams},
6777899f917SBaptiste Daroussin /** Get a list of jail parameters for running jails on the system.
6787899f917SBaptiste Daroussin * @param params optional list of parameter names (table of
6797899f917SBaptiste Daroussin * strings)
6807899f917SBaptiste Daroussin * @return iterator (function), jail_obj (object) with next and
6817899f917SBaptiste Daroussin * close methods
6827899f917SBaptiste Daroussin */
6837899f917SBaptiste Daroussin {"list", l_list},
6847899f917SBaptiste Daroussin /** Attach to a running jail.
6857899f917SBaptiste Daroussin * @param jail jail name (string) or id (integer)
6867899f917SBaptiste Daroussin * @return true (boolean)
6877899f917SBaptiste Daroussin * or nil, error (string) on error
6887899f917SBaptiste Daroussin */
6897899f917SBaptiste Daroussin {"attach", l_attach},
6907899f917SBaptiste Daroussin /** Remove a running jail.
6917899f917SBaptiste Daroussin * @param jail jail name (string) or id (integer)
6927899f917SBaptiste Daroussin * @return true (boolean)
6937899f917SBaptiste Daroussin * or nil, error (string) on error
6947899f917SBaptiste Daroussin */
6957899f917SBaptiste Daroussin {"remove", l_remove},
6967899f917SBaptiste Daroussin {NULL, NULL}
6977899f917SBaptiste Daroussin };
6987899f917SBaptiste Daroussin
6997899f917SBaptiste Daroussin int
luaopen_jail(lua_State * L)7007899f917SBaptiste Daroussin luaopen_jail(lua_State *L)
7017899f917SBaptiste Daroussin {
7027899f917SBaptiste Daroussin lua_newtable(L);
7037899f917SBaptiste Daroussin
7047899f917SBaptiste Daroussin luaL_setfuncs(L, l_jail, 0);
7057899f917SBaptiste Daroussin
7067899f917SBaptiste Daroussin lua_pushinteger(L, JAIL_CREATE);
7077899f917SBaptiste Daroussin lua_setfield(L, -2, "CREATE");
7087899f917SBaptiste Daroussin lua_pushinteger(L, JAIL_UPDATE);
7097899f917SBaptiste Daroussin lua_setfield(L, -2, "UPDATE");
7107899f917SBaptiste Daroussin lua_pushinteger(L, JAIL_ATTACH);
7117899f917SBaptiste Daroussin lua_setfield(L, -2, "ATTACH");
7127899f917SBaptiste Daroussin lua_pushinteger(L, JAIL_DYING);
7137899f917SBaptiste Daroussin lua_setfield(L, -2, "DYING");
7147899f917SBaptiste Daroussin
7157899f917SBaptiste Daroussin register_jail_metatable(L);
7167899f917SBaptiste Daroussin
7177899f917SBaptiste Daroussin return (1);
7187899f917SBaptiste Daroussin }
719