Add qt.chromium.sandboxing setting and sandboxing test

This commit is contained in:
Florian Bruhin 2022-03-03 21:16:04 +01:00
parent 38acd8f44a
commit 8fe1de2fdc
6 changed files with 128 additions and 0 deletions

View File

@ -60,6 +60,7 @@ Added
which shows relative tab numbers.
- New `input.mode_override` option which allows overriding the current mode
based on the new URL when navigating or switching tabs.
- New `qt.chromium.sandboxing` setting which allows to disable Chromium's sandboxing (mainly intended for development and testing)
Fixed
~~~~~

View File

@ -289,6 +289,7 @@
|<<qt.args,qt.args>>|Additional arguments to pass to Qt, without leading `--`.
|<<qt.chromium.low_end_device_mode,qt.chromium.low_end_device_mode>>|When to use Chromium's low-end device mode.
|<<qt.chromium.process_model,qt.chromium.process_model>>|Which Chromium process model to use.
|<<qt.chromium.sandboxing,qt.chromium.sandboxing>>|What sandboxing mechanisms in Chromium to use.
|<<qt.environ,qt.environ>>|Additional environment variables to set.
|<<qt.force_platform,qt.force_platform>>|Force a Qt platform to use.
|<<qt.force_platformtheme,qt.force_platformtheme>>|Force a Qt platformtheme to use.
@ -3814,6 +3815,30 @@ Valid values:
Default: +pass:[process-per-site-instance]+
[[qt.chromium.sandboxing]]
=== qt.chromium.sandboxing
What sandboxing mechanisms in Chromium to use.
Chromium has various sandboxing layers, which should be enabled for normal browser usage. Mainly for testing and development, it's possible to disable individual sandboxing layers via this setting.
Open `chrome://sandbox` to see the current sandbox status.
Changing this setting is only recommended if you know what you're doing, as it **disables one of Chromium's security layers**. To avoid sandboxing being accidentally disabled persistently, this setting can only be set via `config.py`, not via `:set`.
See the Chromium documentation for more details: - Linux: https://chromium.googlesource.com/chromium/src/+/HEAD/docs/linux/sandboxing.md - Windows: https://chromium.googlesource.com/chromium/src/+/HEAD/docs/design/sandbox.md - FAQ (Windows-centric): https://chromium.googlesource.com/chromium/src/+/HEAD/docs/design/sandbox_faq.md
This setting requires a restart.
This setting can only be set in config.py.
This setting is only available with the QtWebEngine backend.
Type: <<types,String>>
Valid values:
* +enable-all+: Enable all available sandboxing mechanisms.
* +disable-seccomp-bpf+: Disable the Seccomp BPF filter sandbox (Linux only).
* +disable-all+: Disable all sandboxing (**not recommended!**).
Default: +pass:[enable-all]+
[[qt.environ]]
=== qt.environ
Additional environment variables to set.

View File

@ -290,6 +290,36 @@ qt.chromium.low_end_device_mode:
This improves the RAM usage of renderer processes, at the expense of
performance.
qt.chromium.sandboxing:
type:
name: String
valid_values:
- enable-all: Enable all available sandboxing mechanisms.
- disable-seccomp-bpf: Disable the Seccomp BPF filter sandbox (Linux only).
- disable-all: Disable all sandboxing (**not recommended!**).
default: enable-all
backend: QtWebEngine
restart: true
no_autoconfig: true # due to it being dangerous
desc: >-
What sandboxing mechanisms in Chromium to use.
Chromium has various sandboxing layers, which should be enabled for normal
browser usage. Mainly for testing and development, it's possible to disable
individual sandboxing layers via this setting.
Open `chrome://sandbox` to see the current sandbox status.
Changing this setting is only recommended if you know what you're doing, as
it **disables one of Chromium's security layers**. To avoid sandboxing being
accidentally disabled persistently, this setting can only be set via
`config.py`, not via `:set`.
See the Chromium documentation for more details:
- Linux: https://chromium.googlesource.com/chromium/src/+/HEAD/docs/linux/sandboxing.md
- Windows: https://chromium.googlesource.com/chromium/src/+/HEAD/docs/design/sandbox.md
- FAQ (Windows-centric): https://chromium.googlesource.com/chromium/src/+/HEAD/docs/design/sandbox_faq.md
qt.highdpi:
type: Bool
default: false

View File

@ -338,6 +338,11 @@ def _qtwebengine_settings_args(versions: version.WebEngineVersions) -> Iterator[
True: '--force-prefers-reduced-motion',
False: None,
},
'qt.chromium.sandboxing': {
'enable-all': None,
'disable-seccomp-bpf': '--disable-seccomp-filter-sandbox',
'disable-all': '--no-sandbox',
}
}
qt_514_ver = utils.VersionNumber(5, 14)

View File

@ -826,3 +826,48 @@ def test_json_logging_without_debug(request, quteproc_new, runtime_tmpdir):
quteproc_new.exit_expected = True
quteproc_new.start(args, env={'XDG_RUNTIME_DIR': str(runtime_tmpdir)})
assert not quteproc_new.is_running()
@pytest.mark.qtwebkit_skip
@pytest.mark.parametrize('sandboxing, has_namespaces, has_seccomp, has_yama, expected_result', [
('enable-all', True, True, True, "You are adequately sandboxed."),
('disable-seccomp-bpf', True, False, True, "You are NOT adequately sandboxed."),
('disable-all', False, False, False, "You are NOT adequately sandboxed."),
])
def test_sandboxing(
request, quteproc_new, sandboxing,
has_namespaces, has_seccomp, has_yama, expected_result,
):
args = _base_args(request.config) + [
'--temp-basedir',
'-s', 'qt.chromium.sandboxing', sandboxing,
]
quteproc_new.start(args)
quteproc_new.open_url('chrome://sandbox')
text = quteproc_new.get_content()
print(text)
header, *lines, empty, result = text.split("\n")
assert header == "Sandbox Status"
assert not empty
status = dict(line.split("\t") for line in lines)
bpf_text = "Seccomp-BPF sandbox"
yama_text = "Ptrace Protection with Yama LSM"
expected_status = {
"Layer 1 Sandbox": "Namespace" if has_namespaces else "None",
"PID namespaces": "Yes" if has_namespaces else "No",
"Network namespaces": "Yes" if has_namespaces else "No",
bpf_text: "Yes" if has_seccomp else "No",
f"{bpf_text} supports TSYNC": "Yes" if has_seccomp else "No",
f"{yama_text} (Broker)": "Yes" if has_yama else "No",
f"{yama_text} (Non-broker)": "No",
}
assert status == expected_status
assert result == expected_result

View File

@ -277,6 +277,28 @@ class TestWebEngineArgs:
else:
assert arg in args
@pytest.mark.parametrize('sandboxing, arg', [
('enable-all', None),
('disable-seccomp-bpf', '--disable-seccomp-filter-sandbox'),
('disable-all', '--no-sandbox'),
])
def test_sandboxing(self, config_stub, parser, sandboxing, arg):
config_stub.val.qt.chromium.sandboxing = sandboxing
parsed = parser.parse_args([])
args = qtargs.qt_args(parsed)
remaining_flags = {
'--no-sandbox',
'--disable-seccomp-filter-sandbox',
}
if arg is not None:
remaining_flags.remove(arg)
if arg is not None:
assert arg in args
assert not set(args) & remaining_flags
@pytest.mark.parametrize('qt_version, referer, arg', [
# 'always' -> no arguments
('5.15.0', 'always', None),