Patch the AsyncSyscall v4 exploit from working

This commit is contained in:
2026-02-24 02:00:37 -06:00
parent ab1e847d1c
commit 415064480a
7 changed files with 83 additions and 39 deletions

View File

@@ -946,23 +946,16 @@ local function runCommand(command)
return return
end end
local text = fs.readAllText(cmdPath) local proc = syscall.spawn(function()
local program, err = load(text, progName) -- Open standard fds so programs that don't do it themselves work correctly.
if not program then syscall.open("/dev/tty/tty1", "r") -- fd 0 stdin
syscall.devctl(1,"sfgc",2) syscall.open("/dev/tty/tty1", "w") -- fd 1 stdout
local line, rest = tostring(err):match(":(%d+): (.+)$") syscall.open("/dev/null", "w") -- fd 2 stderr
if line then printInline(progName..": load error on line "..line..": "); print(rest) -- exec replaces this coroutine's code with a fresh isolated environment
else print(progName..": load error: "..tostring(err)) end -- compiled from disk by the kernel (via loadExecutable -> freshUserEnv),
syscall.devctl(1,"sfgc",1); return -- so the child cannot share any upvalue or syscall table state with hysh.
end syscall.exec(cmdPath, {table.unpack(args, 2)})
end, progName)
local proc = syscall.spawn(function(...)
syscall.open("/dev/tty/tty1","r")
syscall.open("/dev/tty/tty1","w")
syscall.open("/dev/null","w")
local ok2, msg = pcall(program, ...)
if not ok2 then printError(progName, msg) end
end, progName, nil, {table.unpack(args, 2)})
while true do while true do
local exited, code = syscall.collect(proc) local exited, code = syscall.collect(proc)

View File

@@ -8,7 +8,7 @@ local computer = args[6]
local ifs = args[7] local ifs = args[7]
local kernel = {} local kernel = {}
kernel.LOG_Text="" kernel.LOG_Text=""
kernel.version="HyperionOS V1.2.0" kernel.version="HyperionOS V1.2.3"
kernel.process = "Kernel" kernel.process = "Kernel"
kernel.users={[0]="root",[1]="User"} kernel.users={[0]="root",[1]="User"}
kernel.hostname = "hyperion" kernel.hostname = "hyperion"

View File

@@ -207,8 +207,12 @@ function toHex(num)
return string.format("%X", num) return string.format("%X", num)
end end
syscall = setmetatable({}, { local function makeSyscallProxy()
local backing = {}
return setmetatable(backing, {
__index = function(self, name) __index = function(self, name)
local raw = rawget(self, name)
if raw ~= nil then return raw end
return function(...) return function(...)
local res = table.pack(coroutine.yield("syscall", name, ...)) local res = table.pack(coroutine.yield("syscall", name, ...))
if res[1] then if res[1] then
@@ -217,7 +221,15 @@ syscall = setmetatable({}, {
error(res[2], 2) error(res[2], 2)
end end
end end
end end,
}) __newindex = function(self, k, v)
rawset(self, k, v)
end,
})
end
syscall = makeSyscallProxy()
_makeSyscallProxy = makeSyscallProxy
table.serialize = serialize table.serialize = serialize

View File

@@ -334,6 +334,13 @@ local function buildKeyMaps()
end end
kernel.processes.cctmond = function() kernel.processes.cctmond = function()
local _getTasks = function()
local ret = {}
for _, v in pairs(kernel.tasks) do ret[#ret+1] = v.pid end
return ret
end
local _sigsend = kernel.signal.sigsend
local timeout = false local timeout = false
while true do while true do
local event = {kernel.computer:getMachineEvent()} local event = {kernel.computer:getMachineEvent()}
@@ -352,8 +359,8 @@ kernel.processes.cctmond = function()
end end
if ctrl and charOrKey == apis.keys.c then if ctrl and charOrKey == apis.keys.c then
for _, task in ipairs(syscall.getTasks()) do for _, pid in ipairs(_getTasks()) do
syscall.sigsend(task, 1) _sigsend(pid, 1)
end end
end end

View File

@@ -55,3 +55,18 @@ local origLoad = load
kernel._U = readonly(kernel._G) kernel._U = readonly(kernel._G)
kernel._U._G = kernel._U kernel._U._G = kernel._U
kernel._U.load = function(a,b,c,d) return origLoad(a,b,c,d or kernel._U) end kernel._U.load = function(a,b,c,d) return origLoad(a,b,c,d or kernel._U) end
function kernel.freshUserEnv()
local locals = {}
locals.syscall = _makeSyscallProxy()
local env = setmetatable(locals, {
__index = kernel._U,
__newindex = function(_, k, v) rawset(locals, k, v) end,
})
locals._G = env
locals.load = function(a, b, c, d) return origLoad(a, b, c, d or env) end
return env
end

View File

@@ -11,14 +11,16 @@ local function bit_is_set(num, bit)
return math.floor(num / (2 ^ bit)) % 2 == 1 return math.floor(num / (2 ^ bit)) % 2 == 1
end end
local function loadExecutable(path, env) local function loadExecutable(path)
kernel.vfs.access(path, "rx") kernel.vfs.access(path, "rx")
local fd = kernel.vfs.open(path, "r") local fd = kernel.vfs.open(path, "r")
local data = kernel.vfs.read(fd, 1024 * 1024 * 4) local data = kernel.vfs.read(fd, 1024 * 1024 * 4)
kernel.vfs.close(fd) kernel.vfs.close(fd)
local func, err = load(data, "@" .. path, "t", env or kernel._U) local env = kernel.freshUserEnv()
local func, err = load(data, "@" .. path, "t", env)
if not func then error("ENOEXEC: " .. tostring(err)) end if not func then error("ENOEXEC: " .. tostring(err)) end
local meta = kernel.vfs.lstat(path) local meta = kernel.vfs.lstat(path)
@@ -357,10 +359,25 @@ function kernel.main()
if task.sigq and #task.sigq ~= 0 and task.sigh then if task.sigq and #task.sigq ~= 0 and task.sigh then
local coro = coroutine.create(task.sigh) local coro = coroutine.create(task.sigh)
if kernel.config.preempt then local sigret = { coroutine.resume(coro, table.remove(task.sigq, 1)) }
resumeWithTimeout(coro, task.timeSlice, table.remove(task.sigq, 1)) while coroutine.status(coro) ~= "dead" do
if sigret[1] == false then break end
if sigret[2] == "syscall" then
local scname = sigret[3]
local sysret
if kernel.syscalls[scname] then
sysret = { xpcall(kernel.syscalls[scname], debug.traceback, table.unpack(sigret, 4)) }
else else
coroutine.resume(coro, table.remove(task.sigq, 1)) sysret = { false, "Unknown syscall: " .. tostring(scname) }
end
if not sysret[1] then
sigret = { coroutine.resume(coro, false, sysret[2]) }
else
sigret = { coroutine.resume(coro, true, table.unpack(sysret, 2)) }
end
else
sigret = { coroutine.resume(coro) }
end
end end
end end

View File

@@ -2,7 +2,7 @@
local kernel = ... local kernel = ...
kernel.processes.login = function() kernel.processes.login = function()
local ok, err = pcall(syscall.execspawn, "/bin/login", "login") local ok, err = pcall(kernel.hpv.execspawn, "/bin/login", "login")
if not ok then if not ok then
kernel.log("Failed to exec /bin/login: " .. tostring(err), "ERROR", 2) kernel.log("Failed to exec /bin/login: " .. tostring(err), "ERROR", 2)
end end