2 potential vulnerability fixes
This commit is contained in:
@@ -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 .. "]=]"
|
||||||
|
|||||||
@@ -60,21 +60,18 @@ local function parseMetafile(raw)
|
|||||||
local etype, owner, group, perms, cmeta
|
local etype, owner, group, perms, cmeta
|
||||||
|
|
||||||
if version == 0x02 then
|
if version == 0x02 then
|
||||||
-- v2: etype(1) + owner(2) + group(2) + perms(2) = 7 bytes
|
|
||||||
if p + 6 > #raw then break end
|
if p + 6 > #raw then break end
|
||||||
etype = raw:byte(p); p = p + 1
|
etype = raw:byte(p); p = p + 1
|
||||||
owner = raw:byte(p) + raw:byte(p+1) * 256; p = p + 2
|
owner = raw:byte(p) + raw:byte(p+1) * 256; p = p + 2
|
||||||
group = 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
|
perms = raw:byte(p) + raw:byte(p+1) * 256; p = p + 2
|
||||||
elseif version == 0x01 then
|
elseif version == 0x01 then
|
||||||
-- v1: etype(1) + owner(1) + group(1) + perms(2) = 5 bytes
|
|
||||||
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
|
||||||
group = raw:byte(p); p = p + 1
|
group = raw:byte(p); p = p + 1
|
||||||
perms = raw:byte(p) + raw:byte(p+1) * 256; p = p + 2
|
perms = raw:byte(p) + raw:byte(p+1) * 256; p = p + 2
|
||||||
else
|
else
|
||||||
-- v0: owner(1) + group(1) + perms(1) = 3 bytes
|
|
||||||
if p + 2 > #raw then break end
|
if p + 2 > #raw then break end
|
||||||
etype = 0x00
|
etype = 0x00
|
||||||
owner = raw:byte(p); p = p + 1
|
owner = raw:byte(p); p = p + 1
|
||||||
@@ -114,6 +111,22 @@ local function makeMetafile(meta)
|
|||||||
return out
|
return out
|
||||||
end
|
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 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 "/"
|
||||||
@@ -122,7 +135,9 @@ local function normalizePath(path)
|
|||||||
for part in path:gmatch("[^/]+") do
|
for part in path:gmatch("[^/]+") do
|
||||||
if part == ".." then
|
if part == ".." then
|
||||||
if #parts > 0 then table.remove(parts) end
|
if #parts > 0 then table.remove(parts) end
|
||||||
elseif part ~= "." and part ~= "" then
|
elseif part == "." or part == "" then
|
||||||
|
else
|
||||||
|
validateComponent(part)
|
||||||
table.insert(parts, part)
|
table.insert(parts, part)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -164,7 +179,6 @@ local function resolveMount(normalPath)
|
|||||||
return vfs.disks[mountId], diskPath
|
return vfs.disks[mountId], diskPath
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Expose parser for use by other modules (e.g. permissions seeder)
|
|
||||||
vfs._parseMetafile = parseMetafile
|
vfs._parseMetafile = parseMetafile
|
||||||
|
|
||||||
local function readMetaEntry(disk, parentDiskPath, filename)
|
local function readMetaEntry(disk, parentDiskPath, filename)
|
||||||
@@ -181,7 +195,6 @@ local function readMetaEntry(disk, parentDiskPath, filename)
|
|||||||
local raw = f.read(65535)
|
local raw = f.read(65535)
|
||||||
if f.close then f.close() end
|
if f.close then f.close() end
|
||||||
|
|
||||||
-- Auto-upgrade: if this .meta file is not v2, rewrite it as v2 now
|
|
||||||
if raw and #raw > 0 and raw:byte(1) ~= META_VERSION then
|
if raw and #raw > 0 and raw:byte(1) ~= META_VERSION then
|
||||||
local upgraded = makeMetafile(parseMetafile(raw))
|
local upgraded = makeMetafile(parseMetafile(raw))
|
||||||
local wok, wf = pcall(function() return disk:open(mp, "w") end)
|
local wok, wf = pcall(function() return disk:open(mp, "w") end)
|
||||||
@@ -440,7 +453,6 @@ function vfs.open(path, mode)
|
|||||||
if type(handle) ~= "table" then error("ENFILE") end
|
if type(handle) ~= "table" then error("ENFILE") end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- If this is a newly created file, stamp it with the creating user's ownership
|
|
||||||
if isNew then
|
if isNew then
|
||||||
local euid = (task and (task.euid or task.uid)) or kernel.uid
|
local euid = (task and (task.euid or task.uid)) or kernel.uid
|
||||||
local egid = (task and task.gid) or 0
|
local egid = (task and task.gid) or 0
|
||||||
@@ -629,7 +641,6 @@ function vfs.mkdir(path)
|
|||||||
checkperms(parentMeta, "w")
|
checkperms(parentMeta, "w")
|
||||||
local disk, diskPath = resolvePath(path)
|
local disk, diskPath = resolvePath(path)
|
||||||
disk:makeDirectory(diskPath)
|
disk:makeDirectory(diskPath)
|
||||||
-- Stamp the new directory with the creating user's ownership
|
|
||||||
local task = kernel.currentTask
|
local task = kernel.currentTask
|
||||||
local euid = (task and (task.euid or task.uid)) or kernel.uid
|
local euid = (task and (task.euid or task.uid)) or kernel.uid
|
||||||
local egid = (task and task.gid) or 0
|
local egid = (task and task.gid) or 0
|
||||||
|
|||||||
@@ -50,10 +50,8 @@ local function readonly(tbl)
|
|||||||
__metatable = false
|
__metatable = false
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
--local origLoad = load
|
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._U.load = function(a,b,c,d) return origLoad(a,b,c,d or kernel._U) end
|
kernel._U.load = function(a, b, c, d) return origLoad(a, b, c, d or kernel._U) end
|
||||||
kernel.allowGlobalOverwrites = false
|
|
||||||
@@ -1,5 +1,2 @@
|
|||||||
local args = {...}
|
local kernel = ...
|
||||||
local kernel = args[1]
|
kernel.allowGlobalOverwrites = false
|
||||||
|
|
||||||
local origLoad = load
|
|
||||||
--kernel._U.load = function(a,b,c,d) return origLoad(a,b,c,d or kernel._U) end
|
|
||||||
Reference in New Issue
Block a user