Skip to content

Commit 95da8b7

Browse files
committed
Add kernel lockdown utility functions to linux.py
This commit adds three new utility functions to avocado.utils.linux for managing kernel lockdown security feature: 1. is_kernel_lockdown_enabled(): Check current lockdown state - Returns tuple of (mode, is_enabled) - Supports none, integrity, and confidentiality modes - Handles cases where lockdown feature is unavailable 2. enable_kernel_lockdown_integrity(): Enable integrity mode - Prevents kernel modification - Verifies mode change via sysfs - Validates dmesg for lockdown message 3. enable_kernel_lockdown_confidentiality(): Enable confidentiality mode - Most restrictive mode (prevents modification and data exposure) - Verifies mode change via sysfs - Validates dmesg for lockdown message All functions follow PEP 8 standards and include comprehensive docstrings. Lockdown mode transitions are one-way at runtime and require reboot to downgrade. Signed-off-by: Maram Srimannarayana Murthy <msmurthy@linux.vnet.ibm.com>
1 parent 74b7379 commit 95da8b7

1 file changed

Lines changed: 125 additions & 2 deletions

File tree

avocado/utils/linux.py

Lines changed: 125 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525

2626
import os
2727

28-
from avocado.utils import genio, process
28+
from avocado.utils import dmesg, genio, process
2929

3030

3131
class UnsupportedMachineError(Exception):
@@ -94,7 +94,9 @@ def is_os_secureboot_enabled():
9494
if "00000002" in line:
9595
return True
9696
except FileNotFoundError as exc:
97-
raise UnsupportedMachineError("lsprop not a supported command") from exc
97+
raise UnsupportedMachineError(
98+
"lsprop not a supported command"
99+
) from exc
98100
return False
99101

100102

@@ -117,3 +119,124 @@ def enable_sched_schedstats():
117119
if is_sched_schedstats_enabled():
118120
return True
119121
return False
122+
123+
124+
def is_kernel_lockdown_enabled():
125+
"""
126+
Check the current kernel lockdown state.
127+
128+
The kernel lockdown feature restricts certain kernel functionalities
129+
to protect the system from unauthorized access or modification.
130+
131+
Lockdown modes:
132+
- none: Lockdown disabled
133+
- integrity: Prevents kernel modification
134+
- confidentiality: Prevents modification and data exposure
135+
136+
:return: Tuple of (mode_string, is_enabled_boolean)
137+
Returns ("none", False) if lockdown is disabled
138+
Returns ("integrity", True) if integrity mode is enabled
139+
Returns ("confidentiality", True) if confidentiality mode
140+
is enabled
141+
Returns (None, False) if lockdown feature is not available
142+
:rtype: tuple(str, bool)
143+
"""
144+
lockdown_path = "/sys/kernel/security/lockdown"
145+
try:
146+
lockdown_status = genio.read_one_line(lockdown_path).strip()
147+
for mode in ["none", "integrity", "confidentiality"]:
148+
if f"[{mode}]" in lockdown_status:
149+
is_enabled = mode != "none"
150+
return (mode, is_enabled)
151+
return ("none", False)
152+
except FileNotFoundError:
153+
return (None, False)
154+
except PermissionError:
155+
return (None, False)
156+
157+
158+
def enable_kernel_lockdown_integrity():
159+
"""
160+
Enable kernel lockdown in integrity mode.
161+
162+
Integrity mode prevents kernel modification but allows reading
163+
kernel data. This mode can be enabled from 'none' state or is
164+
already active if in 'integrity' or 'confidentiality' mode.
165+
166+
Note: Lockdown mode transitions are one-way at runtime:
167+
- none → integrity (allowed)
168+
- none → confidentiality (allowed)
169+
- integrity → confidentiality (allowed)
170+
- Cannot downgrade without reboot
171+
172+
Expected dmesg output when enabled:
173+
"Kernel is locked down from securityfs; see man kernel_lockdown.7"
174+
175+
:return: True if integrity mode is enabled successfully or already
176+
enabled, False otherwise
177+
:rtype: bool
178+
"""
179+
lockdown_path = "/sys/kernel/security/lockdown"
180+
current_mode, _ = is_kernel_lockdown_enabled()
181+
182+
if current_mode is None:
183+
return False
184+
185+
if current_mode in ["integrity", "confidentiality"]:
186+
return True
187+
188+
try:
189+
genio.write_one_line(lockdown_path, "integrity")
190+
new_mode, _ = is_kernel_lockdown_enabled()
191+
if new_mode in ["integrity", "confidentiality"]:
192+
expected_msg = "Kernel is locked down from securityfs"
193+
dmesg_errors = dmesg.collect_errors_dmesg([expected_msg])
194+
if not dmesg_errors:
195+
return False
196+
return True
197+
return False
198+
except (PermissionError, IOError):
199+
return False
200+
201+
202+
def enable_kernel_lockdown_confidentiality():
203+
"""
204+
Enable kernel lockdown in confidentiality mode.
205+
206+
Confidentiality mode prevents both kernel modification and data
207+
exposure. This is the most restrictive lockdown mode and can be
208+
enabled from any lower mode (none or integrity).
209+
210+
Note: Lockdown mode transitions are one-way at runtime:
211+
- none → confidentiality (allowed)
212+
- integrity → confidentiality (allowed)
213+
- Cannot downgrade without reboot
214+
215+
Expected dmesg output when enabled:
216+
"Kernel is locked down from securityfs; see man kernel_lockdown.7"
217+
218+
:return: True if confidentiality mode is enabled successfully or
219+
already enabled, False otherwise
220+
:rtype: bool
221+
"""
222+
lockdown_path = "/sys/kernel/security/lockdown"
223+
current_mode, _ = is_kernel_lockdown_enabled()
224+
225+
if current_mode is None:
226+
return False
227+
228+
if current_mode == "confidentiality":
229+
return True
230+
231+
try:
232+
genio.write_one_line(lockdown_path, "confidentiality")
233+
new_mode, _ = is_kernel_lockdown_enabled()
234+
if new_mode == "confidentiality":
235+
expected_msg = "Kernel is locked down from securityfs"
236+
dmesg_errors = dmesg.collect_errors_dmesg([expected_msg])
237+
if not dmesg_errors:
238+
return False
239+
return True
240+
return False
241+
except (PermissionError, IOError):
242+
return False

0 commit comments

Comments
 (0)