1.2.4 #6
No files matched your search
@@ -64,12 +64,18 @@ local newGid = resolveGid(groupStr)
|
|||||||
local function chgrpPath(path)
|
local function chgrpPath(path)
|
||||||
local stat = syscall.stat(path)
|
local stat = syscall.stat(path)
|
||||||
if not stat then
|
if not stat then
|
||||||
print(name .. ": cannot stat '" .. path .. "': No such file or directory")
|
print(name .. ": cannot stat '" .. path .. "': no such file or directory")
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
local ok, err = pcall(syscall.chown, path, stat.owner, newGid)
|
local ok, err = pcall(syscall.chown, path, stat.owner, newGid)
|
||||||
if not ok then
|
if not ok then
|
||||||
print(name .. ": cannot change group of '" .. path .. "': " .. tostring(err))
|
local msg = tostring(err)
|
||||||
|
if msg:find("EPERM") or msg:find("EACCES") then
|
||||||
|
msg = "operation not permitted (must be root)"
|
||||||
|
elseif msg:find("ENOENT") then
|
||||||
|
msg = "no such file or directory"
|
||||||
|
end
|
||||||
|
print(name .. ": cannot change group of '" .. path .. "': " .. msg)
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
|
|||||||
@@ -220,7 +220,13 @@ local function chmodPath(path)
|
|||||||
|
|
||||||
local ok, cerr = pcall(syscall.chmod, path, newPerms)
|
local ok, cerr = pcall(syscall.chmod, path, newPerms)
|
||||||
if not ok then
|
if not ok then
|
||||||
print(name .. ": cannot change permissions of '" .. path .. "': " .. tostring(cerr))
|
local msg = tostring(cerr)
|
||||||
|
if msg:find("EACCES") or msg:find("EPERM") then
|
||||||
|
msg = "permission denied"
|
||||||
|
elseif msg:find("ENOENT") then
|
||||||
|
msg = "no such file or directory"
|
||||||
|
end
|
||||||
|
print(name .. ": cannot change permissions of '" .. path .. "': " .. msg)
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
|
|||||||
@@ -95,14 +95,20 @@ end
|
|||||||
local function chownPath(path)
|
local function chownPath(path)
|
||||||
local stat = syscall.stat(path)
|
local stat = syscall.stat(path)
|
||||||
if not stat then
|
if not stat then
|
||||||
print(name .. ": cannot stat '" .. path .. "': No such file or directory")
|
print(name .. ": cannot stat '" .. path .. "': no such file or directory")
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
local uid = newUid ~= nil and newUid or stat.owner
|
local uid = newUid ~= nil and newUid or stat.owner
|
||||||
local gid = newGid ~= nil and newGid or stat.group
|
local gid = newGid ~= nil and newGid or stat.group
|
||||||
local ok, err = pcall(syscall.chown, path, uid, gid)
|
local ok, err = pcall(syscall.chown, path, uid, gid)
|
||||||
if not ok then
|
if not ok then
|
||||||
print(name .. ": cannot change owner of '" .. path .. "': " .. tostring(err))
|
local msg = tostring(err)
|
||||||
|
if msg:find("EPERM") or msg:find("EACCES") then
|
||||||
|
msg = "operation not permitted (must be root)"
|
||||||
|
elseif msg:find("ENOENT") then
|
||||||
|
msg = "no such file or directory"
|
||||||
|
end
|
||||||
|
print(name .. ": cannot change owner of '" .. path .. "': " .. msg)
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ local host_str = syscall.getHost() or "Unknown"
|
|||||||
local cc_ver = host_str:match("ComputerCraft ([%d%.]+)") or host_str
|
local cc_ver = host_str:match("ComputerCraft ([%d%.]+)") or host_str
|
||||||
|
|
||||||
local info = {
|
local info = {
|
||||||
-- {label, value} label=nil means print value as-is (userhost / separator)
|
|
||||||
{nil, userhost},
|
{nil, userhost},
|
||||||
{nil, string.rep("-", #userhost)},
|
{nil, string.rep("-", #userhost)},
|
||||||
{"OS", syscall.version() or "Unknown"},
|
{"OS", syscall.version() or "Unknown"},
|
||||||
@@ -42,7 +41,7 @@ local info = {
|
|||||||
{"Uptime", formatUptime(syscall.getUptime() or 0)},
|
{"Uptime", formatUptime(syscall.getUptime() or 0)},
|
||||||
{"Tasks", tostring(#(syscall.getTasks() or {}))},
|
{"Tasks", tostring(#(syscall.getTasks() or {}))},
|
||||||
{"Shell", syscall.getEnviron("SHELL") or "Unknown"},
|
{"Shell", syscall.getEnviron("SHELL") or "Unknown"},
|
||||||
{"Terminal", "TTY1"},
|
{"Terminal", "tty1"},
|
||||||
{"UID", tostring(syscall.getuid())},
|
{"UID", tostring(syscall.getuid())},
|
||||||
{"Packages", "n/a (spm)"},
|
{"Packages", "n/a (spm)"},
|
||||||
}
|
}
|
||||||
@@ -71,15 +70,12 @@ local lines = math.max(#logo, #info)
|
|||||||
for i = 1, lines do
|
for i = 1, lines do
|
||||||
local logo_str = logo[i] or string.rep(" ", 36)
|
local logo_str = logo[i] or string.rep(" ", 36)
|
||||||
|
|
||||||
-- print logo segment in cyan
|
|
||||||
c(C_LOGO)
|
c(C_LOGO)
|
||||||
printInline(logo_str)
|
printInline(logo_str)
|
||||||
|
|
||||||
-- print separator pipe
|
|
||||||
c(C_LABEL)
|
c(C_LABEL)
|
||||||
printInline("| ")
|
printInline("| ")
|
||||||
|
|
||||||
-- print info segment
|
|
||||||
local row = info[i]
|
local row = info[i]
|
||||||
if row then
|
if row then
|
||||||
if row[1] == nil and i == 1 then
|
if row[1] == nil and i == 1 then
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
--:Minify:--
|
--:Minify:--
|
||||||
syscall.open("/dev/tty/TTY1","r") --stdin (Device 0)
|
syscall.open("/dev/tty/tty1","r") --stdin (Device 0)
|
||||||
syscall.open("/dev/tty/TTY1","w") --stdout (Device 1)
|
syscall.open("/dev/tty/tty1","w") --stdout (Device 1)
|
||||||
syscall.open("/dev/null","w") --stderr (device 2)
|
syscall.open("/dev/null","w") --stderr (device 2)
|
||||||
|
|
||||||
local success, errorMsg = xpcall(function()
|
local success, errorMsg = xpcall(function()
|
||||||
@@ -17,7 +17,13 @@ local commandHistory = {}
|
|||||||
local terminate = false
|
local terminate = false
|
||||||
syscall.setEnviron("SHELL","rtbash")
|
syscall.setEnviron("SHELL","rtbash")
|
||||||
syscall.setEnviron("PATH","/bin/")
|
syscall.setEnviron("PATH","/bin/")
|
||||||
syscall.chdir("/")
|
local _home = syscall.getEnviron("HOME")
|
||||||
|
if _home and _home ~= "" then
|
||||||
|
local ok = pcall(syscall.chdir, _home)
|
||||||
|
if not ok then syscall.chdir("/") end
|
||||||
|
else
|
||||||
|
syscall.chdir("/")
|
||||||
|
end
|
||||||
local oldWD = ""
|
local oldWD = ""
|
||||||
|
|
||||||
for i = 1, 16 do
|
for i = 1, 16 do
|
||||||
@@ -951,8 +957,8 @@ local function runCommand(command)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local proc = syscall.spawn(function(...)
|
local proc = syscall.spawn(function(...)
|
||||||
syscall.open("/dev/tty/TTY1","r")
|
syscall.open("/dev/tty/tty1","r")
|
||||||
syscall.open("/dev/tty/TTY1","w")
|
syscall.open("/dev/tty/tty1","w")
|
||||||
syscall.open("/dev/null","w")
|
syscall.open("/dev/null","w")
|
||||||
local ok2, msg = pcall(program, ...)
|
local ok2, msg = pcall(program, ...)
|
||||||
if not ok2 then printError(progName, msg) end
|
if not ok2 then printError(progName, msg) end
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
--:Minify:--
|
--:Minify:--
|
||||||
syscall.open("/dev/tty/TTY1","r")
|
syscall.open("/dev/tty/tty1","r")
|
||||||
syscall.open("/dev/tty/TTY1","w")
|
syscall.open("/dev/tty/tty1","w")
|
||||||
syscall.open("/dev/null","r")
|
syscall.open("/dev/null","r")
|
||||||
syscall.devctl(1,"clear")
|
syscall.devctl(1,"clear")
|
||||||
syscall.devctl(1,"sfgc",1)
|
syscall.devctl(1,"sfgc",1)
|
||||||
@@ -57,8 +57,8 @@ while true do
|
|||||||
printInline("> ")
|
printInline("> ")
|
||||||
end
|
end
|
||||||
proc = syscall.spawn(function(...)
|
proc = syscall.spawn(function(...)
|
||||||
syscall.open("/dev/tty/TTY1","r")
|
syscall.open("/dev/tty/tty1","r")
|
||||||
syscall.open("/dev/tty/TTY1","w")
|
syscall.open("/dev/tty/tty1","w")
|
||||||
syscall.open("/dev/null","w")
|
syscall.open("/dev/null","w")
|
||||||
program(...)
|
program(...)
|
||||||
end, path, nil, {table.unpack(split, 2)})
|
end, path, nil, {table.unpack(split, 2)})
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
--:Minify:--
|
--:Minify:--
|
||||||
syscall.open("/dev/tty/TTY1", "r") --stdin (fd 0)
|
syscall.open("/dev/tty/tty1", "r") --stdin (fd 0)
|
||||||
syscall.open("/dev/tty/TTY1", "w") --stdout (fd 1)
|
syscall.open("/dev/tty/tty1", "w") --stdout (fd 1)
|
||||||
syscall.open("/dev/null", "w") --stderr (fd 2)
|
syscall.open("/dev/null", "w") --stderr (fd 2)
|
||||||
|
|
||||||
|
|
||||||
@@ -96,6 +96,9 @@ local function spawnShell(username, uid, shell, homedir)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local chdirOk, chdirErr = pcall(syscall.chdir, homedir)
|
local chdirOk, chdirErr = pcall(syscall.chdir, homedir)
|
||||||
|
if not chdirOk then
|
||||||
|
pcall(syscall.chdir, "/")
|
||||||
|
end
|
||||||
|
|
||||||
local ok, err = pcall(syscall.execspawn, shell, username .. ":shell")
|
local ok, err = pcall(syscall.execspawn, shell, username .. ":shell")
|
||||||
if not ok then
|
if not ok then
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ for j = i + 1, #cmdArgs do restArgs[#restArgs + 1] = cmdArgs[j] end
|
|||||||
local currentUid = syscall.getuid()
|
local currentUid = syscall.getuid()
|
||||||
local currentUser = syscall.getUsername(currentUid) or tostring(currentUid)
|
local currentUser = syscall.getUsername(currentUid) or tostring(currentUid)
|
||||||
|
|
||||||
local targetUid = syscall.getuid(targetUser)
|
local targetUid = syscall.getuidbyname(targetUser)
|
||||||
if not targetUid then
|
if not targetUid then
|
||||||
print("sudo: user '" .. targetUser .. "' does not exist")
|
print("sudo: user '" .. targetUser .. "' does not exist")
|
||||||
syscall.exit(1)
|
syscall.exit(1)
|
||||||
@@ -39,7 +39,7 @@ if not targetUid then
|
|||||||
end
|
end
|
||||||
|
|
||||||
if currentUid ~= 0 then
|
if currentUid ~= 0 then
|
||||||
printInline("[sudo] password for " .. currentUser .. ": ")
|
printInline("[sudo] password for root: ")
|
||||||
local pw = ""
|
local pw = ""
|
||||||
while true do
|
while true do
|
||||||
local ch = syscall.read(0)
|
local ch = syscall.read(0)
|
||||||
@@ -55,7 +55,7 @@ if currentUid ~= 0 then
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local ok, err = syscall.elevate(currentUser, pw)
|
local ok, err = syscall.elevate("root", pw)
|
||||||
if not ok then
|
if not ok then
|
||||||
sleep(1)
|
sleep(1)
|
||||||
print("sudo: Authentication failure")
|
print("sudo: Authentication failure")
|
||||||
@@ -63,7 +63,7 @@ if currentUid ~= 0 then
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if targetUid ~= 0 then
|
if targetUid ~= currentUid then
|
||||||
syscall.setuid(targetUid)
|
syscall.setuid(targetUid)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -14,6 +14,9 @@ for i,v in pairs(kernel.processes) do
|
|||||||
end, i)
|
end, i)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if not fs.exists("/bin/startup") then
|
||||||
|
fs.mkdir("/bin/startup")
|
||||||
|
end
|
||||||
local files = fs.list("/bin/startup")
|
local files = fs.list("/bin/startup")
|
||||||
if not files then error("Failed to list /bin/startup") end
|
if not files then error("Failed to list /bin/startup") end
|
||||||
for i,v in ipairs(files) do
|
for i,v in ipairs(files) do
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ function peripheral.isPresent(name)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function peripheral.getType(peripheral)
|
function peripheral.getType(peripheral)
|
||||||
if type(peripheral) == "string" then -- Peripheral name passed
|
if type(peripheral) == "string" then
|
||||||
if native.isPresent(peripheral) then
|
if native.isPresent(peripheral) then
|
||||||
return native.getType(peripheral)
|
return native.getType(peripheral)
|
||||||
end
|
end
|
||||||
@@ -58,7 +58,7 @@ function peripheral.getType(peripheral)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function peripheral.hasType(peripheral, peripheral_type)
|
function peripheral.hasType(peripheral, peripheral_type)
|
||||||
if type(peripheral) == "string" then -- Peripheral name passed
|
if type(peripheral) == "string" then
|
||||||
if native.isPresent(peripheral) then
|
if native.isPresent(peripheral) then
|
||||||
return native.hasType(peripheral, peripheral_type)
|
return native.hasType(peripheral, peripheral_type)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -184,10 +184,17 @@ end
|
|||||||
|
|
||||||
kernel.log("Gathering modules")
|
kernel.log("Gathering modules")
|
||||||
for _, i in ipairs(ifs.list("/lib/modules")) do
|
for _, i in ipairs(ifs.list("/lib/modules")) do
|
||||||
for _,v in ipairs(ifs.list("/lib/modules/"..i)) do
|
local modlist = ifs.list("/lib/modules/"..i)
|
||||||
|
if not modlist then
|
||||||
|
kernel.log("WARNING: could not list /lib/modules/"..i.." (skipping)", "WARN", 8)
|
||||||
|
else
|
||||||
|
for _,v in ipairs(modlist) do
|
||||||
local prior=tonumber(v:sub(1,2))
|
local prior=tonumber(v:sub(1,2))
|
||||||
|
if prior then
|
||||||
modules[prior+1][#modules[prior+1]+1]="/lib/modules/"..i.."/"..v
|
modules[prior+1][#modules[prior+1]+1]="/lib/modules/"..i.."/"..v
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
kernel.ifs=ifs
|
kernel.ifs=ifs
|
||||||
|
|||||||
@@ -1,142 +0,0 @@
|
|||||||
-- :Minify:--
|
|
||||||
local kernel = ...
|
|
||||||
|
|
||||||
local P = kernel.vfs.P
|
|
||||||
local PERM = kernel.vfs.PERM
|
|
||||||
|
|
||||||
local RW_R_R = P.OWNER_R + P.OWNER_W + P.GROUP_R + P.WORLD_R
|
|
||||||
local RWX_RX_RX = P.OWNER_R + P.OWNER_W + P.OWNER_X
|
|
||||||
+ P.GROUP_R + P.GROUP_X
|
|
||||||
+ P.WORLD_R + P.WORLD_X
|
|
||||||
local RW_R__ = P.OWNER_R + P.OWNER_W + P.GROUP_R
|
|
||||||
local RW____ = P.OWNER_R + P.OWNER_W
|
|
||||||
local RWXRWXRWX = PERM.RWXRWXRWX
|
|
||||||
local SUID_755 = PERM.SUID_755
|
|
||||||
|
|
||||||
local META_VERSION = 0x01
|
|
||||||
local rootDisk = kernel.disks["$"]
|
|
||||||
|
|
||||||
local function makeEntry(name, etype, owner, group, perms, cmeta)
|
|
||||||
cmeta = cmeta or ""
|
|
||||||
local plo = perms % 256
|
|
||||||
local phi = math.floor(perms / 256) % 256
|
|
||||||
return string.char(#name) .. name
|
|
||||||
.. string.char(etype, owner, group, plo, phi)
|
|
||||||
.. string.char(#cmeta) .. cmeta
|
|
||||||
end
|
|
||||||
|
|
||||||
local function writeMeta(dir, entries)
|
|
||||||
local diskDir = dir
|
|
||||||
if diskDir:sub(1,1) == "/" then diskDir = diskDir:sub(2) end
|
|
||||||
local metaPath = (diskDir == "" and ".meta" or diskDir .. "/.meta")
|
|
||||||
|
|
||||||
local data = string.char(META_VERSION)
|
|
||||||
for _, e in ipairs(entries) do
|
|
||||||
data = data .. makeEntry(e[1], e[2] or 0x00, e[3], e[4], e[5], e[6])
|
|
||||||
end
|
|
||||||
|
|
||||||
local ok, err = pcall(function()
|
|
||||||
local f = rootDisk:open(metaPath, "w")
|
|
||||||
f.write(data)
|
|
||||||
f.close()
|
|
||||||
end)
|
|
||||||
if not ok then
|
|
||||||
kernel.log("permissions: failed to write " .. metaPath .. ": " .. tostring(err), "WARN", 8)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local REG = 0x00
|
|
||||||
|
|
||||||
if rootDisk:fileExists(".meta") then
|
|
||||||
kernel.log("Permissions already seeded, skipping.", "INFO")
|
|
||||||
else
|
|
||||||
kernel.log("Seeding filesystem permissions...", "INFO")
|
|
||||||
|
|
||||||
-- /
|
|
||||||
writeMeta("/", {
|
|
||||||
{"bin", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"boot", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"dev", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"etc", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"home", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"lib", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"root", REG, 0, 0, RW____ },
|
|
||||||
{"sbin", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"tmp", REG, 0, 0, RWXRWXRWX},
|
|
||||||
{"usr", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"var", REG, 0, 0, RWX_RX_RX},
|
|
||||||
})
|
|
||||||
|
|
||||||
-- /bin
|
|
||||||
writeMeta("/bin", {
|
|
||||||
{"cat", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"clear", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"echo", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"hfetch", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"hysh", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"hyshex", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"install", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"login", REG, 0, 0, SUID_755 },
|
|
||||||
{"ls", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"lua", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"luaold", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"mkdir", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"ps", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"pwd", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"spm", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"su", REG, 0, 0, SUID_755 },
|
|
||||||
{"sudo", REG, 0, 0, SUID_755 },
|
|
||||||
{"sysdump", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"whoami", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"yes", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"startup", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"ln", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"readlink", REG, 0, 0, RWX_RX_RX},
|
|
||||||
})
|
|
||||||
|
|
||||||
writeMeta("/bin/startup", {
|
|
||||||
{"test.lua", REG, 0, 0, RWX_RX_RX},
|
|
||||||
})
|
|
||||||
|
|
||||||
-- /etc
|
|
||||||
writeMeta("/etc", {
|
|
||||||
{"passwd", REG, 0, 0, RW_R_R},
|
|
||||||
{"shadow", REG, 0, 0, RW____},
|
|
||||||
{"pam.d", REG, 0, 0, RWX_RX_RX},
|
|
||||||
})
|
|
||||||
|
|
||||||
writeMeta("/etc/pam.d", {
|
|
||||||
{"secret", REG, 0, 0, RW____},
|
|
||||||
})
|
|
||||||
|
|
||||||
-- /sbin
|
|
||||||
writeMeta("/sbin", {
|
|
||||||
{"init.lua", REG, 0, 0, RWX_RX_RX},
|
|
||||||
})
|
|
||||||
|
|
||||||
-- /boot
|
|
||||||
writeMeta("/boot", {
|
|
||||||
{"kernel.lua", REG, 0, 0, RW_R_R },
|
|
||||||
{"boot.cfg", REG, 0, 0, RW_R_R },
|
|
||||||
{"safeboot.cfg", REG, 0, 0, RW_R_R },
|
|
||||||
{"fstab", REG, 0, 0, RW_R_R },
|
|
||||||
{"initfs", REG, 0, 0, RW_R_R },
|
|
||||||
{"cct", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"oc", REG, 0, 0, RWX_RX_RX},
|
|
||||||
})
|
|
||||||
|
|
||||||
-- /lib
|
|
||||||
writeMeta("/lib", {
|
|
||||||
{"sys", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"modules", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"crypto", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"store", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"snip", REG, 0, 0, RW_R_R },
|
|
||||||
{"io", REG, 0, 0, RW_R_R },
|
|
||||||
{"bit32", REG, 0, 0, RW_R_R },
|
|
||||||
})
|
|
||||||
|
|
||||||
kernel.log("Filesystem permissions seeded.", "INFO")
|
|
||||||
end
|
|
||||||
|
|
||||||
kernel.log("Permission module loaded.", "INFO")
|
|
||||||
+3
-6
@@ -1,4 +1,7 @@
|
|||||||
-- :Minify:--
|
-- :Minify:--
|
||||||
|
local kernel = ...
|
||||||
|
kernel.allowGlobalOverwrites = true
|
||||||
|
|
||||||
function string.hasSuffix(str, suffix)
|
function string.hasSuffix(str, suffix)
|
||||||
return string.sub(str, #suffix + 1) == suffix
|
return string.sub(str, #suffix + 1) == suffix
|
||||||
end
|
end
|
||||||
@@ -68,30 +71,24 @@ end
|
|||||||
local function serialize(tbl, seen)
|
local function serialize(tbl, seen)
|
||||||
seen = seen or {}
|
seen = seen or {}
|
||||||
|
|
||||||
-- If we've seen this table before, return a placeholder to prevent infinite loops
|
|
||||||
if seen[tbl] then return '"[Circular Reference]"' end
|
if seen[tbl] then return '"[Circular Reference]"' end
|
||||||
|
|
||||||
-- Mark this table as seen
|
|
||||||
seen[tbl] = true
|
seen[tbl] = true
|
||||||
|
|
||||||
local output = "{"
|
local output = "{"
|
||||||
local first = true
|
local first = true
|
||||||
|
|
||||||
for i, v in pairs(tbl) do
|
for i, v in pairs(tbl) do
|
||||||
-- Handle comma placement more cleanly
|
|
||||||
if not first then output = output .. "," end
|
if not first then output = output .. "," end
|
||||||
first = false
|
first = false
|
||||||
|
|
||||||
-- Serialize Key
|
|
||||||
if type(i) == "string" then
|
if type(i) == "string" then
|
||||||
output = output .. "[\"" .. i .. "\"]="
|
output = output .. "[\"" .. i .. "\"]="
|
||||||
elseif type(i) == "number" then
|
elseif type(i) == "number" then
|
||||||
output = output .. "[" .. tostring(i) .. "]="
|
output = output .. "[" .. tostring(i) .. "]="
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Serialize Value
|
|
||||||
if type(v) == "table" then
|
if type(v) == "table" then
|
||||||
-- Pass the 'seen' table down to the recursive call
|
|
||||||
output = output .. serialize(v, seen)
|
output = output .. serialize(v, seen)
|
||||||
elseif type(v) == "string" then
|
elseif type(v) == "string" then
|
||||||
output = output .. "[=[" .. v .. "]=]"
|
output = output .. "[=[" .. v .. "]=]"
|
||||||
+113
-21
@@ -5,14 +5,14 @@ kernel.vfs = vfs
|
|||||||
vfs.mounts = {["$"] = "/"}
|
vfs.mounts = {["$"] = "/"}
|
||||||
vfs.disks = kernel.disks
|
vfs.disks = kernel.disks
|
||||||
|
|
||||||
-- Metafile format (version 1)
|
-- Metafile format (version 2)
|
||||||
-- File header: 1 byte = version (0x01)
|
-- File header: 1 byte = version (0x02)
|
||||||
-- Per-entry:
|
-- Per-entry:
|
||||||
-- 1 byte = name length
|
-- 1 byte = name length
|
||||||
-- N bytes = name
|
-- N bytes = name
|
||||||
-- 1 byte = entry type (0x00 = regular, 0x01 = symlink)
|
-- 1 byte = entry type (0x00 = regular, 0x01 = symlink)
|
||||||
-- 1 byte = owner uid
|
-- 2 bytes = owner uid (little-endian uint16)
|
||||||
-- 1 byte = group gid
|
-- 2 bytes = group gid (little-endian uint16)
|
||||||
-- 2 bytes = perms (little-endian uint16)
|
-- 2 bytes = perms (little-endian uint16)
|
||||||
-- bit 0 = world-write bit 1 = world-read
|
-- bit 0 = world-write bit 1 = world-read
|
||||||
-- bit 2 = group-write bit 3 = group-read
|
-- bit 2 = group-write bit 3 = group-read
|
||||||
@@ -24,12 +24,16 @@ vfs.disks = kernel.disks
|
|||||||
-- 1 byte = cmeta length
|
-- 1 byte = cmeta length
|
||||||
-- N bytes = cmeta (for symlinks: the link target path)
|
-- N bytes = cmeta (for symlinks: the link target path)
|
||||||
--
|
--
|
||||||
|
-- Version 1:
|
||||||
|
-- 1 byte name len, N bytes name, 1 byte etype, 1 byte owner,
|
||||||
|
-- 1 byte group, 2 bytes perms (little-endian), 1 byte cmeta len, N bytes cmeta
|
||||||
|
--
|
||||||
-- Version 0:
|
-- Version 0:
|
||||||
-- No file header. Per-entry:
|
-- No file header. Per-entry:
|
||||||
-- 1 byte name len, N bytes name, 1 byte owner, 1 byte group,
|
-- 1 byte name len, N bytes name, 1 byte owner, 1 byte group,
|
||||||
-- 1 byte perms (low 7 bits only), 1 byte cmeta len, N bytes cmeta
|
-- 1 byte perms (low 7 bits only), 1 byte cmeta len, N bytes cmeta
|
||||||
|
|
||||||
local META_VERSION = 0x01
|
local META_VERSION = 0x02
|
||||||
|
|
||||||
local function bit_is_set(num, bit)
|
local function bit_is_set(num, bit)
|
||||||
return math.floor(num / (2 ^ bit)) % 2 == 1
|
return math.floor(num / (2 ^ bit)) % 2 == 1
|
||||||
@@ -41,8 +45,9 @@ local function parseMetafile(raw)
|
|||||||
local p = 1
|
local p = 1
|
||||||
|
|
||||||
local version = 0
|
local version = 0
|
||||||
if raw:byte(1) == META_VERSION then
|
local firstByte = raw:byte(1)
|
||||||
version = META_VERSION
|
if firstByte == 0x02 or firstByte == 0x01 then
|
||||||
|
version = firstByte
|
||||||
p = 2
|
p = 2
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -54,7 +59,13 @@ local function parseMetafile(raw)
|
|||||||
|
|
||||||
local etype, owner, group, perms, cmeta
|
local etype, owner, group, perms, cmeta
|
||||||
|
|
||||||
if version == META_VERSION then
|
if version == 0x02 then
|
||||||
|
if p + 6 > #raw then break end
|
||||||
|
etype = raw:byte(p); p = p + 1
|
||||||
|
owner = raw:byte(p) + raw:byte(p+1) * 256; p = p + 2
|
||||||
|
group = raw:byte(p) + raw:byte(p+1) * 256; p = p + 2
|
||||||
|
perms = raw:byte(p) + raw:byte(p+1) * 256; p = p + 2
|
||||||
|
elseif version == 0x01 then
|
||||||
if p + 4 > #raw then break end
|
if p + 4 > #raw then break end
|
||||||
etype = raw:byte(p); p = p + 1
|
etype = raw:byte(p); p = p + 1
|
||||||
owner = raw:byte(p); p = p + 1
|
owner = raw:byte(p); p = p + 1
|
||||||
@@ -87,34 +98,71 @@ local function makeMetafile(meta)
|
|||||||
for name, m in pairs(meta) do
|
for name, m in pairs(meta) do
|
||||||
local plo = m.perms % 256
|
local plo = m.perms % 256
|
||||||
local phi = math.floor(m.perms / 256) % 256
|
local phi = math.floor(m.perms / 256) % 256
|
||||||
|
local olo = (m.owner or 0) % 256
|
||||||
|
local ohi = math.floor((m.owner or 0) / 256) % 256
|
||||||
|
local glo = (m.group or 0) % 256
|
||||||
|
local ghi = math.floor((m.group or 0) / 256) % 256
|
||||||
out = out
|
out = out
|
||||||
.. string.char(#name) .. name
|
.. string.char(#name) .. name
|
||||||
.. string.char(m.etype or 0x00)
|
.. string.char(m.etype or 0x00)
|
||||||
.. string.char(m.owner, m.group, plo, phi)
|
.. string.char(olo, ohi, glo, ghi, plo, phi)
|
||||||
.. string.char(#m.cmeta) .. m.cmeta
|
.. string.char(#m.cmeta) .. m.cmeta
|
||||||
end
|
end
|
||||||
return out
|
return out
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local SAFE_COMPONENT_PATTERN = "^[A-Za-z0-9_.+%-%@%(%)%[%]]+$"
|
||||||
|
|
||||||
local function normalizePath(path)
|
local function normalizePath(path)
|
||||||
local task = kernel.currentTask
|
local task = kernel.currentTask
|
||||||
local cwd = task.cwd or "/"
|
local cwd = task.cwd or "/"
|
||||||
if path:sub(1,1) ~= "/" then path = cwd .. "/" .. path end
|
|
||||||
local parts = {}
|
if path:sub(1, 1) ~= "/" then
|
||||||
for part in path:gmatch("[^/]+") do
|
path = cwd .. "/" .. path
|
||||||
if part == ".." then
|
end
|
||||||
if #parts > 0 then table.remove(parts) end
|
|
||||||
elseif part ~= "." and part ~= "" then
|
local stack = {}
|
||||||
table.insert(parts, part)
|
local i = 1
|
||||||
|
local len = #path
|
||||||
|
while i <= len do
|
||||||
|
local j = path:find("/", i, true)
|
||||||
|
local comp
|
||||||
|
if j then
|
||||||
|
comp = path:sub(i, j - 1)
|
||||||
|
i = j + 1
|
||||||
|
else
|
||||||
|
comp = path:sub(i)
|
||||||
|
i = len + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
comp = comp:match("^%s*(.-)%s*$")
|
||||||
|
|
||||||
|
if comp == "" or comp == "." then
|
||||||
|
elseif comp == ".." then
|
||||||
|
if #stack > 0 then
|
||||||
|
table.remove(stack)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
comp = comp:lower()
|
||||||
|
if not comp:match(SAFE_COMPONENT_PATTERN) then
|
||||||
|
error("EINVAL: illegal characters in path component: " .. comp, 2)
|
||||||
|
end
|
||||||
|
if comp == ".meta" then
|
||||||
|
error("EINVAL: reserved path component: " .. comp, 2)
|
||||||
|
end
|
||||||
|
table.insert(stack, comp)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local result = "/" .. table.concat(parts, "/")
|
|
||||||
|
local result = "/" .. table.concat(stack, "/")
|
||||||
|
|
||||||
local root = task and task.root
|
local root = task and task.root
|
||||||
if root and root ~= "/" then
|
if root and root ~= "/" then
|
||||||
if result ~= root and result:sub(1, #root + 1) ~= root .. "/" then
|
if result ~= root and result:sub(1, #root + 1) ~= root .. "/" then
|
||||||
result = root
|
result = root
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -146,8 +194,10 @@ local function resolveMount(normalPath)
|
|||||||
return vfs.disks[mountId], diskPath
|
return vfs.disks[mountId], diskPath
|
||||||
end
|
end
|
||||||
|
|
||||||
|
vfs._parseMetafile = parseMetafile
|
||||||
|
|
||||||
local function readMetaEntry(disk, parentDiskPath, filename)
|
local function readMetaEntry(disk, parentDiskPath, filename)
|
||||||
if filename == ".meta" then error("Cannot open metafile") end
|
if filename == ".meta" then error("EACCES: Cannot open metafile") end
|
||||||
local mp
|
local mp
|
||||||
if parentDiskPath == "/" then
|
if parentDiskPath == "/" then
|
||||||
mp = ".meta"
|
mp = ".meta"
|
||||||
@@ -159,6 +209,14 @@ local function readMetaEntry(disk, parentDiskPath, filename)
|
|||||||
if not ok or not f then return nil end
|
if not ok or not f then return nil end
|
||||||
local raw = f.read(65535)
|
local raw = f.read(65535)
|
||||||
if f.close then f.close() end
|
if f.close then f.close() end
|
||||||
|
|
||||||
|
if raw and #raw > 0 and raw:byte(1) ~= META_VERSION then
|
||||||
|
local upgraded = makeMetafile(parseMetafile(raw))
|
||||||
|
local wok, wf = pcall(function() return disk:open(mp, "w") end)
|
||||||
|
if wok and wf then wf.write(upgraded); if wf.close then wf.close() end end
|
||||||
|
raw = upgraded
|
||||||
|
end
|
||||||
|
|
||||||
local parsed = parseMetafile(raw)
|
local parsed = parseMetafile(raw)
|
||||||
return parsed[filename]
|
return parsed[filename]
|
||||||
end
|
end
|
||||||
@@ -400,6 +458,8 @@ function vfs.open(path, mode)
|
|||||||
if not disk then error("NODISK") end
|
if not disk then error("NODISK") end
|
||||||
|
|
||||||
local meta = getFileMeta(path)
|
local meta = getFileMeta(path)
|
||||||
|
local isNew = (mode == "w" or mode == "a") and not disk:fileExists(diskPath)
|
||||||
|
|
||||||
checkperms(meta, mode == "r" and "r" or "w")
|
checkperms(meta, mode == "r" and "r" or "w")
|
||||||
|
|
||||||
local handle
|
local handle
|
||||||
@@ -408,6 +468,21 @@ function vfs.open(path, mode)
|
|||||||
if type(handle) ~= "table" then error("ENFILE") end
|
if type(handle) ~= "table" then error("ENFILE") end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if isNew then
|
||||||
|
local euid = (task and (task.euid or task.uid)) or kernel.uid
|
||||||
|
local egid = (task and task.gid) or 0
|
||||||
|
local norm = normalizePath(path)
|
||||||
|
local parent = norm:match("^(.*)/[^/]+$") or "/"
|
||||||
|
if parent == "" then parent = "/" end
|
||||||
|
local name = norm:match("[^/]+$")
|
||||||
|
if name then
|
||||||
|
local entry = { etype=0x00, owner=euid, group=egid,
|
||||||
|
perms=vfs.PERM.RW_R_R, cmeta="" }
|
||||||
|
pcall(writeMetaEntry, parent, name, entry, false)
|
||||||
|
meta = entry
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local fobj = newFileObj(handle, mode, path, meta, disk:type(diskPath))
|
local fobj = newFileObj(handle, mode, path, meta, disk:type(diskPath))
|
||||||
if mode == "r" and bit_is_set(meta.perms, 6) then
|
if mode == "r" and bit_is_set(meta.perms, 6) then
|
||||||
fobj.suid_owner = meta.owner
|
fobj.suid_owner = meta.owner
|
||||||
@@ -574,15 +649,32 @@ function vfs.listdir(path)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function vfs.mkdir(path)
|
function vfs.mkdir(path)
|
||||||
|
local norm = normalizePath(path)
|
||||||
|
local parent = norm:match("^(.*)/[^/]+$") or "/"
|
||||||
|
if parent == "" then parent = "/" end
|
||||||
|
local parentMeta = getFileMeta(parent)
|
||||||
|
checkperms(parentMeta, "w")
|
||||||
local disk, diskPath = resolvePath(path)
|
local disk, diskPath = resolvePath(path)
|
||||||
local meta = getFileMeta(path)
|
|
||||||
checkperms(meta, "w")
|
|
||||||
disk:makeDirectory(diskPath)
|
disk:makeDirectory(diskPath)
|
||||||
|
local task = kernel.currentTask
|
||||||
|
local euid = (task and (task.euid or task.uid)) or kernel.uid
|
||||||
|
local egid = (task and task.gid) or 0
|
||||||
|
local name = norm:match("[^/]+$")
|
||||||
|
if name then
|
||||||
|
local entry = { etype=0x00, owner=euid, group=egid,
|
||||||
|
perms=vfs.PERM.RWX_RX, cmeta="" }
|
||||||
|
pcall(writeMetaEntry, parent, name, entry, false)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function vfs.remove(path)
|
function vfs.remove(path)
|
||||||
|
local norm = resolveSymlinks(path, true)
|
||||||
|
local parent = norm:match("^(.*)/[^/]+$") or "/"
|
||||||
|
if parent == "" then parent = "/" end
|
||||||
|
local parentMeta = getFileMeta(parent)
|
||||||
|
checkperms(parentMeta, "w")
|
||||||
|
|
||||||
local meta = getFileMeta(path, true)
|
local meta = getFileMeta(path, true)
|
||||||
checkperms(meta, "w")
|
|
||||||
|
|
||||||
if kernel.unixSockets and kernel.unixSockets[path] then
|
if kernel.unixSockets and kernel.unixSockets[path] then
|
||||||
kernel.unixSockets[path] = nil
|
kernel.unixSockets[path] = nil
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+2
-2
@@ -385,11 +385,11 @@ kernel.processes.cctmond = function()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
newtty(apis.term, "TTY1", fifo.pop)
|
newtty(apis.term, "tty1", fifo.pop)
|
||||||
|
|
||||||
|
|
||||||
for i,v in ipairs({peripheral.find("monitor")}) do
|
for i,v in ipairs({peripheral.find("monitor")}) do
|
||||||
v.setTextScale(.5)
|
v.setTextScale(.5)
|
||||||
v.write("Initializing...")
|
v.write("Initializing...")
|
||||||
newtty(v,"TTY"..tostring(i+1),function () end)
|
newtty(v,"tty"..tostring(i+1),function () end)
|
||||||
end
|
end
|
||||||
+5
-4
@@ -3,6 +3,7 @@ local args = {...}
|
|||||||
local kernel = args[1]
|
local kernel = args[1]
|
||||||
kernel._G = _G
|
kernel._G = _G
|
||||||
|
|
||||||
|
|
||||||
local function readonly(tbl)
|
local function readonly(tbl)
|
||||||
return setmetatable({}, {
|
return setmetatable({}, {
|
||||||
__index = function(_, key)
|
__index = function(_, key)
|
||||||
@@ -20,7 +21,7 @@ local function readonly(tbl)
|
|||||||
error("Attempt to modify global variable '" .. k .. "'", 2)
|
error("Attempt to modify global variable '" .. k .. "'", 2)
|
||||||
end,
|
end,
|
||||||
|
|
||||||
__pairs = function()
|
__pairs = function(self)
|
||||||
local function iter(_, key)
|
local function iter(_, key)
|
||||||
local nextKey, value = next(tbl, key)
|
local nextKey, value = next(tbl, key)
|
||||||
if type(value) == "table" then
|
if type(value) == "table" then
|
||||||
@@ -28,7 +29,7 @@ local function readonly(tbl)
|
|||||||
end
|
end
|
||||||
return nextKey, value
|
return nextKey, value
|
||||||
end
|
end
|
||||||
return iter, tbl, nil
|
return iter, self, nil
|
||||||
end,
|
end,
|
||||||
|
|
||||||
__ipairs = function()
|
__ipairs = function()
|
||||||
@@ -49,8 +50,8 @@ local function readonly(tbl)
|
|||||||
__metatable = false
|
__metatable = false
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
local origLoad = load
|
||||||
|
|
||||||
kernel._U = readonly(kernel._G)
|
kernel._U = readonly(kernel._G)
|
||||||
kernel.allowGlobalOverwrites = true
|
|
||||||
kernel._U._G = kernel._U
|
kernel._U._G = kernel._U
|
||||||
kernel.allowGlobalOverwrites = false
|
kernel._U.load = function(a,b,c,d) return origLoad(a,b,c,d or kernel._U) end
|
||||||
+8
-6
@@ -394,6 +394,8 @@ function auth.newUser(username, password, gid, homedir, shell)
|
|||||||
|
|
||||||
if kernel.vfs.mkdir and not kernel.vfs.exists(homedir) then
|
if kernel.vfs.mkdir and not kernel.vfs.exists(homedir) then
|
||||||
kernel.vfs.mkdir(homedir)
|
kernel.vfs.mkdir(homedir)
|
||||||
|
-- Homedir must be owned by the new user, not root
|
||||||
|
pcall(kernel.vfs.chown, homedir, uid, uid)
|
||||||
end
|
end
|
||||||
|
|
||||||
kernel.log("AUTH: new user '" .. username .. "' uid=" .. tostring(uid))
|
kernel.log("AUTH: new user '" .. username .. "' uid=" .. tostring(uid))
|
||||||
@@ -591,13 +593,13 @@ function auth.elevate(targetUsername, password)
|
|||||||
|
|
||||||
local task = kernel.currentTask
|
local task = kernel.currentTask
|
||||||
local prevUid = task.uid
|
local prevUid = task.uid
|
||||||
task.uid = uid
|
task.uid = 0
|
||||||
task.euid = uid
|
task.euid = 0
|
||||||
task.gid = tonumber(entry[2]) or uid
|
task.gid = 0
|
||||||
task.egid = tonumber(entry[2]) or uid
|
task.egid = 0
|
||||||
kernel.uid = uid
|
kernel.uid = 0
|
||||||
|
|
||||||
kernel.log("AUTH: elevate uid=" .. tostring(prevUid) .. " -> " .. tostring(uid) .. " (" .. targetUsername .. ")")
|
kernel.log("AUTH: elevate uid=" .. tostring(prevUid) .. " -> 0 (via " .. targetUsername .. ")")
|
||||||
return true, uid
|
return true, uid
|
||||||
end
|
end
|
||||||
|
|
||||||
+10
-4
@@ -5,6 +5,8 @@ local sys = {}
|
|||||||
local nextpid = 2
|
local nextpid = 2
|
||||||
kernel.exitMain = false
|
kernel.exitMain = false
|
||||||
|
|
||||||
|
local resumeWithTimeout = coroutine.resumeWithTimeout
|
||||||
|
|
||||||
local function bit_is_set(num, bit)
|
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
|
||||||
@@ -206,10 +208,14 @@ function sys.kill(pid)
|
|||||||
return false, "Task does not exist"
|
return false, "Task does not exist"
|
||||||
elseif task.status == "Z" then
|
elseif task.status == "Z" then
|
||||||
return false, "Task is already dead"
|
return false, "Task is already dead"
|
||||||
else
|
end
|
||||||
|
local caller = kernel.currentTask
|
||||||
|
local ceuid = caller and (caller.euid or caller.uid) or kernel.uid
|
||||||
|
if ceuid ~= 0 and task.uid ~= (caller and caller.uid or kernel.uid) then
|
||||||
|
return false, "EPERM"
|
||||||
|
end
|
||||||
task.status = "Z"
|
task.status = "Z"
|
||||||
return true
|
return true
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function sys.stop(pid)
|
function sys.stop(pid)
|
||||||
@@ -352,7 +358,7 @@ 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
|
if kernel.config.preempt then
|
||||||
coroutine.resumeWithTimeout(coro, task.timeSlice, table.remove(task.sigq, 1))
|
resumeWithTimeout(coro, task.timeSlice, table.remove(task.sigq, 1))
|
||||||
else
|
else
|
||||||
coroutine.resume(coro, table.remove(task.sigq, 1))
|
coroutine.resume(coro, table.remove(task.sigq, 1))
|
||||||
end
|
end
|
||||||
@@ -363,7 +369,7 @@ function kernel.main()
|
|||||||
local ret
|
local ret
|
||||||
|
|
||||||
if kernel.config.preempt then
|
if kernel.config.preempt then
|
||||||
ret = { coroutine.resumeWithTimeout(task.coro, task.timeSlice, table.unpack(task.syscallReturn)) }
|
ret = { resumeWithTimeout(task.coro, task.timeSlice, table.unpack(task.syscallReturn)) }
|
||||||
else
|
else
|
||||||
ret = { coroutine.resume(task.coro, table.unpack(task.syscallReturn)) }
|
ret = { coroutine.resume(task.coro, table.unpack(task.syscallReturn)) }
|
||||||
end
|
end
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,233 @@
|
|||||||
|
-- :Minify:--
|
||||||
|
local kernel = ...
|
||||||
|
|
||||||
|
local P = kernel.vfs.P
|
||||||
|
local PERM = kernel.vfs.PERM
|
||||||
|
|
||||||
|
local RW_R_R = P.OWNER_R + P.OWNER_W + P.GROUP_R + P.WORLD_R
|
||||||
|
local RWX_RX_RX = P.OWNER_R + P.OWNER_W + P.OWNER_X
|
||||||
|
+ P.GROUP_R + P.GROUP_X
|
||||||
|
+ P.WORLD_R + P.WORLD_X
|
||||||
|
local RW_R__ = P.OWNER_R + P.OWNER_W + P.GROUP_R
|
||||||
|
local RW____ = P.OWNER_R + P.OWNER_W
|
||||||
|
local RWXRWXRWX = PERM.RWXRWXRWX
|
||||||
|
local SUID_755 = PERM.SUID_755
|
||||||
|
|
||||||
|
local META_VERSION = 0x02
|
||||||
|
local rootDisk = kernel.disks["$"]
|
||||||
|
|
||||||
|
local function makeEntry(name, etype, owner, group, perms, cmeta)
|
||||||
|
cmeta = cmeta or ""
|
||||||
|
local plo = perms % 256
|
||||||
|
local phi = math.floor(perms / 256) % 256
|
||||||
|
local olo = (owner or 0) % 256
|
||||||
|
local ohi = math.floor((owner or 0) / 256) % 256
|
||||||
|
local glo = (group or 0) % 256
|
||||||
|
local ghi = math.floor((group or 0) / 256) % 256
|
||||||
|
return string.char(#name) .. name
|
||||||
|
.. string.char(etype, olo, ohi, glo, ghi, plo, phi)
|
||||||
|
.. string.char(#cmeta) .. cmeta
|
||||||
|
end
|
||||||
|
|
||||||
|
local REG = 0x00
|
||||||
|
|
||||||
|
local function mergeMeta(dir, entries)
|
||||||
|
local diskDir = dir
|
||||||
|
if diskDir:sub(1,1) == "/" then diskDir = diskDir:sub(2) end
|
||||||
|
local metaPath = (diskDir == "" and ".meta" or diskDir .. "/.meta")
|
||||||
|
|
||||||
|
local existing = {}
|
||||||
|
local rok, rf = pcall(function() return rootDisk:open(metaPath, "r") end)
|
||||||
|
if rok and rf then
|
||||||
|
local raw = rf.read(65535)
|
||||||
|
if rf.close then rf.close() end
|
||||||
|
existing = (kernel.vfs._parseMetafile and kernel.vfs._parseMetafile(raw)) or {}
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, e in ipairs(entries) do
|
||||||
|
local name = e[1]
|
||||||
|
local etype = e[2] or REG
|
||||||
|
local owner = e[3] or 0
|
||||||
|
local group = e[4] or 0
|
||||||
|
local perms = e[5] or RWX_RX_RX
|
||||||
|
local cmeta = e[6] or ""
|
||||||
|
existing[name] = {
|
||||||
|
etype = etype,
|
||||||
|
owner = owner,
|
||||||
|
group = group,
|
||||||
|
perms = perms,
|
||||||
|
cmeta = cmeta,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
local data = string.char(META_VERSION)
|
||||||
|
for name, m in pairs(existing) do
|
||||||
|
data = data .. makeEntry(
|
||||||
|
name,
|
||||||
|
m.etype or REG,
|
||||||
|
m.owner or 0,
|
||||||
|
m.group or 0,
|
||||||
|
m.perms or RWX_RX_RX,
|
||||||
|
m.cmeta or ""
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
local ok, err = pcall(function()
|
||||||
|
local f = rootDisk:open(metaPath, "w")
|
||||||
|
f.write(data)
|
||||||
|
f.close()
|
||||||
|
end)
|
||||||
|
if not ok then
|
||||||
|
kernel.log("permissions: failed to write " .. metaPath .. ": " .. tostring(err), "WARN", 8)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
kernel.log("Seeding filesystem permissions...", "INFO")
|
||||||
|
|
||||||
|
mergeMeta("/", {
|
||||||
|
{"bin", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"boot", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"dev", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"etc", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"home", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"lib", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"root", REG, 0, 0, RW____ },
|
||||||
|
{"sbin", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"tmp", REG, 0, 0, RWXRWXRWX},
|
||||||
|
{"usr", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"var", REG, 0, 0, RWX_RX_RX},
|
||||||
|
})
|
||||||
|
|
||||||
|
mergeMeta("/boot", {
|
||||||
|
{"kernel.lua", REG, 0, 0, RW_R_R },
|
||||||
|
{"boot.cfg", REG, 0, 0, RW_R_R },
|
||||||
|
{"safeboot.cfg", REG, 0, 0, RW_R_R },
|
||||||
|
{"fstab", REG, 0, 0, RW_R_R },
|
||||||
|
{"initfs", REG, 0, 0, RW_R_R },
|
||||||
|
{"cct", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"oc", REG, 0, 0, RWX_RX_RX},
|
||||||
|
})
|
||||||
|
|
||||||
|
mergeMeta("/boot/cct", {
|
||||||
|
{"boot.lua", REG, 0, 0, RW_R_R},
|
||||||
|
{"initdisks", REG, 0, 0, RW_R_R},
|
||||||
|
{"eeprom", REG, 0, 0, RW_R_R},
|
||||||
|
})
|
||||||
|
|
||||||
|
mergeMeta("/boot/oc", {
|
||||||
|
{"boot.lua", REG, 0, 0, RW_R_R},
|
||||||
|
{"initfs.lua",REG, 0, 0, RW_R_R},
|
||||||
|
{"eeprom", REG, 0, 0, RW_R_R},
|
||||||
|
})
|
||||||
|
|
||||||
|
mergeMeta("/sbin", {
|
||||||
|
{"init.lua", REG, 0, 0, RWX_RX_RX},
|
||||||
|
})
|
||||||
|
|
||||||
|
mergeMeta("/bin", {
|
||||||
|
{"cat", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"chattr", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"chgrp", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"chmod", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"chown", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"chroot", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"clear", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"echo", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"hfetch", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"help", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"hysh", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"hyshex", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"id", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"install", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"ln", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"login", REG, 0, 0, SUID_755 },
|
||||||
|
{"loimgcreate", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"looptest", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"losetup", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"ls", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"lsusers", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"lua", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"luaold", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"micro", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"mkdir", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"mount", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"passwd", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"ps", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"pwd", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"readlink", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"sed", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"socktest", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"spm", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"startup", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"su", REG, 0, 0, SUID_755 },
|
||||||
|
{"sudo", REG, 0, 0, SUID_755 },
|
||||||
|
{"sysdump", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"umount", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"useradd", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"userdel", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"usermod", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"whoami", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"yes", REG, 0, 0, RWX_RX_RX},
|
||||||
|
})
|
||||||
|
|
||||||
|
mergeMeta("/bin/startup", {
|
||||||
|
{"test.lua", REG, 0, 0, RWX_RX_RX},
|
||||||
|
})
|
||||||
|
|
||||||
|
mergeMeta("/lib", {
|
||||||
|
{"sys", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"modules", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"crypto", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"store", REG, 0, 0, RWX_RX_RX},
|
||||||
|
{"snip", REG, 0, 0, RW_R_R },
|
||||||
|
{"io", REG, 0, 0, RW_R_R },
|
||||||
|
{"bit32", REG, 0, 0, RW_R_R },
|
||||||
|
})
|
||||||
|
|
||||||
|
mergeMeta("/lib/sys", {
|
||||||
|
{"fs", REG, 0, 0, RW_R_R},
|
||||||
|
{"hpv", REG, 0, 0, RW_R_R},
|
||||||
|
{"ipc", REG, 0, 0, RW_R_R},
|
||||||
|
{"term", REG, 0, 0, RW_R_R},
|
||||||
|
{"init", REG, 0, 0, RW_R_R},
|
||||||
|
})
|
||||||
|
|
||||||
|
mergeMeta("/lib/modules", {
|
||||||
|
{"hyperion", REG, 0, 0, RWX_RX_RX},
|
||||||
|
})
|
||||||
|
|
||||||
|
mergeMeta("/lib/modules/hyperion", {
|
||||||
|
{"01_stdlib.kmod", REG, 0, 0, RW_R_R},
|
||||||
|
{"10_vfs.kmod", REG, 0, 0, RW_R_R},
|
||||||
|
{"11_require.kmod", REG, 0, 0, RW_R_R},
|
||||||
|
{"12_devfs.kmod", REG, 0, 0, RW_R_R},
|
||||||
|
{"12_tmpfs.kmod", REG, 0, 0, RW_R_R},
|
||||||
|
{"13_loopdev.kmod", REG, 0, 0, RW_R_R},
|
||||||
|
{"14_keventd.kmod", REG, 0, 0, RW_R_R},
|
||||||
|
{"19_fstab.kmod", REG, 0, 0, RW_R_R},
|
||||||
|
{"20_signals.kmod", REG, 0, 0, RW_R_R},
|
||||||
|
{"20_socket.kmod", REG, 0, 0, RW_R_R},
|
||||||
|
{"26_tty.kmod", REG, 0, 0, RW_R_R},
|
||||||
|
{"30_userspace.kmod", REG, 0, 0, RW_R_R},
|
||||||
|
{"40_auth.kmod", REG, 0, 0, RW_R_R},
|
||||||
|
{"45_hypervisor.kmod", REG, 0, 0, RW_R_R},
|
||||||
|
{"47_dbg.kmod", REG, 0, 0, RW_R_R},
|
||||||
|
{"50_gpio.kmod", REG, 0, 0, RW_R_R},
|
||||||
|
{"70_stdlibadv.kmod", REG, 0, 0, RW_R_R},
|
||||||
|
{"90_init.kmod", REG, 0, 0, RW_R_R},
|
||||||
|
{"91_login.kmod", REG, 0, 0, RW_R_R},
|
||||||
|
{"92_permissions.kmod", REG, 0, 0, RW_R_R},
|
||||||
|
{"99_final.kmod", REG, 0, 0, RW_R_R},
|
||||||
|
})
|
||||||
|
|
||||||
|
mergeMeta("/etc", {
|
||||||
|
{"passwd", REG, 0, 0, RW_R_R },
|
||||||
|
{"shadow", REG, 0, 0, RW____ },
|
||||||
|
{"pam.d", REG, 0, 0, RWX_RX_RX},
|
||||||
|
})
|
||||||
|
|
||||||
|
mergeMeta("/etc/pam.d", {
|
||||||
|
{"secret", REG, 0, 0, RW____},
|
||||||
|
})
|
||||||
|
|
||||||
|
kernel.log("Filesystem permissions seeded.", "INFO")
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
local kernel = ...
|
||||||
|
kernel.allowGlobalOverwrites = false
|
||||||
@@ -203,7 +203,7 @@ def _make_firstboot_kmod(users):
|
|||||||
|
|
||||||
lines.append("do")
|
lines.append("do")
|
||||||
lines.append(" local ok, err = pcall(function()")
|
lines.append(" local ok, err = pcall(function()")
|
||||||
lines.append(" kernel.vfs.remove('/lib/modules/Hyperion/50_firstboot_users.kmod')")
|
lines.append(" kernel.vfs.remove('/lib/modules/hyperion/50_firstboot_users.kmod')")
|
||||||
lines.append(" end)")
|
lines.append(" end)")
|
||||||
lines.append(" if not ok then")
|
lines.append(" if not ok then")
|
||||||
lines.append(" kernel.log('FIRSTBOOT: could not self-delete: ' .. tostring(err), 'WARN')")
|
lines.append(" kernel.log('FIRSTBOOT: could not self-delete: ' .. tostring(err), 'WARN')")
|
||||||
@@ -215,7 +215,7 @@ def _make_firstboot_kmod(users):
|
|||||||
|
|
||||||
def inject_makeusers(users, arch):
|
def inject_makeusers(users, arch):
|
||||||
base = BUILD_ROOT / "$" if arch else BUILD_ROOT
|
base = BUILD_ROOT / "$" if arch else BUILD_ROOT
|
||||||
kmod_path = base / "lib" / "modules" / "Hyperion" / "50_firstboot_users.kmod"
|
kmod_path = base / "lib" / "modules" / "hyperion" / "50_firstboot_users.kmod"
|
||||||
kmod_path.parent.mkdir(parents=True, exist_ok=True)
|
kmod_path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
kmod_path.write_text(_make_firstboot_kmod(users), encoding="utf-8")
|
kmod_path.write_text(_make_firstboot_kmod(users), encoding="utf-8")
|
||||||
print(" Wrote first-boot user setup -> " + str(kmod_path.relative_to(BUILD_ROOT)))
|
print(" Wrote first-boot user setup -> " + str(kmod_path.relative_to(BUILD_ROOT)))
|
||||||
|
|||||||
Reference in new issue
Block a user