]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/flua/libjail/lua_jail.c
zfs: merge openzfs/zfs@c3b60eded (zfs-2.1-release) into stable/13
[FreeBSD/FreeBSD.git] / lib / flua / libjail / lua_jail.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2020, Ryan Moeller <freqlabs@FreeBSD.org>
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  * $FreeBSD$
28  */
29
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32
33 #include <sys/param.h>
34 #include <sys/jail.h>
35 #include <errno.h>
36 #include <jail.h>
37 #include <stdlib.h>
38 #include <string.h>
39
40 #include <lua.h>
41 #include <lauxlib.h>
42 #include <lualib.h>
43
44 int luaopen_jail(lua_State *);
45
46 static int
47 l_getid(lua_State *L)
48 {
49         const char *name;
50         int jid;
51
52         name = luaL_checkstring(L, 1);
53         jid = jail_getid(name);
54         if (jid == -1) {
55                 lua_pushnil(L);
56                 lua_pushstring(L, jail_errmsg);
57                 return (2);
58         }
59         lua_pushinteger(L, jid);
60         return (1);
61 }
62
63 static int
64 l_getname(lua_State *L)
65 {
66         char *name;
67         int jid;
68
69         jid = luaL_checkinteger(L, 1);
70         name = jail_getname(jid);
71         if (name == NULL) {
72                 lua_pushnil(L);
73                 lua_pushstring(L, jail_errmsg);
74                 return (2);
75         }
76         lua_pushstring(L, name);
77         free(name);
78         return (1);
79 }
80
81 static int
82 l_allparams(lua_State *L)
83 {
84         struct jailparam *params;
85         int params_count;
86
87         params_count = jailparam_all(&params);
88         if (params_count == -1) {
89                 lua_pushnil(L);
90                 lua_pushstring(L, jail_errmsg);
91                 return (2);
92         }
93         lua_newtable(L);
94         for (int i = 0; i < params_count; ++i) {
95                 lua_pushstring(L, params[i].jp_name);
96                 lua_rawseti(L, -2, i + 1);
97         }
98         jailparam_free(params, params_count);
99         free(params);
100         return (1);
101 }
102
103 static int
104 l_getparams(lua_State *L)
105 {
106         const char *name;
107         struct jailparam *params;
108         size_t params_count, skipped;
109         int flags, jid, type;
110
111         type = lua_type(L, 1);
112         luaL_argcheck(L, type == LUA_TSTRING || type == LUA_TNUMBER, 1,
113             "expected a jail name (string) or id (integer)");
114         luaL_checktype(L, 2, LUA_TTABLE);
115         params_count = 1 + lua_rawlen(L, 2);
116         flags = luaL_optinteger(L, 3, 0);
117
118         params = malloc(params_count * sizeof(struct jailparam));
119         if (params == NULL)
120                 return (luaL_error(L, "malloc: %s", strerror(errno)));
121
122         /*
123          * Set the jail name or id param as determined by the first arg.
124          */
125
126         if (type == LUA_TSTRING) {
127                 if (jailparam_init(&params[0], "name") == -1) {
128                         free(params);
129                         return (luaL_error(L, "jailparam_init: %s",
130                             jail_errmsg));
131                 }
132                 name = lua_tostring(L, 1);
133                 if (jailparam_import(&params[0], name) == -1) {
134                         jailparam_free(params, 1);
135                         free(params);
136                         return (luaL_error(L, "jailparam_import: %s",
137                             jail_errmsg));
138                 }
139         } else /* type == LUA_TNUMBER */ {
140                 if (jailparam_init(&params[0], "jid") == -1) {
141                         free(params);
142                         return (luaL_error(L, "jailparam_init: %s",
143                             jail_errmsg));
144                 }
145                 jid = lua_tointeger(L, 1);
146                 if (jailparam_import_raw(&params[0], &jid, sizeof(jid)) == -1) {
147                         jailparam_free(params, 1);
148                         free(params);
149                         return (luaL_error(L, "jailparam_import_raw: %s",
150                             jail_errmsg));
151                 }
152         }
153
154         /*
155          * Set the remaining param names being requested.
156          */
157
158         skipped = 0;
159         for (size_t i = 1; i < params_count; ++i) {
160                 const char *param_name;
161
162                 lua_rawgeti(L, -1, i);
163                 param_name = lua_tostring(L, -1);
164                 if (param_name == NULL) {
165                         jailparam_free(params, i - skipped);
166                         free(params);
167                         return (luaL_argerror(L, 2,
168                             "param names must be strings"));
169                 }
170                 lua_pop(L, 1);
171                 /* Skip name or jid, whichever was given. */
172                 if (type == LUA_TSTRING) {
173                         if (strcmp(param_name, "name") == 0) {
174                                 ++skipped;
175                                 continue;
176                         }
177                 } else /* type == LUA_TNUMBER */ {
178                         if (strcmp(param_name, "jid") == 0) {
179                                 ++skipped;
180                                 continue;
181                         }
182                 }
183                 if (jailparam_init(&params[i - skipped], param_name) == -1) {
184                         jailparam_free(params, i - skipped);
185                         free(params);
186                         return (luaL_error(L, "jailparam_init: %s",
187                             jail_errmsg));
188                 }
189         }
190         params_count -= skipped;
191
192         /*
193          * Get the values and convert to a table.
194          */
195
196         jid = jailparam_get(params, params_count, flags);
197         if (jid == -1) {
198                 jailparam_free(params, params_count);
199                 free(params);
200                 lua_pushnil(L);
201                 lua_pushstring(L, jail_errmsg);
202                 return (2);
203         }
204         lua_pushinteger(L, jid);
205
206         lua_newtable(L);
207         for (size_t i = 0; i < params_count; ++i) {
208                 char *value;
209
210                 value = jailparam_export(&params[i]);
211                 lua_pushstring(L, value);
212                 free(value);
213                 lua_setfield(L, -2, params[i].jp_name);
214         }
215
216         jailparam_free(params, params_count);
217         free(params);
218
219         return (2);
220 }
221
222 static int
223 l_setparams(lua_State *L)
224 {
225         const char *name;
226         struct jailparam *params;
227         size_t params_count;
228         int flags, jid, type;
229
230         type = lua_type(L, 1);
231         luaL_argcheck(L, type == LUA_TSTRING || type == LUA_TNUMBER, 1,
232             "expected a jail name (string) or id (integer)");
233         luaL_checktype(L, 2, LUA_TTABLE);
234
235         lua_pushnil(L);
236         for (params_count = 1; lua_next(L, 2) != 0; ++params_count)
237                 lua_pop(L, 1);
238
239         flags = luaL_optinteger(L, 3, 0);
240
241         params = malloc(params_count * sizeof(struct jailparam));
242         if (params == NULL)
243                 return (luaL_error(L, "malloc: %s", strerror(errno)));
244
245         /*
246          * Set the jail name or id param as determined by the first arg.
247          */
248
249         if (type == LUA_TSTRING) {
250                 if (jailparam_init(&params[0], "name") == -1) {
251                         free(params);
252                         return (luaL_error(L, "jailparam_init: %s",
253                             jail_errmsg));
254                 }
255                 name = lua_tostring(L, 1);
256                 if (jailparam_import(&params[0], name) == -1) {
257                         jailparam_free(params, 1);
258                         free(params);
259                         return (luaL_error(L, "jailparam_import: %s",
260                             jail_errmsg));
261                 }
262         } else /* type == LUA_TNUMBER */ {
263                 if (jailparam_init(&params[0], "jid") == -1) {
264                         free(params);
265                         return (luaL_error(L, "jailparam_init: %s",
266                             jail_errmsg));
267                 }
268                 jid = lua_tointeger(L, 1);
269                 if (jailparam_import_raw(&params[0], &jid, sizeof(jid)) == -1) {
270                         jailparam_free(params, 1);
271                         free(params);
272                         return (luaL_error(L, "jailparam_import_raw: %s",
273                             jail_errmsg));
274                 }
275         }
276
277         /*
278          * Set the rest of the provided params.
279          */
280
281         lua_pushnil(L);
282         for (size_t i = 1; i < params_count && lua_next(L, 2) != 0; ++i) {
283                 const char *value;
284
285                 name = lua_tostring(L, -2);
286                 if (name == NULL) {
287                         jailparam_free(params, i);
288                         free(params);
289                         return (luaL_argerror(L, 2,
290                             "param names must be strings"));
291                 }
292                 if (jailparam_init(&params[i], name) == -1) {
293                         jailparam_free(params, i);
294                         free(params);
295                         return (luaL_error(L, "jailparam_init: %s",
296                             jail_errmsg));
297                 }
298
299                 value = lua_tostring(L, -1);
300                 if (value == NULL) {
301                         jailparam_free(params, i + 1);
302                         free(params);
303                         return (luaL_argerror(L, 2,
304                             "param values must be strings"));
305                 }
306                 if (jailparam_import(&params[i], value) == -1) {
307                         jailparam_free(params, i + 1);
308                         free(params);
309                         return (luaL_error(L, "jailparam_import: %s",
310                             jail_errmsg));
311                 }
312
313                 lua_pop(L, 1);
314         }
315
316         /*
317          * Attempt to set the params.
318          */
319
320         jid = jailparam_set(params, params_count, flags);
321         if (jid == -1) {
322                 jailparam_free(params, params_count);
323                 free(params);
324                 lua_pushnil(L);
325                 lua_pushstring(L, jail_errmsg);
326                 return (2);
327         }
328         lua_pushinteger(L, jid);
329
330         jailparam_free(params, params_count);
331         free(params);
332         return (1);
333 }
334
335 static const struct luaL_Reg l_jail[] = {
336         /** Get id of a jail by name.
337          * @param name  jail name (string)
338          * @return      jail id (integer)
339          *              or nil, error (string) on error
340          */
341         {"getid", l_getid},
342         /** Get name of a jail by id.
343          * @param jid   jail id (integer)
344          * @return      jail name (string)
345          *              or nil, error (string) on error
346          */
347         {"getname", l_getname},
348         /** Get a list of all known jail parameters.
349          * @return      list of jail parameter names (table of strings)
350          *              or nil, error (string) on error
351          */
352         {"allparams", l_allparams},
353         /** Get the listed params for a given jail.
354          * @param jail  jail name (string) or id (integer)
355          * @param params        list of parameter names (table of strings)
356          * @param flags optional flags (integer)
357          * @return      jid (integer), params (table of [string] = string)
358          *              or nil, error (string) on error
359          */
360         {"getparams", l_getparams},
361         /** Set params for a given jail.
362          * @param jail  jail name (string) or id (integer)
363          * @param params        params and values (table of [string] = string)
364          * @param flags optional flags (integer)
365          * @return      jid (integer)
366          *              or nil, error (string) on error
367          */
368         {"setparams", l_setparams},
369         {NULL, NULL}
370 };
371
372 int
373 luaopen_jail(lua_State *L)
374 {
375         lua_newtable(L);
376
377         luaL_setfuncs(L, l_jail, 0);
378
379         lua_pushinteger(L, JAIL_CREATE);
380         lua_setfield(L, -2, "CREATE");
381         lua_pushinteger(L, JAIL_UPDATE);
382         lua_setfield(L, -2, "UPDATE");
383         lua_pushinteger(L, JAIL_ATTACH);
384         lua_setfield(L, -2, "ATTACH");
385         lua_pushinteger(L, JAIL_DYING);
386         lua_setfield(L, -2, "DYING");
387
388         return (1);
389 }