Compare commits
7 Commits
1.2-releas
...
1.2.2
| Author | SHA1 | Date | |
|---|---|---|---|
| ab1e847d1c | |||
| 62a03bfe6b | |||
| e77a8b3636 | |||
| 6bb7f03a3e | |||
| 8798a2f4fe | |||
| a6d2f6dca7 | |||
| b015d5880a |
@@ -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/")
|
||||||
|
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("/")
|
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,11 +184,18 @@ 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
|
||||||
kernel.apis=apis
|
kernel.apis=apis
|
||||||
|
|||||||
@@ -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")
|
|
||||||
@@ -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 .. "]=]"
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
|
|
||||||
@@ -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,11 +208,15 @@ 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)
|
||||||
local task = tasks[tostring(pid)]
|
local task = tasks[tostring(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
|
||||||
233
Src/Hyperion-kernel/lib/modules/hyperion/92_permissions.kmod
Normal file
233
Src/Hyperion-kernel/lib/modules/hyperion/92_permissions.kmod
Normal file
@@ -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")
|
||||||
2
Src/Hyperion-kernel/lib/modules/hyperion/99_final.kmod
Normal file
2
Src/Hyperion-kernel/lib/modules/hyperion/99_final.kmod
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
local kernel = ...
|
||||||
|
kernel.allowGlobalOverwrites = false
|
||||||
4
build.py
4
build.py
@@ -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