]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/flua/libjail/lua_jail.c
bhnd(9): Fix a few mandoc related issues
[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         luaL_argcheck(L, params_count > 1, 2, "expected #params > 0");
117         flags = luaL_optinteger(L, 3, 0);
118
119         params = malloc(params_count * sizeof(struct jailparam));
120         if (params == NULL)
121                 return (luaL_error(L, "malloc: %s", strerror(errno)));
122
123         /*
124          * Set the jail name or id param as determined by the first arg.
125          */
126
127         if (type == LUA_TSTRING) {
128                 if (jailparam_init(&params[0], "name") == -1) {
129                         free(params);
130                         return (luaL_error(L, "jailparam_init: %s",
131                             jail_errmsg));
132                 }
133                 name = lua_tostring(L, 1);
134                 if (jailparam_import(&params[0], name) == -1) {
135                         jailparam_free(params, 1);
136                         free(params);
137                         return (luaL_error(L, "jailparam_import: %s",
138                             jail_errmsg));
139                 }
140         } else /* type == LUA_TNUMBER */ {
141                 if (jailparam_init(&params[0], "jid") == -1) {
142                         free(params);
143                         return (luaL_error(L, "jailparam_init: %s",
144                             jail_errmsg));
145                 }
146                 jid = lua_tointeger(L, 1);
147                 if (jailparam_import_raw(&params[0], &jid, sizeof(jid)) == -1) {
148                         jailparam_free(params, 1);
149                         free(params);
150                         return (luaL_error(L, "jailparam_import_raw: %s",
151                             jail_errmsg));
152                 }
153         }
154
155         /*
156          * Set the remaining param names being requested.
157          */
158
159         skipped = 0;
160         for (size_t i = 1; i < params_count; ++i) {
161                 const char *param_name;
162
163                 lua_rawgeti(L, -1, i);
164                 param_name = lua_tostring(L, -1);
165                 if (param_name == NULL) {
166                         jailparam_free(params, i - skipped);
167                         free(params);
168                         return (luaL_argerror(L, 2,
169                             "param names must be strings"));
170                 }
171                 lua_pop(L, 1);
172                 /* Skip name or jid, whichever was given. */
173                 if (type == LUA_TSTRING) {
174                         if (strcmp(param_name, "name") == 0) {
175                                 ++skipped;
176                                 continue;
177                         }
178                 } else /* type == LUA_TNUMBER */ {
179                         if (strcmp(param_name, "jid") == 0) {
180                                 ++skipped;
181                                 continue;
182                         }
183                 }
184                 if (jailparam_init(&params[i - skipped], param_name) == -1) {
185                         jailparam_free(params, i - skipped);
186                         free(params);
187                         return (luaL_error(L, "jailparam_init: %s",
188                             jail_errmsg));
189                 }
190         }
191         params_count -= skipped;
192
193         /*
194          * Get the values and convert to a table.
195          */
196
197         jid = jailparam_get(params, params_count, flags);
198         if (jid == -1) {
199                 jailparam_free(params, params_count);
200                 free(params);
201                 lua_pushnil(L);
202                 lua_pushstring(L, jail_errmsg);
203                 return (2);
204         }
205         lua_pushinteger(L, jid);
206
207         lua_newtable(L);
208         for (size_t i = 0; i < params_count; ++i) {
209                 char *value;
210
211                 value = jailparam_export(&params[i]);
212                 lua_pushstring(L, value);
213                 free(value);
214                 lua_setfield(L, -2, params[i].jp_name);
215         }
216
217         jailparam_free(params, params_count);
218         free(params);
219
220         return (2);
221 }
222
223 static int
224 l_setparams(lua_State *L)
225 {
226         const char *name;
227         struct jailparam *params;
228         size_t params_count;
229         int flags, jid, type;
230
231         type = lua_type(L, 1);
232         luaL_argcheck(L, type == LUA_TSTRING || type == LUA_TNUMBER, 1,
233             "expected a jail name (string) or id (integer)");
234         luaL_checktype(L, 2, LUA_TTABLE);
235
236         lua_pushnil(L);
237         for (params_count = 1; lua_next(L, 2) != 0; ++params_count)
238                 lua_pop(L, 1);
239         luaL_argcheck(L, params_count > 1, 2, "expected #params > 0");
240
241         flags = luaL_optinteger(L, 3, 0);
242
243         params = malloc(params_count * sizeof(struct jailparam));
244         if (params == NULL)
245                 return (luaL_error(L, "malloc: %s", strerror(errno)));
246
247         /*
248          * Set the jail name or id param as determined by the first arg.
249          */
250
251         if (type == LUA_TSTRING) {
252                 if (jailparam_init(&params[0], "name") == -1) {
253                         free(params);
254                         return (luaL_error(L, "jailparam_init: %s",
255                             jail_errmsg));
256                 }
257                 name = lua_tostring(L, 1);
258                 if (jailparam_import(&params[0], name) == -1) {
259                         jailparam_free(params, 1);
260                         free(params);
261                         return (luaL_error(L, "jailparam_import: %s",
262                             jail_errmsg));
263                 }
264         } else /* type == LUA_TNUMBER */ {
265                 if (jailparam_init(&params[0], "jid") == -1) {
266                         free(params);
267                         return (luaL_error(L, "jailparam_init: %s",
268                             jail_errmsg));
269                 }
270                 jid = lua_tointeger(L, 1);
271                 if (jailparam_import_raw(&params[0], &jid, sizeof(jid)) == -1) {
272                         jailparam_free(params, 1);
273                         free(params);
274                         return (luaL_error(L, "jailparam_import_raw: %s",
275                             jail_errmsg));
276                 }
277         }
278
279         /*
280          * Set the rest of the provided params.
281          */
282
283         lua_pushnil(L);
284         for (size_t i = 1; i < params_count && lua_next(L, 2) != 0; ++i) {
285                 const char *value;
286
287                 name = lua_tostring(L, -2);
288                 if (name == NULL) {
289                         jailparam_free(params, i);
290                         free(params);
291                         return (luaL_argerror(L, 2,
292                             "param names must be strings"));
293                 }
294                 if (jailparam_init(&params[i], name) == -1) {
295                         jailparam_free(params, i);
296                         free(params);
297                         return (luaL_error(L, "jailparam_init: %s",
298                             jail_errmsg));
299                 }
300
301                 value = lua_tostring(L, -1);
302                 if (value == NULL) {
303                         jailparam_free(params, i + 1);
304                         free(params);
305                         return (luaL_argerror(L, 2,
306                             "param values must be strings"));
307                 }
308                 if (jailparam_import(&params[i], value) == -1) {
309                         jailparam_free(params, i + 1);
310                         free(params);
311                         return (luaL_error(L, "jailparam_import: %s",
312                             jail_errmsg));
313                 }
314
315                 lua_pop(L, 1);
316         }
317
318         /*
319          * Attempt to set the params.
320          */
321
322         jid = jailparam_set(params, params_count, flags);
323         if (jid == -1) {
324                 jailparam_free(params, params_count);
325                 free(params);
326                 lua_pushnil(L);
327                 lua_pushstring(L, jail_errmsg);
328                 return (2);
329         }
330         lua_pushinteger(L, jid);
331
332         jailparam_free(params, params_count);
333         free(params);
334         return (1);
335 }
336
337 static const struct luaL_Reg l_jail[] = {
338         /** Get id of a jail by name.
339          * @param name  jail name (string)
340          * @return      jail id (integer)
341          *              or nil, error (string) on error
342          */
343         {"getid", l_getid},
344         /** Get name of a jail by id.
345          * @param jid   jail id (integer)
346          * @return      jail name (string)
347          *              or nil, error (string) on error
348          */
349         {"getname", l_getname},
350         /** Get a list of all known jail parameters.
351          * @return      list of jail parameter names (table of strings)
352          *              or nil, error (string) on error
353          */
354         {"allparams", l_allparams},
355         /** Get the listed params for a given jail.
356          * @param jail  jail name (string) or id (integer)
357          * @param params        list of parameter names (table of strings)
358          * @param flags optional flags (integer)
359          * @return      jid (integer), params (table of [string] = string)
360          *              or nil, error (string) on error
361          */
362         {"getparams", l_getparams},
363         /** Set params for a given jail.
364          * @param jail  jail name (string) or id (integer)
365          * @param params        params and values (table of [string] = string)
366          * @param flags optional flags (integer)
367          * @return      jid (integer)
368          *              or nil, error (string) on error
369          */
370         {"setparams", l_setparams},
371         {NULL, NULL}
372 };
373
374 int
375 luaopen_jail(lua_State *L)
376 {
377         lua_newtable(L);
378
379         luaL_setfuncs(L, l_jail, 0);
380
381         lua_pushinteger(L, JAIL_CREATE);
382         lua_setfield(L, -2, "CREATE");
383         lua_pushinteger(L, JAIL_UPDATE);
384         lua_setfield(L, -2, "UPDATE");
385         lua_pushinteger(L, JAIL_ATTACH);
386         lua_setfield(L, -2, "ATTACH");
387         lua_pushinteger(L, JAIL_DYING);
388         lua_setfield(L, -2, "DYING");
389
390         return (1);
391 }