From 6bb7f03a3e2a79e6c804853401589a5c6c651af6 Mon Sep 17 00:00:00 2001 From: spsf Date: Mon, 23 Feb 2026 23:50:37 -0600 Subject: [PATCH] file permissions fixes --- .../lib/modules/Hyperion/10_vfs.kmod | 57 ++-- .../lib/modules/Hyperion/92_permissions.kmod | 301 ++++++++++-------- 2 files changed, 193 insertions(+), 165 deletions(-) diff --git a/Src/Hyperion-kernel/lib/modules/Hyperion/10_vfs.kmod b/Src/Hyperion-kernel/lib/modules/Hyperion/10_vfs.kmod index d15989a..6024265 100644 --- a/Src/Hyperion-kernel/lib/modules/Hyperion/10_vfs.kmod +++ b/Src/Hyperion-kernel/lib/modules/Hyperion/10_vfs.kmod @@ -111,43 +111,52 @@ local function makeMetafile(meta) return out end -local function validateComponent(part) - 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 SAFE_COMPONENT_PATTERN = "^[A-Za-z0-9_.+%-%@ %(%)%[%] ]+$" local function normalizePath(path) local task = kernel.currentTask local cwd = task.cwd or "/" - if path:sub(1,1) ~= "/" then path = cwd .. "/" .. path end - local parts = {} - for part in path:gmatch("[^/]+") do - if part == ".." then - if #parts > 0 then table.remove(parts) end - elseif part == "." or part == "" then + + if path:sub(1, 1) ~= "/" then + path = cwd .. "/" .. path + end + + 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 - validateComponent(part) - table.insert(parts, part) + comp = path:sub(i) + 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 - local result = "/" .. table.concat(parts, "/") + + local result = "/" .. table.concat(stack, "/") + local root = task and task.root if root and root ~= "/" then if result ~= root and result:sub(1, #root + 1) ~= root .. "/" then result = root end end + return result end diff --git a/Src/Hyperion-kernel/lib/modules/Hyperion/92_permissions.kmod b/Src/Hyperion-kernel/lib/modules/Hyperion/92_permissions.kmod index da3e8d4..85274c8 100644 --- a/Src/Hyperion-kernel/lib/modules/Hyperion/92_permissions.kmod +++ b/Src/Hyperion-kernel/lib/modules/Hyperion/92_permissions.kmod @@ -29,110 +29,47 @@ local function makeEntry(name, etype, owner, group, perms, cmeta) .. 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 --- 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 diskDir = dir if diskDir:sub(1,1) == "/" then diskDir = diskDir:sub(2) end local metaPath = (diskDir == "" and ".meta" or diskDir .. "/.meta") - -- Read existing meta (may be v1 or v2) 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 - -- Parse using the VFS parser (handles v0/v1/v2) - existing = kernel.vfs and kernel.vfs._parseMetafile and kernel.vfs._parseMetafile(raw) or {} + existing = (kernel.vfs._parseMetafile and kernel.vfs._parseMetafile(raw)) or {} end - -- Add any missing entries (don't overwrite existing customised perms) for _, e in ipairs(entries) do - if not existing[e[1]] then - existing[e[1]] = { - etype = e[2] or 0x00, - owner = e[3] or 0, - group = e[4] or 0, - perms = e[5] or RWX_RX_RX, - cmeta = e[6] or "", - } - end + 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 - -- Write back as v2 local data = string.char(META_VERSION) 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 local ok, err = pcall(function() @@ -145,70 +82,152 @@ local function mergeMeta(dir, entries) end end -local freshInstall = not rootDisk:fileExists(".meta") +kernel.log("Seeding filesystem permissions...", "INFO") -if freshInstall then - 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}, +}) - -- / (only on fresh install — these dirs are stable) - 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}, - }) +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}, +}) - writeMeta("/bin/startup", { - {"test.lua", 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}, +}) - writeMeta("/etc", { - {"passwd", REG, 0, 0, RW_R_R}, - {"shadow", REG, 0, 0, RW____}, - {"pam.d", REG, 0, 0, RWX_RX_RX}, - }) +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}, +}) - writeMeta("/etc/pam.d", { - {"secret", REG, 0, 0, RW____}, - }) +mergeMeta("/sbin", { + {"init.lua", REG, 0, 0, RWX_RX_RX}, +}) - writeMeta("/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}, +}) - 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}, - }) +mergeMeta("/bin/startup", { + {"test.lua", REG, 0, 0, RWX_RX_RX}, +}) - 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 }, - }) +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 }, +}) - kernel.log("Filesystem permissions seeded.", "INFO") -else - kernel.log("Permissions already seeded, merging /bin updates...", "INFO") -end +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}, +}) --- Always merge /bin — adds missing entries and upgrades format to v2 -mergeMeta("/bin", BIN_ENTRIES) +mergeMeta("/lib/modules", { + {"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")