按源保护 PythonPlugin inittab 初始化边界
This commit is contained in:
@@ -7,7 +7,7 @@ cd "$(dirname "$0")"
|
|||||||
# rs274/tooldata sources directly or link wasm-safe shims whose source basis is
|
# rs274/tooldata sources directly or link wasm-safe shims whose source basis is
|
||||||
# checked against LinuxCNC source comments before building.
|
# checked against LinuxCNC source comments before building.
|
||||||
usage() {
|
usage() {
|
||||||
echo "usage: $0 --mode tooldata-link|tooldata-common-link|interp-base-link|python-plugin-link|rs274ngc-pre-object" >&2
|
echo "usage: $0 --mode tooldata-link|tooldata-common-link|interp-base-link|python-plugin-link|python-plugin-inittab-link|rs274ngc-pre-object" >&2
|
||||||
}
|
}
|
||||||
|
|
||||||
mode=
|
mode=
|
||||||
@@ -33,7 +33,7 @@ while [[ "$#" -gt 0 ]]; do
|
|||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
case "$mode" in
|
case "$mode" in
|
||||||
tooldata-link|tooldata-common-link|interp-base-link|python-plugin-link|rs274ngc-pre-object)
|
tooldata-link|tooldata-common-link|interp-base-link|python-plugin-link|python-plugin-inittab-link|rs274ngc-pre-object)
|
||||||
;;
|
;;
|
||||||
"")
|
"")
|
||||||
usage
|
usage
|
||||||
@@ -114,14 +114,21 @@ case "$mode" in
|
|||||||
)
|
)
|
||||||
target_name=interp_base_probe
|
target_name=interp_base_probe
|
||||||
;;
|
;;
|
||||||
python-plugin-link)
|
python-plugin-link|python-plugin-inittab-link)
|
||||||
python_plugin_shim=$(./list-linuxcnc-wasm-safe-shims.sh python_plugin.cc)
|
python_plugin_shim=$(./list-linuxcnc-wasm-safe-shims.sh python_plugin.cc)
|
||||||
grep -F 'LinuxCNC source basis: src/emc/pythonplugin/python_plugin.cc and' core/wasm_shims/pythonplugin/python_plugin_probe_main.cc >/dev/null
|
if [[ "$mode" == "python-plugin-link" ]]; then
|
||||||
|
probe_source=core/wasm_shims/pythonplugin/python_plugin_probe_main.cc
|
||||||
|
target_name=python_plugin_probe
|
||||||
|
grep -F 'LinuxCNC source basis: src/emc/pythonplugin/python_plugin.cc and' "$probe_source" >/dev/null
|
||||||
|
else
|
||||||
|
probe_source=core/wasm_shims/pythonplugin/python_plugin_inittab_probe_main.cc
|
||||||
|
target_name=python_plugin_inittab_probe
|
||||||
|
grep -F 'LinuxCNC source basis: src/emc/pythonplugin/python_plugin.cc' "$probe_source" >/dev/null
|
||||||
|
fi
|
||||||
sources+=(
|
sources+=(
|
||||||
"$python_plugin_shim"
|
"$python_plugin_shim"
|
||||||
core/wasm_shims/pythonplugin/python_plugin_probe_main.cc
|
"$probe_source"
|
||||||
)
|
)
|
||||||
target_name=python_plugin_probe
|
|
||||||
;;
|
;;
|
||||||
rs274ngc-pre-object)
|
rs274ngc-pre-object)
|
||||||
rs274ngc_pre_source=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-source-files.sh src/emc/rs274ngc/rs274ngc_pre.cc)
|
rs274ngc_pre_source=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-source-files.sh src/emc/rs274ngc/rs274ngc_pre.cc)
|
||||||
|
|||||||
@@ -93,11 +93,15 @@ grep -F 'return vsnprintf(buffer, size, fmt, args);' \
|
|||||||
grep -F 'class PythonPlugin' "$linuxcnc_root/src/emc/pythonplugin/python_plugin.hh" >/dev/null
|
grep -F 'class PythonPlugin' "$linuxcnc_root/src/emc/pythonplugin/python_plugin.hh" >/dev/null
|
||||||
grep -F 'PLUGIN_PYTHON_NOT_INITIALIZED = -12,' "$linuxcnc_root/src/emc/pythonplugin/python_plugin.hh" >/dev/null
|
grep -F 'PLUGIN_PYTHON_NOT_INITIALIZED = -12,' "$linuxcnc_root/src/emc/pythonplugin/python_plugin.hh" >/dev/null
|
||||||
grep -F 'PLUGIN_BAD_PATH = -5,' "$linuxcnc_root/src/emc/pythonplugin/python_plugin.hh" >/dev/null
|
grep -F 'PLUGIN_BAD_PATH = -5,' "$linuxcnc_root/src/emc/pythonplugin/python_plugin.hh" >/dev/null
|
||||||
|
grep -F 'PLUGIN_INITTAB_FAILED = -7 ,' "$linuxcnc_root/src/emc/pythonplugin/python_plugin.hh" >/dev/null
|
||||||
grep -F 'PLUGIN_EXCEPTION_DURING_PATH_PREPEND = -9,' "$linuxcnc_root/src/emc/pythonplugin/python_plugin.hh" >/dev/null
|
grep -F 'PLUGIN_EXCEPTION_DURING_PATH_PREPEND = -9,' "$linuxcnc_root/src/emc/pythonplugin/python_plugin.hh" >/dev/null
|
||||||
grep -F 'PLUGIN_EXCEPTION_DURING_PATH_APPEND = -10,' "$linuxcnc_root/src/emc/pythonplugin/python_plugin.hh" >/dev/null
|
grep -F 'PLUGIN_EXCEPTION_DURING_PATH_APPEND = -10,' "$linuxcnc_root/src/emc/pythonplugin/python_plugin.hh" >/dev/null
|
||||||
grep -F 'PLUGIN_NO_CALLABLE = 1,' "$linuxcnc_root/src/emc/pythonplugin/python_plugin.hh" >/dev/null
|
grep -F 'PLUGIN_NO_CALLABLE = 1,' "$linuxcnc_root/src/emc/pythonplugin/python_plugin.hh" >/dev/null
|
||||||
grep -F 'PLUGIN_EXCEPTION = 2' "$linuxcnc_root/src/emc/pythonplugin/python_plugin.hh" >/dev/null
|
grep -F 'PLUGIN_EXCEPTION = 2' "$linuxcnc_root/src/emc/pythonplugin/python_plugin.hh" >/dev/null
|
||||||
grep -F 'PythonPlugin::instantiate' "$linuxcnc_root/src/emc/pythonplugin/python_plugin.cc" >/dev/null
|
grep -F 'PythonPlugin::instantiate' "$linuxcnc_root/src/emc/pythonplugin/python_plugin.cc" >/dev/null
|
||||||
|
grep -F 'for (int i = 0; inittab[i].name != NULL; i++) {' "$linuxcnc_root/src/emc/pythonplugin/python_plugin.cc" >/dev/null
|
||||||
|
grep -F 'if (module == NULL) {' "$linuxcnc_root/src/emc/pythonplugin/python_plugin.cc" >/dev/null
|
||||||
|
grep -F 'status = PLUGIN_INITTAB_FAILED;' "$linuxcnc_root/src/emc/pythonplugin/python_plugin.cc" >/dev/null
|
||||||
grep -F 'if (status < PLUGIN_OK)' "$linuxcnc_root/src/emc/pythonplugin/python_plugin.cc" >/dev/null
|
grep -F 'if (status < PLUGIN_OK)' "$linuxcnc_root/src/emc/pythonplugin/python_plugin.cc" >/dev/null
|
||||||
grep -F 'if (auto inistring = inifile.findString("TOPLEVEL", section)) {' \
|
grep -F 'if (auto inistring = inifile.findString("TOPLEVEL", section)) {' \
|
||||||
"$linuxcnc_root/src/emc/pythonplugin/python_plugin.cc" >/dev/null
|
"$linuxcnc_root/src/emc/pythonplugin/python_plugin.cc" >/dev/null
|
||||||
@@ -327,6 +331,7 @@ for needle in [
|
|||||||
|
|
||||||
python_plugin_shim = Path("core/wasm_shims/pythonplugin/python_plugin.cc").read_text(encoding="utf-8")
|
python_plugin_shim = Path("core/wasm_shims/pythonplugin/python_plugin.cc").read_text(encoding="utf-8")
|
||||||
python_plugin_probe = Path("core/wasm_shims/pythonplugin/python_plugin_probe_main.cc").read_text(encoding="utf-8")
|
python_plugin_probe = Path("core/wasm_shims/pythonplugin/python_plugin_probe_main.cc").read_text(encoding="utf-8")
|
||||||
|
python_plugin_inittab_probe = Path("core/wasm_shims/pythonplugin/python_plugin_inittab_probe_main.cc").read_text(encoding="utf-8")
|
||||||
python_c_api_shim = Path("core/wasm_shims/python_c_api_shim.cc").read_text(encoding="utf-8")
|
python_c_api_shim = Path("core/wasm_shims/python_c_api_shim.cc").read_text(encoding="utf-8")
|
||||||
for forbidden in [
|
for forbidden in [
|
||||||
"bp::exec(",
|
"bp::exec(",
|
||||||
@@ -340,6 +345,8 @@ for needle in [
|
|||||||
'find_ini_value(iniFilename, section, "TOPLEVEL", toplevel)',
|
'find_ini_value(iniFilename, section, "TOPLEVEL", toplevel)',
|
||||||
"realpath(toplevel.c_str(), resolved_path) == nullptr",
|
"realpath(toplevel.c_str(), resolved_path) == nullptr",
|
||||||
"status = PLUGIN_BAD_PATH;",
|
"status = PLUGIN_BAD_PATH;",
|
||||||
|
"status = PLUGIN_INITTAB_FAILED;",
|
||||||
|
"failed to initialize built-in module",
|
||||||
'check_python_path_entries(iniFilename,',
|
'check_python_path_entries(iniFilename,',
|
||||||
"PLUGIN_EXCEPTION_DURING_PATH_PREPEND",
|
"PLUGIN_EXCEPTION_DURING_PATH_PREPEND",
|
||||||
"PLUGIN_EXCEPTION_DURING_PATH_APPEND",
|
"PLUGIN_EXCEPTION_DURING_PATH_APPEND",
|
||||||
@@ -351,6 +358,16 @@ for needle in [
|
|||||||
]:
|
]:
|
||||||
if needle not in python_plugin_shim:
|
if needle not in python_plugin_shim:
|
||||||
raise SystemExit(f"PythonPlugin wasm shim missing disabled-python boundary: {needle}")
|
raise SystemExit(f"PythonPlugin wasm shim missing disabled-python boundary: {needle}")
|
||||||
|
for needle in [
|
||||||
|
"PythonPlugin::PythonPlugin(struct _inittab*) reports PLUGIN_INITTAB_FAILED",
|
||||||
|
"PythonPlugin *plugin = PythonPlugin::instantiate(bad_modules);",
|
||||||
|
"plugin != nullptr",
|
||||||
|
"python_plugin->plugin_status() != PLUGIN_INITTAB_FAILED",
|
||||||
|
"python_plugin->usable()",
|
||||||
|
'python_plugin->last_errmsg() != "failed to initialize built-in module"',
|
||||||
|
]:
|
||||||
|
if needle not in python_plugin_inittab_probe:
|
||||||
|
raise SystemExit(f"PythonPlugin inittab probe missing first-caller status assertion: {needle}")
|
||||||
for needle in [
|
for needle in [
|
||||||
"PLUGIN_NO_SECTION",
|
"PLUGIN_NO_SECTION",
|
||||||
"PLUGIN_BAD_INIFILE",
|
"PLUGIN_BAD_INIFILE",
|
||||||
@@ -437,6 +454,7 @@ for phrase in [
|
|||||||
"must not execute `bp::exec`, `bp::exec_file`, or",
|
"must not execute `bp::exec`, `bp::exec_file`, or",
|
||||||
"inactive-DB return values",
|
"inactive-DB return values",
|
||||||
"negative-status short-circuit behavior",
|
"negative-status short-circuit behavior",
|
||||||
|
"first-caller `_inittab` `PLUGIN_INITTAB_FAILED` edge",
|
||||||
"preserve the `TOPLEVEL` missing-path `PLUGIN_BAD_PATH` edge",
|
"preserve the `TOPLEVEL` missing-path `PLUGIN_BAD_PATH` edge",
|
||||||
"preserve `PATH_PREPEND` and `PATH_APPEND` tilde-expansion failure statuses",
|
"preserve `PATH_PREPEND` and `PATH_APPEND` tilde-expansion failure statuses",
|
||||||
"LinuxCNC `rcs_print_error` split entry points",
|
"LinuxCNC `rcs_print_error` split entry points",
|
||||||
|
|||||||
@@ -113,10 +113,27 @@ int check_python_path_entries(const char *iniFilename,
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
PythonPlugin *PythonPlugin::instantiate(struct _inittab *) {
|
PythonPlugin *PythonPlugin::instantiate(struct _inittab *inittab) {
|
||||||
static PythonPlugin plugin;
|
static PythonPlugin plugin;
|
||||||
python_plugin = &plugin;
|
if (!python_plugin) {
|
||||||
python_plugin->status = PLUGIN_OK;
|
python_plugin = &plugin;
|
||||||
|
python_plugin->status = PLUGIN_OK;
|
||||||
|
if (inittab) {
|
||||||
|
for (int i = 0; inittab[i].name != nullptr; ++i) {
|
||||||
|
// LinuxCNC source basis: python_plugin.cc reports
|
||||||
|
// PLUGIN_INITTAB_FAILED when a built-in module from the
|
||||||
|
// _inittab cannot be initialized.
|
||||||
|
if (!inittab[i].initfunc || inittab[i].initfunc() == nullptr) {
|
||||||
|
python_plugin->error_msg = "failed to initialize built-in module";
|
||||||
|
python_plugin->status = PLUGIN_INITTAB_FAILED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!python_plugin->usable()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
return python_plugin;
|
return python_plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
#include "pythonplugin/python_plugin.hh"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
PyObject *init_bad_module() {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
// LinuxCNC source basis: src/emc/pythonplugin/python_plugin.cc
|
||||||
|
// PythonPlugin::PythonPlugin(struct _inittab*) reports PLUGIN_INITTAB_FAILED
|
||||||
|
// when a built-in Python module from the first caller's inittab cannot be
|
||||||
|
// initialized; instantiate() then returns nullptr for the unusable plugin.
|
||||||
|
int main() {
|
||||||
|
_inittab bad_modules[] = {
|
||||||
|
{"cnc_sim_bad_module", init_bad_module},
|
||||||
|
{nullptr, nullptr},
|
||||||
|
};
|
||||||
|
|
||||||
|
PythonPlugin *plugin = PythonPlugin::instantiate(bad_modules);
|
||||||
|
if (plugin != nullptr) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (python_plugin == nullptr) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
if (python_plugin->plugin_status() != PLUGIN_INITTAB_FAILED) {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
if (python_plugin->usable()) {
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
if (python_plugin->last_errmsg() != "failed to initialize built-in module") {
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -61,8 +61,10 @@ only; it must not add CNC behavior and must not expand the temporary smoke parse
|
|||||||
`python_plugin.cc` link expectations; it must not call into CPython runtime.
|
`python_plugin.cc` link expectations; it must not call into CPython runtime.
|
||||||
- `core/wasm_shims/pythonplugin/python_plugin.cc` must preserve LinuxCNC
|
- `core/wasm_shims/pythonplugin/python_plugin.cc` must preserve LinuxCNC
|
||||||
`PythonPlugin` status edges for `PLUGIN_NO_SECTION`, `PLUGIN_BAD_INIFILE`,
|
`PythonPlugin` status edges for `PLUGIN_NO_SECTION`, `PLUGIN_BAD_INIFILE`,
|
||||||
`PLUGIN_BAD_PATH`, `PLUGIN_PYTHON_NOT_INITIALIZED`, `PLUGIN_NO_CALLABLE`,
|
`PLUGIN_BAD_PATH`, `PLUGIN_INITTAB_FAILED`,
|
||||||
and `PLUGIN_EXCEPTION` while keeping Python execution disabled.
|
`PLUGIN_PYTHON_NOT_INITIALIZED`, `PLUGIN_NO_CALLABLE`, and
|
||||||
|
`PLUGIN_EXCEPTION` while keeping Python execution disabled.
|
||||||
|
- The PythonPlugin shim must preserve the first-caller `_inittab` `PLUGIN_INITTAB_FAILED` edge from `src/emc/pythonplugin/python_plugin.cc` when a built-in module init function fails, while keeping browser-safe probes detached from real Python module execution.
|
||||||
- The PythonPlugin shim must preserve the `TOPLEVEL` missing-path `PLUGIN_BAD_PATH` edge from `src/emc/pythonplugin/python_plugin.cc` before reporting the browser-safe disabled Python runtime status.
|
- The PythonPlugin shim must preserve the `TOPLEVEL` missing-path `PLUGIN_BAD_PATH` edge from `src/emc/pythonplugin/python_plugin.cc` before reporting the browser-safe disabled Python runtime status.
|
||||||
- The PythonPlugin shim must preserve `PATH_PREPEND` and `PATH_APPEND` tilde-expansion failure statuses from `src/emc/pythonplugin/python_plugin.cc` and `src/emc/ini/inifile.cc` without executing Python path mutation in browser-safe probes.
|
- The PythonPlugin shim must preserve `PATH_PREPEND` and `PATH_APPEND` tilde-expansion failure statuses from `src/emc/pythonplugin/python_plugin.cc` and `src/emc/ini/inifile.cc` without executing Python path mutation in browser-safe probes.
|
||||||
- The PythonPlugin shim must not execute `bp::exec`, `bp::exec_file`, or real
|
- The PythonPlugin shim must not execute `bp::exec`, `bp::exec_file`, or real
|
||||||
|
|||||||
@@ -6,7 +6,9 @@ cd "$(dirname "$0")"
|
|||||||
# LinuxCNC source basis: src/emc/pythonplugin/python_plugin.cc and
|
# LinuxCNC source basis: src/emc/pythonplugin/python_plugin.cc and
|
||||||
# python_plugin.hh define the PythonPlugin API covered by this wrapper.
|
# python_plugin.hh define the PythonPlugin API covered by this wrapper.
|
||||||
probe=$(./build-linuxcnc-wasm-standalone-probe.sh --mode python-plugin-link)
|
probe=$(./build-linuxcnc-wasm-standalone-probe.sh --mode python-plugin-link)
|
||||||
|
inittab_probe=$(./build-linuxcnc-wasm-standalone-probe.sh --mode python-plugin-inittab-link)
|
||||||
|
|
||||||
"$probe"
|
"$probe"
|
||||||
|
"$inittab_probe"
|
||||||
|
|
||||||
echo "linuxcnc wasm python_plugin link probe passed"
|
echo "linuxcnc wasm python_plugin link probe passed"
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ grep -F 'LinuxCNC source basis: this probe derives required Python C API exports
|
|||||||
grep -F 'LinuxCNC source basis: this probe compares wasm-safe tooldata runtime stubs' test-linuxcnc-wasm-tooldata-runtime-symbols.sh >/dev/null
|
grep -F 'LinuxCNC source basis: this probe compares wasm-safe tooldata runtime stubs' test-linuxcnc-wasm-tooldata-runtime-symbols.sh >/dev/null
|
||||||
grep -F 'LinuxCNC source basis: the standalone probe links src/emc/rs274ngc/interp_base.cc' test-linuxcnc-wasm-interp-base-link.sh >/dev/null
|
grep -F 'LinuxCNC source basis: the standalone probe links src/emc/rs274ngc/interp_base.cc' test-linuxcnc-wasm-interp-base-link.sh >/dev/null
|
||||||
grep -F 'LinuxCNC source basis: src/emc/pythonplugin/python_plugin.cc and' test-linuxcnc-wasm-python-plugin-link.sh >/dev/null
|
grep -F 'LinuxCNC source basis: src/emc/pythonplugin/python_plugin.cc and' test-linuxcnc-wasm-python-plugin-link.sh >/dev/null
|
||||||
|
grep -F 'python-plugin-inittab-link' test-linuxcnc-wasm-python-plugin-link.sh >/dev/null
|
||||||
grep -F 'LinuxCNC source basis: src/emc/rs274ngc/rs274ngc_pre.cc is compiled directly' test-linuxcnc-wasm-rs274ngc-pre-object.sh >/dev/null
|
grep -F 'LinuxCNC source basis: src/emc/rs274ngc/rs274ngc_pre.cc is compiled directly' test-linuxcnc-wasm-rs274ngc-pre-object.sh >/dev/null
|
||||||
grep -F 'LinuxCNC source basis: src/emc/rs274ngc/rs274ngc_pre.cc provides the Interp' test-linuxcnc-wasm-rs274ngc-pre-link.sh >/dev/null
|
grep -F 'LinuxCNC source basis: src/emc/rs274ngc/rs274ngc_pre.cc provides the Interp' test-linuxcnc-wasm-rs274ngc-pre-link.sh >/dev/null
|
||||||
grep -F 'LinuxCNC source basis: src/emc/rs274ngc/rs274ngc_pre.cc provides read()' test-linuxcnc-wasm-runtime-link.sh >/dev/null
|
grep -F 'LinuxCNC source basis: src/emc/rs274ngc/rs274ngc_pre.cc provides read()' test-linuxcnc-wasm-runtime-link.sh >/dev/null
|
||||||
|
|||||||
Reference in New Issue
Block a user