mirror of
https://github.com/20kdc/OC-KittenOS.git
synced 2024-11-23 19:08:05 +11:00
Got rid of the nasty security-request system.
The new system is more hook-like, which is both good & bad, but frankly mostly good given the complexity out of kernel.
This commit is contained in:
parent
4a57c9f175
commit
0e97fbbfd6
@ -59,9 +59,6 @@ monitors[0] = {nil, nil, 80, 25}
|
|||||||
-- line y
|
-- line y
|
||||||
local surfaces = {}
|
local surfaces = {}
|
||||||
|
|
||||||
-- Dead process's switch to clean up resources by crashing processes which "just don't get it"
|
|
||||||
local dead = false
|
|
||||||
|
|
||||||
local savingThrow = neo.requestAccess("x.neo.sys.manage")
|
local savingThrow = neo.requestAccess("x.neo.sys.manage")
|
||||||
if savingThrow then
|
if savingThrow then
|
||||||
savingThrow.registerForShutdownEvent()
|
savingThrow.registerForShutdownEvent()
|
||||||
@ -73,7 +70,7 @@ if savingThrow then
|
|||||||
-- In this case the surfaces are leaked and hold references here. They have to be removed manually.
|
-- In this case the surfaces are leaked and hold references here. They have to be removed manually.
|
||||||
-- Do this via a "primary event" (k.deregistration) and "deathtrap events"
|
-- Do this via a "primary event" (k.deregistration) and "deathtrap events"
|
||||||
-- If a process evades the deathtrap then it clearly has reason to stay alive regardless of Everest status.
|
-- If a process evades the deathtrap then it clearly has reason to stay alive regardless of Everest status.
|
||||||
dead = true
|
-- Also note, should savingThrow fail, neo.dead is now a thing.
|
||||||
monitors = {}
|
monitors = {}
|
||||||
for _, v in ipairs(surfaces) do
|
for _, v in ipairs(surfaces) do
|
||||||
pcall(v[6], "line", 1)
|
pcall(v[6], "line", 1)
|
||||||
@ -335,7 +332,7 @@ everestProvider(function (pkg, pid, sendSig)
|
|||||||
local base = pkg .. "/" .. pid
|
local base = pkg .. "/" .. pid
|
||||||
local lid = 0
|
local lid = 0
|
||||||
return function (w, h, title)
|
return function (w, h, title)
|
||||||
if dead then error("everest died") end
|
if neo.dead then error("everest died") end
|
||||||
w = math.floor(math.max(w, 8))
|
w = math.floor(math.max(w, 8))
|
||||||
h = math.floor(math.max(h, 1)) + 1
|
h = math.floor(math.max(h, 1)) + 1
|
||||||
if type(title) ~= "string" then
|
if type(title) ~= "string" then
|
||||||
@ -410,7 +407,7 @@ everestProvider(function (pkg, pid, sendSig)
|
|||||||
return {
|
return {
|
||||||
id = llid,
|
id = llid,
|
||||||
setSize = function (w, h)
|
setSize = function (w, h)
|
||||||
if dead then return end
|
if neo.dead then return end
|
||||||
w = math.floor(math.max(w, 8))
|
w = math.floor(math.max(w, 8))
|
||||||
h = math.floor(math.max(h, 1)) + 1
|
h = math.floor(math.max(h, 1)) + 1
|
||||||
local _, x, y = ensureOnscreen(surf[1], surf[2], surf[3], w, h)
|
local _, x, y = ensureOnscreen(surf[1], surf[2], surf[3], w, h)
|
||||||
@ -418,7 +415,7 @@ everestProvider(function (pkg, pid, sendSig)
|
|||||||
return w, (h - 1)
|
return w, (h - 1)
|
||||||
end,
|
end,
|
||||||
span = function (x, y, text, bg, fg)
|
span = function (x, y, text, bg, fg)
|
||||||
if dead then error("everest died") end
|
if neo.dead then error("everest died") end
|
||||||
if type(x) ~= "number" then error("X must be number.") end
|
if type(x) ~= "number" then error("X must be number.") end
|
||||||
if type(y) ~= "number" then error("Y must be number.") end
|
if type(y) ~= "number" then error("Y must be number.") end
|
||||||
if type(bg) ~= "number" then error("Background must be number.") end
|
if type(bg) ~= "number" then error("Background must be number.") end
|
||||||
@ -429,7 +426,7 @@ everestProvider(function (pkg, pid, sendSig)
|
|||||||
handleSpan(surf, x, y + 1, text, bg, fg)
|
handleSpan(surf, x, y + 1, text, bg, fg)
|
||||||
end,
|
end,
|
||||||
close = function ()
|
close = function ()
|
||||||
if dead then return end
|
if neo.dead then return end
|
||||||
local os1 = surfaces[1]
|
local os1 = surfaces[1]
|
||||||
surfaceOwners[surf] = nil
|
surfaceOwners[surf] = nil
|
||||||
for k, v in ipairs(surfaces) do
|
for k, v in ipairs(surfaces) do
|
||||||
|
@ -4,17 +4,15 @@
|
|||||||
-- s-donkonit : config, shutdown, screens
|
-- s-donkonit : config, shutdown, screens
|
||||||
|
|
||||||
-- Doesn't matter what calls this service, because there's a mutex here.
|
-- Doesn't matter what calls this service, because there's a mutex here.
|
||||||
local donkonitSPProvider = neo.requestAccess("r.neo.sys.manage") -- Restrict to s-
|
local donkonitSPProvider = neo.requireAccess("r.neo.sys.manage", "creating NEO core APIs") -- Restrict to s-
|
||||||
if not donkonitSPProvider then return end
|
local donkonitRDProvider = neo.requireAccess("r.neo.sys.screens", "creating NEO core APIs")
|
||||||
local donkonitRDProvider = neo.requestAccess("r.neo.sys.screens")
|
|
||||||
if not donkonitRDProvider then return end
|
|
||||||
|
|
||||||
local computer = neo.requestAccess("k.computer")
|
local computer = neo.requireAccess("k.computer", "shutting down")
|
||||||
local fs = neo.requestAccess("c.filesystem")
|
local fs = neo.requireAccess("c.filesystem", "settings I/O")
|
||||||
local gpus = neo.requestAccess("c.gpu")
|
local gpus = neo.requireAccess("c.gpu", "screen control")
|
||||||
local screens = neo.requestAccess("c.screen")
|
local screens = neo.requireAccess("c.screen", "screen control")
|
||||||
neo.requestAccess("s.h.component_added")
|
neo.requireAccess("s.h.component_added", "HW management")
|
||||||
neo.requestAccess("s.h.component_removed")
|
neo.requireAccess("s.h.component_removed", "HW management")
|
||||||
|
|
||||||
local function shutdownFin(reboot)
|
local function shutdownFin(reboot)
|
||||||
-- any final actions donkonit needs to take here
|
-- any final actions donkonit needs to take here
|
||||||
|
@ -9,15 +9,11 @@ local neoux, err = require("neoux")
|
|||||||
if not neoux then error(err) end -- This app is basically neoux's testcase
|
if not neoux then error(err) end -- This app is basically neoux's testcase
|
||||||
neoux = neoux(event, neo)
|
neoux = neoux(event, neo)
|
||||||
|
|
||||||
local donkonit = neo.requestAccess("x.neo.sys.manage")
|
local settings = neo.requireAccess("x.neo.sys.manage", "security sysconf access")
|
||||||
if not donkonit then error("needs donkonit for sysconf access") end
|
|
||||||
local scr = neo.requestAccess("s.k.securityrequest")
|
|
||||||
if not scr then error("no security request access") end
|
|
||||||
|
|
||||||
local fs = neo.requestAccess("c.filesystem")
|
local fs = neo.requireAccess("c.filesystem", "file managers")
|
||||||
|
|
||||||
local donkonitDFProvider = neo.requestAccess("r.neo.pub.base")
|
local donkonitDFProvider = neo.requireAccess("r.neo.pub.base", "creating basic NEO APIs")
|
||||||
if not donkonitDFProvider then return end
|
|
||||||
|
|
||||||
local targsDH = {} -- data disposal
|
local targsDH = {} -- data disposal
|
||||||
|
|
||||||
@ -110,14 +106,34 @@ donkonitDFProvider(function (pkg, pid, sendSig)
|
|||||||
}
|
}
|
||||||
end)
|
end)
|
||||||
|
|
||||||
event.listen("k.securityrequest", function (evt, pkg, pid, perm, rsp)
|
-- Connect in security policy now
|
||||||
|
local rootAccess = neo.requireAccess("k.root", "installing GUI integration")
|
||||||
|
local backup = rootAccess.securityPolicyINIT or rootAccess.securityPolicy
|
||||||
|
rootAccess.securityPolicyINIT = backup
|
||||||
|
rootAccess.securityPolicy = function (pid, proc, req)
|
||||||
|
if neo.dead then
|
||||||
|
return backup(pid, proc, req)
|
||||||
|
end
|
||||||
|
req.result = proc.pkg:sub(1, 4) == "sys-"
|
||||||
local secpol, err = require("sys-secpolicy")
|
local secpol, err = require("sys-secpolicy")
|
||||||
if not secpol then
|
if not secpol then
|
||||||
rsp(false)
|
-- Failsafe.
|
||||||
error("Bad security policy: " .. err)
|
neo.emergency("Used fallback policy because of load-err: " .. err)
|
||||||
|
req.service()
|
||||||
|
return
|
||||||
end
|
end
|
||||||
secpol(neoux, donkonit, pkg, pid, perm, rsp)
|
-- Push to ICECAP thread to avoid deadlock on neoux b/c wrong event-pull context
|
||||||
|
event.runAt(0, function ()
|
||||||
|
local ok, err = pcall(secpol, neoux, settings, proc.pkg, pid, req.perm, function (r)
|
||||||
|
req.result = r
|
||||||
|
req.service()
|
||||||
end)
|
end)
|
||||||
|
if not ok then
|
||||||
|
neo.emergency("Used fallback policy because of run-err: " .. err)
|
||||||
|
req.service()
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
event.listen("k.procdie", function (evt, pkg, pid, reason)
|
event.listen("k.procdie", function (evt, pkg, pid, reason)
|
||||||
if targsDH[pid] then
|
if targsDH[pid] then
|
||||||
|
@ -281,6 +281,31 @@ end
|
|||||||
|
|
||||||
local function initializeSystem()
|
local function initializeSystem()
|
||||||
-- System has just booted, bristol is in charge
|
-- System has just booted, bristol is in charge
|
||||||
|
-- IMMEDIATELY install security policy in a TSR-like manner,
|
||||||
|
-- using root privs to keep it going when sys-init's not around
|
||||||
|
local rootAccess = neo.requireAccess("k.root", "installing security (YOU SHOULD NEVER SEE THIS)")
|
||||||
|
rootAccess.securityPolicy = function (pid, proc, req)
|
||||||
|
req.result = proc.pkg:sub(1, 4) == "sys-"
|
||||||
|
local secpol, err = require("sys-secpolicy")
|
||||||
|
if not secpol then
|
||||||
|
-- Failsafe.
|
||||||
|
neo.emergency("Used fallback policy because of load-err: " .. err)
|
||||||
|
req.service()
|
||||||
|
end
|
||||||
|
local settings
|
||||||
|
pcall(function ()
|
||||||
|
-- basically pull system settings from thin air
|
||||||
|
settings = rootAccess.retrieveAccess("x.neo.sys.manage", "sys-init", -1)
|
||||||
|
end)
|
||||||
|
local ok, err = pcall(secpol, nil, settings, proc.pkg, pid, req.perm, function (r)
|
||||||
|
req.result = r
|
||||||
|
req.service()
|
||||||
|
end)
|
||||||
|
if not ok then
|
||||||
|
neo.emergency("Used fallback policy because of run-err: " .. err)
|
||||||
|
req.service()
|
||||||
|
end
|
||||||
|
end
|
||||||
-- Firstly, initialize hardware to something sensible since we don't know scrcfg
|
-- Firstly, initialize hardware to something sensible since we don't know scrcfg
|
||||||
gpu = neo.requestAccess("c.gpu").list()()
|
gpu = neo.requestAccess("c.gpu").list()()
|
||||||
if gpu then
|
if gpu then
|
||||||
|
155
code/init.lua
155
code/init.lua
@ -16,7 +16,7 @@ local readBufSize = 2048
|
|||||||
-- A function used for logging, usable by programs.
|
-- A function used for logging, usable by programs.
|
||||||
-- Comment this out if you don't want programs to have
|
-- Comment this out if you don't want programs to have
|
||||||
-- access to ocemu's logger.
|
-- access to ocemu's logger.
|
||||||
local emergencyFunction
|
local emergencyFunction = function () end
|
||||||
local ocemu = component.list("ocemu", true)()
|
local ocemu = component.list("ocemu", true)()
|
||||||
if ocemu then
|
if ocemu then
|
||||||
ocemu = component.proxy(ocemu)
|
ocemu = component.proxy(ocemu)
|
||||||
@ -25,6 +25,7 @@ end
|
|||||||
|
|
||||||
primaryDisk = component.proxy(computer.getBootAddress())
|
primaryDisk = component.proxy(computer.getBootAddress())
|
||||||
|
|
||||||
|
-- {{time, func, arg1...}...}
|
||||||
timers = {}
|
timers = {}
|
||||||
|
|
||||||
libraries = {}
|
libraries = {}
|
||||||
@ -36,7 +37,7 @@ setmetatable(libraries, {
|
|||||||
-- proc.pkg = "pkg"
|
-- proc.pkg = "pkg"
|
||||||
-- proc.access = {["perm"] = true, ...}
|
-- proc.access = {["perm"] = true, ...}
|
||||||
-- proc.denied = {["perm"] = true, ...}
|
-- proc.denied = {["perm"] = true, ...}
|
||||||
-- proc.deathcbs = {function(), ...}
|
-- proc.deathCBs = {function(), ...}
|
||||||
-- very slightly adjusted total CPU time
|
-- very slightly adjusted total CPU time
|
||||||
-- proc.cpuUsage
|
-- proc.cpuUsage
|
||||||
processes = {}
|
processes = {}
|
||||||
@ -44,12 +45,6 @@ processes = {}
|
|||||||
accesses = {}
|
accesses = {}
|
||||||
local lastPID = 0
|
local lastPID = 0
|
||||||
|
|
||||||
-- keys: <any>
|
|
||||||
-- sr.waiting: keys are PIDs, values are just "true"
|
|
||||||
-- sr.service: function()
|
|
||||||
-- sr.result: boolean
|
|
||||||
local outstandingSR = {}
|
|
||||||
|
|
||||||
-- Kernel global "idle time" counter, useful for accurate performance data
|
-- Kernel global "idle time" counter, useful for accurate performance data
|
||||||
local idleTime = 0
|
local idleTime = 0
|
||||||
|
|
||||||
@ -184,7 +179,7 @@ local function termProc(pid, reason)
|
|||||||
-- Immediately prepare for GC, it's possible this is out of memory.
|
-- Immediately prepare for GC, it's possible this is out of memory.
|
||||||
-- If out of memory, then to reduce risk of memory leak by error, memory needs to be freed ASAP.
|
-- If out of memory, then to reduce risk of memory leak by error, memory needs to be freed ASAP.
|
||||||
-- Start by getting rid of all process data.
|
-- Start by getting rid of all process data.
|
||||||
local dcbs = processes[pid].deathcbs
|
local dcbs = processes[pid].deathCBs
|
||||||
local pkg = processes[pid].pkg
|
local pkg = processes[pid].pkg
|
||||||
local usage = processes[pid].cpuUsage
|
local usage = processes[pid].cpuUsage
|
||||||
processes[pid] = nil
|
processes[pid] = nil
|
||||||
@ -197,7 +192,7 @@ local function termProc(pid, reason)
|
|||||||
if reason and criticalFailure then
|
if reason and criticalFailure then
|
||||||
error(tostring(reason)) -- This is a debugging aid to give development work an easy-to-get-at outlet. Icecap is for most cases
|
error(tostring(reason)) -- This is a debugging aid to give development work an easy-to-get-at outlet. Icecap is for most cases
|
||||||
end
|
end
|
||||||
if reason and emergencyFunction then
|
if reason then
|
||||||
emergencyFunction("d1 " .. pkg .. "/" .. pid)
|
emergencyFunction("d1 " .. pkg .. "/" .. pid)
|
||||||
emergencyFunction("d2 " .. reason)
|
emergencyFunction("d2 " .. reason)
|
||||||
end
|
end
|
||||||
@ -240,19 +235,17 @@ function distEvent(pid, s, ...)
|
|||||||
if not v then
|
if not v then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if (not v.access["s." .. s]) or v.access["k.root"] then
|
if not (v.access["s." .. s] or v.access["k.root"]) then
|
||||||
return
|
|
||||||
end
|
|
||||||
-- Schedule a timer for "now"
|
|
||||||
table.insert(timers, {computer.uptime(), function ()
|
|
||||||
return execEvent(pid, s, table.unpack(ev))
|
|
||||||
end})
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
-- Schedule the timer to carry the event.
|
||||||
|
table.insert(timers, {0, execEvent, pid, s, table.unpack(ev)})
|
||||||
|
else
|
||||||
for k, v in pairs(processes) do
|
for k, v in pairs(processes) do
|
||||||
distEvent(k, s, ...)
|
distEvent(k, s, ...)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local loadLibraryInner = nil
|
local loadLibraryInner = nil
|
||||||
|
|
||||||
@ -337,6 +330,26 @@ function loadLibraryInner(library)
|
|||||||
return nil, r
|
return nil, r
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- These two are hooks for k.root level applications to change policy.
|
||||||
|
-- Only a k.root application is allowed to do this for obvious reasons.
|
||||||
|
function securityPolicy(pid, proc, req)
|
||||||
|
-- Important safety measure : only sys-init gets anything until sys-init decides what to do.
|
||||||
|
req.result = proc.pkg == "sys-init"
|
||||||
|
req.service()
|
||||||
|
end
|
||||||
|
function runProgramPolicy(ipkg, pkg, pid, ...)
|
||||||
|
-- VERY specific injunction here:
|
||||||
|
-- non "sys-" apps NEVER start "sys-" apps
|
||||||
|
-- This is part of the "default security policy" below:
|
||||||
|
-- sys- has all access
|
||||||
|
-- anything else has none
|
||||||
|
if ipkg:sub(1, 4) == "sys-" then
|
||||||
|
if pkg:sub(1, 4) ~= "sys-" then
|
||||||
|
return nil, "non-sys app trying to start sys app"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function retrieveAccess(perm, pkg, pid)
|
function retrieveAccess(perm, pkg, pid)
|
||||||
-- Return the access lib and the death callback.
|
-- Return the access lib and the death callback.
|
||||||
|
|
||||||
@ -344,12 +357,16 @@ function retrieveAccess(perm, pkg, pid)
|
|||||||
-- "c.<hw>": Component
|
-- "c.<hw>": Component
|
||||||
-- "s.<event>": Signal receiver (with responsibilities for Security Request watchers)
|
-- "s.<event>": Signal receiver (with responsibilities for Security Request watchers)
|
||||||
-- "s.k.<...>": Kernel stuff
|
-- "s.k.<...>": Kernel stuff
|
||||||
-- "s.k.securityrequest": !!! HAS SIDE EFFECTS !!!
|
-- "s.k.procnew" : New process (pkg, pid)
|
||||||
|
-- "s.k.procdie" : Process dead (pkg, pid, reason, usage)
|
||||||
|
-- "s.k.registration" : Registration of service alert ("x." .. etc)
|
||||||
|
-- "s.k.deregistration" : Registration of service alert ("x." .. etc)
|
||||||
|
-- "s.k.securityresponse" : Response from security policy (accessId, accessObj)
|
||||||
-- "s.h.<...>": Incoming HW messages
|
-- "s.h.<...>": Incoming HW messages
|
||||||
-- "s.x.<endpoint>": This access is actually useless on it's own - it is given by x.<endpoint>
|
-- "s.x.<endpoint>": This access is actually useless on it's own - it is given by x.<endpoint>
|
||||||
|
|
||||||
-- "k.<x>": Kernel
|
-- "k.<x>": Kernel
|
||||||
-- "k.root": _ENV (holy grail)
|
-- "k.root": _ENV (holy grail), and indirectly security request control (which is basically equivalent to this)
|
||||||
-- "k.computer": computer
|
-- "k.computer": computer
|
||||||
|
|
||||||
-- "r.<endpoint>": Registration Of Service...
|
-- "r.<endpoint>": Registration Of Service...
|
||||||
@ -441,24 +458,15 @@ end
|
|||||||
local start = nil
|
local start = nil
|
||||||
|
|
||||||
function start(pkg, ...)
|
function start(pkg, ...)
|
||||||
ensureType(pkg, "string")
|
|
||||||
ensurePathComponent(pkg .. ".lua")
|
|
||||||
local args = {...}
|
local args = {...}
|
||||||
local proc = {}
|
local proc = {}
|
||||||
local pid = lastPID
|
local pid = lastPID
|
||||||
lastPID = lastPID + 1
|
lastPID = lastPID + 1
|
||||||
|
|
||||||
local function startFromUser(ipkg, ...)
|
local function startFromUser(ipkg, ...)
|
||||||
-- VERY specific injunction here:
|
ensureType(pkg, "string")
|
||||||
-- non "sys-" apps NEVER start "sys-" apps
|
ensurePathComponent(pkg .. ".lua")
|
||||||
-- This is part of the "default security policy" below:
|
runProgramPolicy(ipkg, pkg, pid, ...)
|
||||||
-- sys- has all access
|
|
||||||
-- anything else has none
|
|
||||||
if ipkg:sub(1, 4) == "sys-" then
|
|
||||||
if pkg:sub(1, 4) ~= "sys-" then
|
|
||||||
return nil, "non-sys app trying to start sys app"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return start(ipkg, pkg, pid, ...)
|
return start(ipkg, pkg, pid, ...)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -479,16 +487,17 @@ function start(pkg, ...)
|
|||||||
ensureType(perm, "string")
|
ensureType(perm, "string")
|
||||||
-- Safety-checked, prepare security event.
|
-- Safety-checked, prepare security event.
|
||||||
local req = {}
|
local req = {}
|
||||||
req.waiting = {}
|
req.perm = perm
|
||||||
req.service = function ()
|
req.service = function ()
|
||||||
if processes[pid] then
|
if processes[pid] then
|
||||||
local n = nil
|
local n = nil
|
||||||
local n2 = nil
|
local n2 = nil
|
||||||
if req.result then
|
if req.result then
|
||||||
proc.access[perm] = true
|
proc.access[perm] = true
|
||||||
|
proc.denied[perm] = nil
|
||||||
n, n2 = retrieveAccess(perm, pkg, pid)
|
n, n2 = retrieveAccess(perm, pkg, pid)
|
||||||
if n2 then
|
if n2 then
|
||||||
table.insert(processes[pid].deathcbs, n2)
|
table.insert(processes[pid].deathCBs, n2)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
proc.denied[perm] = true
|
proc.denied[perm] = true
|
||||||
@ -496,40 +505,21 @@ function start(pkg, ...)
|
|||||||
distEvent(pid, "k.securityresponse", perm, n)
|
distEvent(pid, "k.securityresponse", perm, n)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
req.result = (not proc.denied[perm]) or proc.access["k.root"]
|
-- outer security policy:
|
||||||
|
req.result = proc.access["k.root"] or not proc.denied[perm]
|
||||||
|
|
||||||
if proc.access["k.root"] or proc.access[perm] or proc.denied[perm] then
|
if proc.access["k.root"] or proc.access[perm] or proc.denied[perm] then
|
||||||
-- Use cached result to prevent possible unintentional security service spam
|
-- Use cached result to prevent possible unintentional security service spam
|
||||||
req.service()
|
req.service()
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
-- Anything with s.k.securityrequest access has the response function and thus the vote,
|
-- Denied goes to on to prevent spam
|
||||||
-- but can't vote on itself for obvious reasons. Kernel judge is a fallback.
|
proc.denied[perm] = true
|
||||||
local shouldKernelJudge = true
|
securityPolicy(pid, proc, req)
|
||||||
for k, v in pairs(processes) do
|
|
||||||
if v.access["s.k.securityrequest"] then
|
|
||||||
shouldKernelJudge = false
|
|
||||||
if k ~= pid then
|
|
||||||
req.waiting[k] = true
|
|
||||||
distEvent(k, "k.securityrequest", pkg, pid, perm, function (r)
|
|
||||||
ensureType(r, "boolean")
|
|
||||||
if not r then
|
|
||||||
req.result = false
|
|
||||||
end
|
|
||||||
req.waiting[k] = nil
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if shouldKernelJudge then
|
|
||||||
-- Rather restrictive, but an important safety measure
|
|
||||||
req.result = pkg:sub(1, 4) == "sys-"
|
|
||||||
req.service()
|
|
||||||
else
|
|
||||||
table.insert(outstandingSR, req)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
local env = baseProcEnv()
|
local env = baseProcEnv()
|
||||||
env.neo.pid = pid
|
env.neo.pid = pid
|
||||||
|
env.neo.dead = false
|
||||||
env.neo.executeAsync = startFromUser
|
env.neo.executeAsync = startFromUser
|
||||||
env.neo.execute = function (...)
|
env.neo.execute = function (...)
|
||||||
return osExecuteCore(function () end, ...)
|
return osExecuteCore(function () end, ...)
|
||||||
@ -548,12 +538,16 @@ function start(pkg, ...)
|
|||||||
handler(table.unpack(n))
|
handler(table.unpack(n))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
env.neo.requireAccess = function (perm, reason)
|
||||||
|
-- Allows for hooking
|
||||||
|
local res = env.neo.requestAccess(perm)
|
||||||
|
if not res then error(pkg .. " needed " .. perm .. " for " .. (reason or "some reason")) end
|
||||||
|
return res
|
||||||
|
end
|
||||||
env.neo.scheduleTimer = function (time)
|
env.neo.scheduleTimer = function (time)
|
||||||
ensureType(time, "number")
|
ensureType(time, "number")
|
||||||
local tag = {}
|
local tag = {}
|
||||||
table.insert(timers, {time, function(ofs)
|
table.insert(timers, {time, execEvent, pid, "k.timer", tag, time, ofs})
|
||||||
return execEvent(pid, "k.timer", tag, time, ofs)
|
|
||||||
end})
|
|
||||||
return tag
|
return tag
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -571,11 +565,13 @@ function start(pkg, ...)
|
|||||||
["s.k.procdie"] = true,
|
["s.k.procdie"] = true,
|
||||||
-- Used when a registration is updated, in particular, as this signifies "readiness"
|
-- Used when a registration is updated, in particular, as this signifies "readiness"
|
||||||
["s.k.registration"] = true,
|
["s.k.registration"] = true,
|
||||||
|
["s.k.deregistration"] = true
|
||||||
}
|
}
|
||||||
proc.denied = {}
|
proc.denied = {}
|
||||||
proc.deathcbs = {}
|
-- You are dead. Not big surprise.
|
||||||
|
proc.deathCBs = {function () pcall(function () env.neo.dead = true end) end}
|
||||||
proc.cpuUsage = 0
|
proc.cpuUsage = 0
|
||||||
-- Note the target process doesn't get the procnew (it's executed after it's creation)
|
-- Note the target process doesn't get the procnew (the dist occurs before it's creation)
|
||||||
pcall(distEvent, nil, "k.procnew", pkg, pid)
|
pcall(distEvent, nil, "k.procnew", pkg, pid)
|
||||||
processes[pid] = proc
|
processes[pid] = proc
|
||||||
-- For processes waiting on others, this at least tries to guarantee some safety.
|
-- For processes waiting on others, this at least tries to guarantee some safety.
|
||||||
@ -589,34 +585,10 @@ function start(pkg, ...)
|
|||||||
return pid
|
return pid
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Main Scheduling Loop --
|
-- Kernel Scheduling Loop --
|
||||||
|
|
||||||
local function processSRs()
|
|
||||||
local didAnything = false
|
|
||||||
for k, v in pairs(outstandingSR) do
|
|
||||||
-- Outstanding security request handler.
|
|
||||||
local actualWaitingCount = 0
|
|
||||||
for k2, _ in pairs(v.waiting) do
|
|
||||||
if not processes[k2] then
|
|
||||||
v.waiting[k2] = nil
|
|
||||||
v.result = false
|
|
||||||
else
|
|
||||||
actualWaitingCount = actualWaitingCount + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if actualWaitingCount == 0 then
|
|
||||||
-- Service the SR
|
|
||||||
outstandingSR[k].service()
|
|
||||||
outstandingSR[k] = nil
|
|
||||||
didAnything = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return didAnything
|
|
||||||
end
|
|
||||||
|
|
||||||
-- The actual loop & initialization
|
|
||||||
|
|
||||||
if not start("sys-init") then error("Could not start sys-init") end
|
if not start("sys-init") then error("Could not start sys-init") end
|
||||||
|
|
||||||
while true do
|
while true do
|
||||||
local tmr = nil
|
local tmr = nil
|
||||||
for i = 1, 16 do
|
for i = 1, 16 do
|
||||||
@ -628,7 +600,7 @@ while true do
|
|||||||
while timers[k] do
|
while timers[k] do
|
||||||
local v = timers[k]
|
local v = timers[k]
|
||||||
if v[1] <= now then
|
if v[1] <= now then
|
||||||
if v[2](now - v[1]) then
|
if v[2](table.unpack(v, 3)) then
|
||||||
breaking = true
|
breaking = true
|
||||||
tmr = 0.05
|
tmr = 0.05
|
||||||
break
|
break
|
||||||
@ -649,7 +621,6 @@ while true do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
if breaking then break end
|
if breaking then break end
|
||||||
didAnything = didAnything or processSRs()
|
|
||||||
-- If the system didn't make any progress, then we're waiting for a signal (this includes timers)
|
-- If the system didn't make any progress, then we're waiting for a signal (this includes timers)
|
||||||
if not didAnything then break end
|
if not didAnything then break end
|
||||||
end
|
end
|
||||||
|
@ -53,12 +53,11 @@ end
|
|||||||
|
|
||||||
return function (neoux, settings, pkg, pid, perm, rsp)
|
return function (neoux, settings, pkg, pid, perm, rsp)
|
||||||
local res = actualPolicy(pkg, pid, perm)
|
local res = actualPolicy(pkg, pid, perm)
|
||||||
if res == "ask" then
|
if res == "ask" and settings then
|
||||||
res = settings.getSetting("perm|" .. pkg .. "|" .. perm) or "ask"
|
res = settings.getSetting("perm|" .. pkg .. "|" .. perm) or "ask"
|
||||||
end
|
end
|
||||||
if res == "ask" then
|
if res == "ask" and neoux then
|
||||||
local fmt = neoux.fmtText(unicode.safeTextFormat(string.format("%s/%i wants:\n%s\nAllow this?", pkg, pid, perm)), 20)
|
local fmt = neoux.fmtText(unicode.safeTextFormat(string.format("%s/%i wants:\n%s\nAllow this?", pkg, pid, perm)), 20)
|
||||||
|
|
||||||
local always = "Always"
|
local always = "Always"
|
||||||
local yes = "Yes"
|
local yes = "Yes"
|
||||||
local no = "No"
|
local no = "No"
|
||||||
@ -73,7 +72,9 @@ return function (neoux, settings, pkg, pid, perm, rsp)
|
|||||||
w.close()
|
w.close()
|
||||||
end),
|
end),
|
||||||
neoux.tcbutton((#yes) + 3, #fmt + 2, always, function (w)
|
neoux.tcbutton((#yes) + 3, #fmt + 2, always, function (w)
|
||||||
|
if settings then
|
||||||
settings.setSetting("perm|" .. pkg .. "|" .. perm, "allow")
|
settings.setSetting("perm|" .. pkg .. "|" .. perm, "allow")
|
||||||
|
end
|
||||||
rsp(true)
|
rsp(true)
|
||||||
w.close()
|
w.close()
|
||||||
end),
|
end),
|
||||||
|
Loading…
Reference in New Issue
Block a user