opnsense-src/sys/tools/syscalls/config.lua
Brooks Davis ec86d763d1 sys/tools/syscalls: desupport capabilities.conf
We haven't used this since commit be67ea40c5 in 2021 so stop carrying
it forward.

Also remove support for setting the list in syscalls.conf via the
capenabled variable.  This was last used by cloudabi (removed in 2021
by commit cf0ee8738e).
2024-10-30 21:04:31 +00:00

263 lines
7.6 KiB
Lua

--
-- SPDX-License-Identifier: BSD-2-Clause
--
-- Copyright (c) 2021-2024 SRI International
-- Copyright (c) 2024 Tyler Baxter <agge@FreeBSD.org>
-- Copyright (c) 2023 Warner Losh <imp@bsdimp.com>
-- Copyright (c) 2019 Kyle Evans <kevans@FreeBSD.org>
--
--
-- Code to read in the config file that drives this. Since we inherit from the
-- FreeBSD makesyscall.sh legacy, all config is done through a config file that
-- sets a number of variables (as noted below); it used to be a .sh file that
-- was sourced in. This dodges the need to write a command line parser.
--
local util = require("tools.util")
--
-- Global config map.
-- Default configuration is native. Any of these may get replaced by an
-- optionally specified configuration file.
--
local config = {
sysnames = "syscalls.c",
syshdr = "../sys/syscall.h",
sysmk = "/dev/null",
syssw = "init_sysent.c",
systrace = "systrace_args.c",
sysproto = "../sys/sysproto.h",
libsysmap = "/dev/null",
libsys_h = "/dev/null",
sysproto_h = "_SYS_SYSPROTO_H_",
syscallprefix = "SYS_",
switchname = "sysent",
namesname = "syscallnames",
abi_flags = {},
abi_func_prefix = "",
abi_type_suffix = "",
abi_long = "long",
abi_u_long = "u_long",
abi_semid_t = "semid_t",
abi_size_t = "size_t",
abi_ptr_array_t = "",
abi_headers = "",
abi_intptr_t = "intptr_t",
ptr_intptr_t_cast = "intptr_t",
obsol = {},
unimpl = {},
compat_set = "native",
mincompat = 0,
-- System calls that require ABI-specific handling.
syscall_abi_change = {},
-- System calls that appear to require handling, but don't.
syscall_no_abi_change = {},
-- Keep track of modifications if there are.
modifications = {},
-- Stores compat_sets from syscalls.conf; config.mergeCompat()
-- instantiates.
compat_options = {},
}
--
-- For each entry, the ABI flag is the key. One may also optionally provide an
-- expr, which are contained in an array associated with each key; expr gets
-- applied to each argument type to indicate whether this argument is subject to
-- ABI change given the configured flags.
--
config.known_abi_flags = {
long_size = {
"_Contains[a-z_]*_long_",
"^long [a-z0-9_]+$",
"long [*]",
"size_t [*]",
-- semid_t is not included because it is only used
-- as an argument or written out individually and
-- said writes are handled by the ksem framework.
-- Technically a sign-extension issue exists for
-- arguments, but because semid_t is actually a file
-- descriptor negative 32-bit values are invalid
-- regardless of sign-extension.
},
time_t_size = {
"_Contains[a-z_]*_timet_",
},
pointer_args = {
-- no expr
},
pointer_size = {
"_Contains[a-z_]*_ptr_",
"[*][*]",
},
pair_64bit = {
"^dev_t[ ]*$",
"^id_t[ ]*$",
"^off_t[ ]*$",
},
}
-- All compat option entries should have five entries:
-- definition: The preprocessor macro that will be set for this.
-- compatlevel: The level this compatibility should be included at. This
-- generally represents the version of FreeBSD that it is compatible
-- with, but ultimately it's just the level of mincompat in which it's
-- included.
-- flag: The name of the flag in syscalls.master.
-- prefix: The prefix to use for _args and syscall prototype. This will be
-- used as-is, without "_" or any other character appended.
-- descr: The description of this compat option in init_sysent.c comments.
-- The special "stdcompat" entry will cause the other five to be autogenerated.
local compat_option_sets = {
native = {
{
definition = "COMPAT_43",
compatlevel = 3,
flag = "COMPAT",
prefix = "o",
descr = "old",
},
{ stdcompat = "FREEBSD4" },
{ stdcompat = "FREEBSD6" },
{ stdcompat = "FREEBSD7" },
{ stdcompat = "FREEBSD10" },
{ stdcompat = "FREEBSD11" },
{ stdcompat = "FREEBSD12" },
{ stdcompat = "FREEBSD13" },
{ stdcompat = "FREEBSD14" },
},
}
--
-- config looks like a shell script; in fact, the previous makesyscalls.sh
-- script actually sourced it in. It had a pretty common format, so we should
-- be fine to make various assumptions.
--
-- This function processes config to be merged into our global config map with
-- config.merge(). It aborts if there's malformed lines and returns NIL and a
-- message if no file was provided.
--
function config.process(file)
local cfg = {}
local comment_line_expr = "^%s*#.*"
-- We capture any whitespace padding here so we can easily advance to
-- the end of the line as needed to check for any trailing bogus bits.
-- Alternatively, we could drop the whitespace and instead try to
-- use a pattern to strip out the meaty part of the line, but then we
-- would need to sanitize the line for potentially special characters.
local line_expr = "^([%w%p]+%s*)=(%s*[`\"]?[^\"`]*[`\"]?)"
if not file then
return nil, "No file given"
end
local fh = assert(io.open(file))
for nextline in fh:lines() do
-- Strip any whole-line comments.
nextline = nextline:gsub(comment_line_expr, "")
-- Parse it into key, value pairs.
local key, value = nextline:match(line_expr)
if key ~= nil and value ~= nil then
local kvp = key .. "=" .. value
key = util.trim(key)
value = util.trim(value)
local delim = value:sub(1,1)
if delim == '"' then
local trailing_context
-- Strip off the key/value part.
trailing_context = nextline:sub(kvp:len() + 1)
-- Strip off any trailing comment.
trailing_context = trailing_context:gsub("#.*$",
"")
-- Strip off leading/trailing whitespace.
trailing_context = util.trim(trailing_context)
if trailing_context ~= "" then
print(trailing_context)
util.abort(1,
"Malformed line: " .. nextline)
end
value = util.trim(value, delim)
else
-- Strip off potential comments.
value = value:gsub("#.*$", "")
-- Strip off any padding whitespace.
value = util.trim(value)
if value:match("%s") then
util.abort(1,
"Malformed config line: " ..
nextline)
end
end
cfg[key] = value
elseif not nextline:match("^%s*$") then
-- Make sure format violations don't get overlooked
-- here, but ignore blank lines. Comments are already
-- stripped above.
util.abort(1, "Malformed config line: " .. nextline)
end
end
assert(fh:close())
return cfg
end
-- Merges processed configuration file into the global config map (see above),
-- or returns NIL and a message if no file was provided.
function config.merge(fh)
if not fh then
return nil, "No file given"
end
local res = assert(config.process(fh))
for k, v in pairs(res) do
if v ~= config[k] then
-- Handling of string lists:
if k:find("abi_flags") then
-- Match for pipe, that's how abi_flags
-- is formatted.
config[k] = util.setFromString(v, "[^|]+")
elseif k:find("syscall_abi_change") or
k:find("syscall_no_abi_change") or
k:find("obsol") or
k:find("unimpl") then
-- Match for space, that's how these
-- are formatted.
config[k] = util.setFromString(v, "[^ ]+")
else
config[k] = v
end
-- Construct config modified table as config
-- is processed.
config.modifications[k] = true
else
-- config wasn't modified.
config.modifications[k] = false
end
end
end
-- Returns TRUE if there are ABI changes from native for the provided ABI flag.
function config.abiChanges(name)
if config.known_abi_flags[name] == nil then
util.abort(1, "abi_changes: unknown flag: " .. name)
end
return config.abi_flags[name] ~= nil
end
-- Instantiates config.compat_options.
function config.mergeCompat()
if config.compat_set ~= "" then
if not compat_option_sets[config.compat_set] then
util.abort(1, "Undefined compat set: " ..
config.compat_set)
end
config.compat_options = compat_option_sets[config.compat_set]
end
end
return config