aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--ClientHamr/GuiLua/skang.lua292
1 files changed, 292 insertions, 0 deletions
diff --git a/ClientHamr/GuiLua/skang.lua b/ClientHamr/GuiLua/skang.lua
index a8a75ae..81e65af 100644
--- a/ClientHamr/GuiLua/skang.lua
+++ b/ClientHamr/GuiLua/skang.lua
@@ -1102,6 +1102,298 @@ GGG GUI Thing, but servlets can access them across the net.
1102 1102
1103For servlet only modules from an applet, the applet only loads the skanglet class, using it for all 1103For servlet only modules from an applet, the applet only loads the skanglet class, using it for all
1104access to the module. 1104access to the module.
1105
1106
1107Lua Security best practices -
1108
1109 From an email by Mike Pall -
1110
1111"The only reasonably safe way to run untrusted/malicious Lua scripts is
1112to sandbox it at the process level. Everything else has far too many
1113loopholes."
1114
1115http://lua-users.org/lists/lua-l/2011-02/msg01595.html
1116http://lua-users.org/lists/lua-l/2011-02/msg01609.html
1117http://lua-users.org/lists/lua-l/2011-02/msg01097.html
1118http://lua-users.org/lists/lua-l/2011-02/msg01106.html
1119
1120So that's processes, not threads like LuaProc does. B-(
1121
1122However, security in depth is good, so still worthwhile looking at it from other levels as well.
1123
1124General solution is to create a new environment, which we are doing
1125anyway, then whitelist the safe stuff into it, instead of blacklisting
1126unsafe stuff. Coz you never know if new unsafe stuff might exist.
1127
1128Different between 5.1 (setfenv) and 5.2 (_ENV)
1129
1130http://lua-users.org/wiki/SandBoxes -
1131
1132------------------------------------------------------
1133-- make environment
1134local env = -- add functions you know are safe here
1135{
1136 ipairs = ipairs,
1137 next = next,
1138 pairs = pairs,
1139 pcall = pcall,
1140 tonumber = tonumber,
1141 tostring = tostring,
1142 type = type,
1143 unpack = unpack,
1144 coroutine = { create = coroutine.create, resume = coroutine.resume,
1145 running = coroutine.running, status = coroutine.status,
1146 wrap = coroutine.wrap },
1147 string = { byte = string.byte, char = string.char, find = string.find,
1148 format = string.format, gmatch = string.gmatch, gsub = string.gsub,
1149 len = string.len, lower = string.lower, match = string.match,
1150 rep = string.rep, reverse = string.reverse, sub = string.sub,
1151 upper = string.upper },
1152 table = { insert = table.insert, maxn = table.maxn, remove = table.remove,
1153 sort = table.sort },
1154 math = { abs = math.abs, acos = math.acos, asin = math.asin,
1155 atan = math.atan, atan2 = math.atan2, ceil = math.ceil, cos = math.cos,
1156 cosh = math.cosh, deg = math.deg, exp = math.exp, floor = math.floor,
1157 fmod = math.fmod, frexp = math.frexp, huge = math.huge,
1158 ldexp = math.ldexp, log = math.log, log10 = math.log10, max = math.max,
1159 min = math.min, modf = math.modf, pi = math.pi, pow = math.pow,
1160 rad = math.rad, random = math.random, sin = math.sin, sinh = math.sinh,
1161 sqrt = math.sqrt, tan = math.tan, tanh = math.tanh },
1162 os = { clock = os.clock, difftime = os.difftime, time = os.time },
1163}
1164
1165-- run code under environment [Lua 5.1]
1166local function run(untrusted_code)
1167 if untrusted_code:byte(1) == 27 then return nil, "binary bytecode prohibited" end
1168 local untrusted_function, message = loadstring(untrusted_code)
1169 if not untrusted_function then return nil, message end
1170 setfenv(untrusted_function, env)
1171 return pcall(untrusted_function)
1172end
1173
1174-- run code under environment [Lua 5.2]
1175local function run(untrusted_code)
1176 local untrusted_function, message = load(untrusted_code, nil, 't', env)
1177 if not untrusted_function then return nil, message end
1178 return pcall(untrusted_function)
1179end
1180------------------------------------------------------
1181
1182Also includes a table of safe / unsafe stuff.
1183
1184
1185While whitelisting stuff, could also wrap unsafe stuff to make them more safe.
1186
1187print() -> should reroute to our output widgets.
1188rawget/set() -> don't bypass the metatables, but gets tricky and recursive.
1189require -> don't allow bypassing the sandbox to get access to restricted modules
1190package.loaded -> ditto
1191
1192
1193Other things to do -
1194
1195debug.sethook() can be used to call a hook every X lines, which can help with endless loops and such.
1196Have a custom memory allocater, like edje_lua2 does.
1197
1198------------------------------------------------------
1199------------------------------------------------------
1200
1201The plan -
1202
1203 Process level -
1204 Have a Lua script runner C program / library.
1205 It does the LuaProc thing, and the edje_lua2 memory allocater thing.
1206 Other code feeds scripts to it via a pipe.
1207 Unless they are using this as a library.
1208 It can be chrooted, ulimited, LXC containered, etc.
1209 It has an internal watchdog thread.
1210 The truly paranoid can have a watchdog timer process watch it.
1211 Watches for a "new Lua state pulled off the queue" signal.
1212 This could be done from the App that spawned it.
1213
1214 It runs a bunch of worker threads, with a queue of ready Lua states.
1215 Each Lua state being run has lua_sethook() set to run each X lines, AND a watchdog timer set.
1216 If either is hit, then the Lua state is put back on the queue.
1217 (Currently LuaProc states go back an the queue when waiting for a "channel message", which does a lua_yeild().)
1218 NOTE - apparently "compiled code" bypasses hooks, though there's an undocumented LuaJIT compile switch for that. http://lua-users.org/lists/lua-l/2011-02/msg01106.html
1219 EFL is event based.
1220 LSL is event based.
1221 LuaSL is event based.
1222 Java skang is event based, with anything that has long running stuff overriding runBit().
1223 Coz Java AWT is event based, the "events" are over ridden methods in each widget class.
1224 Should all work if we keep this as event based.
1225 An "event" is a bit of Lua script in a string, at Input trust level usually.
1226 Configurable for this script runner is -
1227 IP address & port, or pipe name.
1228 Security level to run at, defaults to Network.
1229 Number of worker threads, defaults to number of CPUs.
1230 Memory limit per Lua state.
1231 Lines & time per tick for Lua states.
1232
1233 Different levels of script trust -
1234 System - the local skang and similar stuff.
1235 -> No security at all.
1236 App - Lua scripts and C from the running application.
1237 -> Current module level security.
1238 Each has it's own environment, with no cross environment leakage.
1239 Runs in the Apps process, though that might be the script runner as a library.
1240 Or could be skang's main loop.
1241 Local - Lua scripts and skang files sent from the client apps running on the same system.
1242 -> As per App.
1243 Runs in a script runner, maybe? Or just the Apps script runner.
1244 Limit OS and file stuff, the client app can do those itself.
1245 Network - Lua scripts and skang files sent from the network.
1246 -> Runs in a script runner.
1247 Option to chroot it, ulimit it, etc.
1248 Heavily Lua sandboxed via environment.
1249 It can access nails, but via network derived credentials.
1250 Can have very limited local storage, not direct file access though, but via some sort of security layer.
1251 Can have network access.
1252 Can have GUI access, but only to it's own window.
1253 Config - Lua scripts run as configuration files.
1254 -> Almost empty local environment, can really only do math and set Things.
1255 Input - Lua scripts run as a result of hitting skang widgets on the other end of a socket.
1256 -> As per Config, but can include function calls.
1257 Also would need sanitizing, as this can come from the network.
1258 Microsoft - Not to be trusted at all.
1259 Apple - Don't expect them to trust us.
1260
1261 NOTE - edje_lua2 would be roughly Local trust level.
1262
1263 So we need to be able to pass Lua between processes -
1264 Have to be able to do it from C, from Lua, and from Lua embedded in C.
1265 edje_lua2 - uses Edje messages / signals.
1266 LuaSL - uses Ecore_Con, in this case a TCP port, even though it's only local.
1267 LuaSL mainloop for it's scripts is to basically wait for these messages from LuaProc.
1268 Which yield's until we get one.
1269 Eventually gets Lua code as a string -> loadstring() -> setfenv() -> pcall()
1270 The pcall returns a string that we send back as a LuaProc message.
1271 Extantz - we want to use stdin/stdout for the pipe, but otherwise LuaSL style semantics.
1272
1273 Hmm, Extantz could run external skang modules in two ways -
1274 Run the module as a separate app, with stdin/stdout.
1275 Require the module, and run it internally.
1276 Stuff like the in world editor and radar would be better as module, since they are useless outside Extantz?
1277 Radar is useless outside Extantz, editor could be used to edit a local file.
1278 Stuff like woMan would be better off as a separate application, so it can start and stop extantz.
1279
1280]]
1281
1282
1283--[[
1284The main loop.
1285 A Lua skang module is basically a table, with skang managed fields.
1286 Once it calls moduleEnd(), it's expected to have finished.
1287 test.lua is currently an exception, it runs test stuff afterwards.
1288 So their code just registers Things and local variables.
1289 Some of those Things might be functions for manipulating internal module state.
1290 A C module has it's variables managed outside of it by Lua.
1291 So would have to go via LUA_GLOBALSINDEX to get to them.
1292 Unless they are userdata, which are C things anyway.
1293 Though it's functions are obviously inside the C module.
1294 Normal Lua module semantics expect them to return to the require call after setting themselves up.
1295 So test.lua is really an aberation.
1296
1297 Soooo, where does the main loop go?
1298 The skang module itself could define the main loop.
1299 Should not actually call it though, coz skang is itself a module.
1300
1301 In Java we had different entry points depending on how it was called.
1302 If it was called as an applet or application, it got it's own thread with a mainloop.
1303 That main loop just slept and called runBit() on all registered modules.
1304 If it was loaded as a module, it bypassed that stuff.
1305 I don't think Lua provides any such mechanism.
1306 In theory, the first call to moduleBegin would be the one that was started as an application.
1307 So we could capture that, and test against it in moduleEnd to find when THAT module finally got to the end.
1308 THEN we can start the main loop (test.lua being the exception that fucks this up).
1309 Though test.lua could include a runBits() that quits the main loop, then starts the main loop at the very end once more?
1310 The problem with this is applications that require skang type modules.
1311 The first one they require() isn't going to return.
1312 Eventually skang itself will get loaded. It looks at the "arg" global, which SHOULD be the command line.
1313 Including the name of the application, which we could use to double check.
1314 Extantz / script runner would set this arg global itself.
1315
1316 Skang applications have one main loop per app.
1317 Skang modules use the main loop of what ever app called them.
1318 Non skang apps have the option of calling skangs main loop.
1319 Extantz starts many external skang apps, which each get their own main loop.
1320 Extantz has it's own Ecore main loop.
1321 LuaSL still has one main loop per script.
1322 LSL scripts get their own main loop, but LSL is stupid and doesn't have any real "module" type stuff.
1323
1324What does skang main loop actually do?
1325 In Java it just slept for a bit, then called runBit() from each module, and the only module that had one was watch.
1326 Actually better off using Ecore timers for that sort of thing.
1327 Skang main loop has nothing to do? lol
1328 Well, except for the "wait for LuaProc channel messages" thing.
1329 Widget main loop would be Ecore's main loop.
1330
1331 Extantz loads a skang module.
1332 Module runs in extantz script runner.
1333 Module runs luaproc message main loop from skang.
1334 Evas / Elm widgets send signals, call C callbacks.
1335 Extantz sends Lua input scripts via luaproc messages to module.
1336 Extantz runs separate skang module.
1337 Module runs in it's own process.
1338 Module runs it's own message loop on the end of stdin.
1339 Evas / Elm widgets send signals, call C callbacks.
1340 Extantz sends Lua Input scripts to module via stdout.
1341 Module runs stand alone.
1342 Module runs in it's own process.
1343 Module has to have widget start Ecore's main loop.
1344 Module runs it's own message loop, waiting for widget to send it messages.
1345 Evas / Elm widgets send signals, call C callbacks.
1346 Widget sends Lua Input scripts to module.
1347
1348Alternate plan -
1349 Skang has no main loop, modules are just tables.
1350 OK, so sometimes skang has to start up an Ecore main loop.
1351 With either Ecore_Con, or Evas and Elm.
1352 skang.message(string)
1353 Call it to pass a bit of Lua to skang, which is likely Input.
1354 Widget twiddles happen in Ecore's main loop, via signals and call backs.
1355 Eventually these call backs hit the widgets action string.
1356 Send that action string to skang.message().
1357
1358 Extantz loads a skang module.
1359 Extantz has a skang Lua state.
1360 Module is just another table in skang.
1361 Widget -> callback -> action string -> skang.message()
1362 Extantz runs separate skang module.
1363 Skang module C code runs an Ecore main loop.
1364 Module is just another table in skang.
1365 Skang C uses Ecore_Con to get messages from Extantz' Ecore_Con.
1366 Widget -> callback -> action string -> Ecore_Con -> skang.message()
1367 OOORRRR ....
1368 Skang runs a main loop reading stdin.
1369 Widget -> callback -> action string -> stdout -> skang.message()
1370 Module runs stand alone.
1371 Skang module C code runs an Ecore main loop.
1372 Module is just another table in skang.
1373 Widget -> callback -> action string -> skang.message()
1374 Extantz loads a skang module from the network.
1375 Skang module runs on the server with it's own Ecore main loop somehow.
1376 Module is just another table in skang.
1377 Extantz uses Ecore_Con to get messages from Extantz' Ecore_Con, via TCP.
1378 Widget -> callback -> action string -> Ecore_Con -> skang.message()
1379 OOORRRR ....
1380 Remember, these are untrusted, so that's what the script runner is for.
1381 Skang module runs in the script runner, with some sort of luaproc interface.
1382 Widget -> callback -> action string -> Ecore_Con -> luaproc -> skang.message()
1383
1384 Skang running as a web server.
1385 Skang runs an Ecore main loop.
1386 Skang has an Ecore_Con server attached to port 80.
1387 Skang loads modules as usual.
1388 Skang responds to specific URLs with HTML forms generated from Skang files.
1389 Skang gets post data back, which kinda looks like Input. B-)
1390
1391 Extantz runs a LuaSL / LSL script from the network.
1392 Send this one to the LuaSL script runner.
1393 Coz LSL scripts tend to have lots of copies with the same name in different objects.
1394 Could get too huge to deal with via "just another table".
1395 In this case, compiling the LSL might be needed to.
1396
1105]] 1397]]
1106 1398
1107 1399