Skip to content

Commit 500fb1c

Browse files
committed
Error when Landlock ABI is too old for requested network/IPC features
Signed-off-by: Cong Wang <cwang@multikernel.io>
1 parent 491af97 commit 500fb1c

File tree

2 files changed

+42
-3
lines changed

2 files changed

+42
-3
lines changed

src/sandlock/_landlock.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,8 @@ def confine(
250250
251251
Raises:
252252
LandlockUnavailableError: If Landlock is not supported.
253-
ConfinementError: If confinement setup fails.
253+
ConfinementError: If confinement setup fails, or if network/IPC
254+
features are requested but the kernel's Landlock ABI is too old.
254255
"""
255256
abi = landlock_abi_version()
256257
if abi < 1:
@@ -272,15 +273,25 @@ def confine(
272273

273274
# Network handled mask (ABI v4+)
274275
handled_net = 0
275-
if abi >= 4:
276+
if bind_ports is not None or connect_ports is not None:
277+
if abi < 4:
278+
raise ConfinementError(
279+
f"Network port restrictions require Landlock ABI >= 4 "
280+
f"(Linux >= 6.7), but this kernel only supports ABI v{abi}"
281+
)
276282
if bind_ports is not None:
277283
handled_net |= LANDLOCK_ACCESS_NET_BIND_TCP
278284
if connect_ports is not None:
279285
handled_net |= LANDLOCK_ACCESS_NET_CONNECT_TCP
280286

281287
# IPC scoping mask (ABI v6+)
282288
scoped = 0
283-
if abi >= 6:
289+
if isolate_ipc or isolate_signals:
290+
if abi < 6:
291+
raise ConfinementError(
292+
f"IPC/signal isolation requires Landlock ABI >= 6 "
293+
f"(Linux >= 6.12), but this kernel only supports ABI v{abi}"
294+
)
284295
if isolate_ipc:
285296
scoped |= LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET
286297
if isolate_signals:

tests/test_landlock.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# SPDX-License-Identifier: Apache-2.0
22
"""Tests for sandlock._landlock."""
33

4+
from unittest import mock
5+
46
import pytest
57

68
from sandlock._landlock import (
@@ -13,8 +15,10 @@
1315
_FULL_ACCESS,
1416
_READ_ACCESS,
1517
_WRITE_ACCESS,
18+
confine,
1619
landlock_abi_version,
1720
)
21+
from sandlock.exceptions import ConfinementError
1822

1923

2024
class TestAccessFlags:
@@ -49,6 +53,30 @@ def test_scope_flags_no_overlap(self):
4953
assert LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET & LANDLOCK_SCOPE_SIGNAL == 0
5054

5155

56+
class TestAbiVersionGuards:
57+
"""confine() must error when features need a newer ABI than available."""
58+
59+
@mock.patch("sandlock._landlock.landlock_abi_version", return_value=3)
60+
def test_bind_ports_requires_abi4(self, _mock_abi):
61+
with pytest.raises(ConfinementError, match="ABI >= 4"):
62+
confine(readable=["/tmp"], bind_ports=[80])
63+
64+
@mock.patch("sandlock._landlock.landlock_abi_version", return_value=3)
65+
def test_connect_ports_requires_abi4(self, _mock_abi):
66+
with pytest.raises(ConfinementError, match="ABI >= 4"):
67+
confine(readable=["/tmp"], connect_ports=[443])
68+
69+
@mock.patch("sandlock._landlock.landlock_abi_version", return_value=5)
70+
def test_isolate_ipc_requires_abi6(self, _mock_abi):
71+
with pytest.raises(ConfinementError, match="ABI >= 6"):
72+
confine(readable=["/tmp"], isolate_ipc=True)
73+
74+
@mock.patch("sandlock._landlock.landlock_abi_version", return_value=5)
75+
def test_isolate_signals_requires_abi6(self, _mock_abi):
76+
with pytest.raises(ConfinementError, match="ABI >= 6"):
77+
confine(readable=["/tmp"], isolate_signals=True)
78+
79+
5280
class TestLandlockAbiVersion:
5381
def test_returns_int(self):
5482
ver = landlock_abi_version()

0 commit comments

Comments
 (0)