file permissions fixes

This commit is contained in:
2026-02-23 23:50:37 -06:00
parent 8798a2f4fe
commit 6bb7f03a3e
2 changed files with 193 additions and 165 deletions

View File

@@ -111,43 +111,52 @@ local function makeMetafile(meta)
return out return out
end end
local function validateComponent(part) local SAFE_COMPONENT_PATTERN = "^[A-Za-z0-9_.+%-%@ %(%)%[%] ]+$"
if part == "" then
error("EINVAL: empty path component", 2)
end
if part:sub(1, 2) == ".." then
error("EINVAL: illegal path component '" .. part .. "'", 2)
end
if part:find("\0", 1, true) then
error("EINVAL: null byte in path component", 2)
end
if part:find("/", 1, true) then
error("EINVAL: slash in path component", 2)
end
return true
end
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 == "." or part == "" then local stack = {}
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 else
validateComponent(part) comp = path:sub(i)
table.insert(parts, part) i = len + 1
end
if comp == "" or comp == "." then
elseif comp == ".." then
if #stack > 0 then
table.remove(stack)
end
else
if not comp:match(SAFE_COMPONENT_PATTERN) then
error("EINVAL: illegal characters in 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

View File

@@ -29,110 +29,47 @@ local function makeEntry(name, etype, owner, group, perms, cmeta)
.. string.char(#cmeta) .. cmeta .. string.char(#cmeta) .. cmeta
end 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 local REG = 0x00
-- All known /bin entries with their permissions
local BIN_ENTRIES = {
{"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},
{"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},
{"startup", REG, 0, 0, RWX_RX_RX},
}
-- Merge entries: always ensure all known entries exist with correct permissions.
-- This handles both fresh installs and upgrades (adds missing entries, upgrades
-- the on-disk format to v2 by rewriting).
local function mergeMeta(dir, entries) local function mergeMeta(dir, entries)
local diskDir = dir local diskDir = dir
if diskDir:sub(1,1) == "/" then diskDir = diskDir:sub(2) end if diskDir:sub(1,1) == "/" then diskDir = diskDir:sub(2) end
local metaPath = (diskDir == "" and ".meta" or diskDir .. "/.meta") local metaPath = (diskDir == "" and ".meta" or diskDir .. "/.meta")
-- Read existing meta (may be v1 or v2)
local existing = {} local existing = {}
local rok, rf = pcall(function() return rootDisk:open(metaPath, "r") end) local rok, rf = pcall(function() return rootDisk:open(metaPath, "r") end)
if rok and rf then if rok and rf then
local raw = rf.read(65535) local raw = rf.read(65535)
if rf.close then rf.close() end if rf.close then rf.close() end
-- Parse using the VFS parser (handles v0/v1/v2) existing = (kernel.vfs._parseMetafile and kernel.vfs._parseMetafile(raw)) or {}
existing = kernel.vfs and kernel.vfs._parseMetafile and kernel.vfs._parseMetafile(raw) or {}
end end
-- Add any missing entries (don't overwrite existing customised perms)
for _, e in ipairs(entries) do for _, e in ipairs(entries) do
if not existing[e[1]] then local name = e[1]
existing[e[1]] = { local etype = e[2] or REG
etype = e[2] or 0x00, local owner = e[3] or 0
owner = e[3] or 0, local group = e[4] or 0
group = e[4] or 0, local perms = e[5] or RWX_RX_RX
perms = e[5] or RWX_RX_RX, local cmeta = e[6] or ""
cmeta = e[6] or "", existing[name] = {
} etype = etype,
end owner = owner,
group = group,
perms = perms,
cmeta = cmeta,
}
end end
-- Write back as v2
local data = string.char(META_VERSION) local data = string.char(META_VERSION)
for name, m in pairs(existing) do for name, m in pairs(existing) do
data = data .. makeEntry(name, m.etype or 0x00, m.owner or 0, m.group or 0, m.perms or RWX_RX_RX, m.cmeta or "") 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 end
local ok, err = pcall(function() local ok, err = pcall(function()
@@ -145,70 +82,152 @@ local function mergeMeta(dir, entries)
end end
end end
local freshInstall = not rootDisk:fileExists(".meta") kernel.log("Seeding filesystem permissions...", "INFO")
if freshInstall then mergeMeta("/", {
kernel.log("Seeding filesystem permissions...", "INFO") {"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},
})
-- / (only on fresh install — these dirs are stable) mergeMeta("/boot", {
writeMeta("/", { {"kernel.lua", REG, 0, 0, RW_R_R },
{"bin", REG, 0, 0, RWX_RX_RX}, {"boot.cfg", REG, 0, 0, RW_R_R },
{"boot", REG, 0, 0, RWX_RX_RX}, {"safeboot.cfg", REG, 0, 0, RW_R_R },
{"dev", REG, 0, 0, RWX_RX_RX}, {"fstab", REG, 0, 0, RW_R_R },
{"etc", REG, 0, 0, RWX_RX_RX}, {"initfs", REG, 0, 0, RW_R_R },
{"home", REG, 0, 0, RWX_RX_RX}, {"cct", REG, 0, 0, RWX_RX_RX},
{"lib", REG, 0, 0, RWX_RX_RX}, {"oc", 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},
})
writeMeta("/bin/startup", { mergeMeta("/boot/cct", {
{"test.lua", REG, 0, 0, RWX_RX_RX}, {"boot.lua", REG, 0, 0, RW_R_R},
}) {"initdisks", REG, 0, 0, RW_R_R},
{"eeprom", REG, 0, 0, RW_R_R},
})
writeMeta("/etc", { mergeMeta("/boot/oc", {
{"passwd", REG, 0, 0, RW_R_R}, {"boot.lua", REG, 0, 0, RW_R_R},
{"shadow", REG, 0, 0, RW____}, {"initfs.lua",REG, 0, 0, RW_R_R},
{"pam.d", REG, 0, 0, RWX_RX_RX}, {"eeprom", REG, 0, 0, RW_R_R},
}) })
writeMeta("/etc/pam.d", { mergeMeta("/sbin", {
{"secret", REG, 0, 0, RW____}, {"init.lua", REG, 0, 0, RWX_RX_RX},
}) })
writeMeta("/sbin", { mergeMeta("/bin", {
{"init.lua", REG, 0, 0, RWX_RX_RX}, {"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},
})
writeMeta("/boot", { mergeMeta("/bin/startup", {
{"kernel.lua", REG, 0, 0, RW_R_R }, {"test.lua", REG, 0, 0, RWX_RX_RX},
{"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},
})
writeMeta("/lib", { mergeMeta("/lib", {
{"sys", REG, 0, 0, RWX_RX_RX}, {"sys", REG, 0, 0, RWX_RX_RX},
{"modules", REG, 0, 0, RWX_RX_RX}, {"modules", REG, 0, 0, RWX_RX_RX},
{"crypto", REG, 0, 0, RWX_RX_RX}, {"crypto", REG, 0, 0, RWX_RX_RX},
{"store", REG, 0, 0, RWX_RX_RX}, {"store", REG, 0, 0, RWX_RX_RX},
{"snip", REG, 0, 0, RW_R_R }, {"snip", REG, 0, 0, RW_R_R },
{"io", REG, 0, 0, RW_R_R }, {"io", REG, 0, 0, RW_R_R },
{"bit32", REG, 0, 0, RW_R_R }, {"bit32", REG, 0, 0, RW_R_R },
}) })
kernel.log("Filesystem permissions seeded.", "INFO") mergeMeta("/lib/sys", {
else {"fs", REG, 0, 0, RW_R_R},
kernel.log("Permissions already seeded, merging /bin updates...", "INFO") {"hpv", REG, 0, 0, RW_R_R},
end {"ipc", REG, 0, 0, RW_R_R},
{"term", REG, 0, 0, RW_R_R},
{"init", REG, 0, 0, RW_R_R},
})
-- Always merge /bin — adds missing entries and upgrades format to v2 mergeMeta("/lib/modules", {
mergeMeta("/bin", BIN_ENTRIES) {"Hyperion", REG, 0, 0, RWX_RX_RX},
})
kernel.log("Permission module loaded.", "INFO") 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")