Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
kernel-hardening-checker
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
fact-depend
kernel-hardening-checker
Commits
dc68441b
Commit
dc68441b
authored
Jul 09, 2023
by
Alexander Popov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add the basic infrastructure for checking sysctl
Refers to #65
parent
d50ea2d4
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
35 additions
and
7 deletions
+35
-7
__init__.py
kconfig_hardened_check/__init__.py
+29
-4
checks.py
kconfig_hardened_check/checks.py
+6
-3
No files found.
kconfig_hardened_check/__init__.py
View file @
dc68441b
...
@@ -17,7 +17,7 @@ from collections import OrderedDict
...
@@ -17,7 +17,7 @@ from collections import OrderedDict
import
re
import
re
import
json
import
json
from
.__about__
import
__version__
from
.__about__
import
__version__
from
.checks
import
add_kconfig_checks
,
add_cmdline_checks
,
normalize_cmdline_options
from
.checks
import
add_kconfig_checks
,
add_cmdline_checks
,
normalize_cmdline_options
,
add_sysctl_checks
from
.engine
import
populate_with_data
,
perform_checks
,
override_expected_value
from
.engine
import
populate_with_data
,
perform_checks
,
override_expected_value
...
@@ -197,6 +197,10 @@ def parse_cmdline_file(parsed_options, fname):
...
@@ -197,6 +197,10 @@ def parse_cmdline_file(parsed_options, fname):
parsed_options
[
name
]
=
value
parsed_options
[
name
]
=
value
def
parse_sysctl_file
(
parsed_options
,
fname
):
print
(
'parse_sysctl_file: TODO'
)
def
main
():
def
main
():
# Report modes:
# Report modes:
# * verbose mode for
# * verbose mode for
...
@@ -214,11 +218,14 @@ def main():
...
@@ -214,11 +218,14 @@ def main():
help
=
'check the security hardening options in the kernel Kconfig file (also supports *.gz files)'
)
help
=
'check the security hardening options in the kernel Kconfig file (also supports *.gz files)'
)
parser
.
add_argument
(
'-l'
,
'--cmdline'
,
parser
.
add_argument
(
'-l'
,
'--cmdline'
,
help
=
'check the security hardening options in the kernel cmdline file (contents of /proc/cmdline)'
)
help
=
'check the security hardening options in the kernel cmdline file (contents of /proc/cmdline)'
)
# parser.add_argument('-s', '--sysctl',
# help='check the security hardening options in the sysctl output file (`sudo sysctl -a > file`)')
parser
.
add_argument
(
'-p'
,
'--print'
,
choices
=
supported_archs
,
parser
.
add_argument
(
'-p'
,
'--print'
,
choices
=
supported_archs
,
help
=
'print the security hardening recommendations for the selected microarchitecture'
)
help
=
'print the security hardening recommendations for the selected microarchitecture'
)
parser
.
add_argument
(
'-g'
,
'--generate'
,
choices
=
supported_archs
,
parser
.
add_argument
(
'-g'
,
'--generate'
,
choices
=
supported_archs
,
help
=
'generate a Kconfig fragment with the security hardening options for the selected microarchitecture'
)
help
=
'generate a Kconfig fragment with the security hardening options for the selected microarchitecture'
)
args
=
parser
.
parse_args
()
args
=
parser
.
parse_args
()
args
.
sysctl
=
None
# FIXME
mode
=
None
mode
=
None
if
args
.
mode
:
if
args
.
mode
:
...
@@ -239,6 +246,8 @@ def main():
...
@@ -239,6 +246,8 @@ def main():
print
(
f
'[+] Kconfig file to check: {args.config}'
)
print
(
f
'[+] Kconfig file to check: {args.config}'
)
if
args
.
cmdline
:
if
args
.
cmdline
:
print
(
f
'[+] Kernel cmdline file to check: {args.cmdline}'
)
print
(
f
'[+] Kernel cmdline file to check: {args.cmdline}'
)
if
args
.
sysctl
:
print
(
f
'[+] Kernel sysctl output file to check: {args.sysctl}'
)
arch
,
msg
=
detect_arch
(
args
.
config
,
supported_archs
)
arch
,
msg
=
detect_arch
(
args
.
config
,
supported_archs
)
if
arch
is
None
:
if
arch
is
None
:
...
@@ -266,6 +275,10 @@ def main():
...
@@ -266,6 +275,10 @@ def main():
# add relevant cmdline checks to the checklist
# add relevant cmdline checks to the checklist
add_cmdline_checks
(
config_checklist
,
arch
)
add_cmdline_checks
(
config_checklist
,
arch
)
if
args
.
sysctl
:
# add relevant sysctl checks to the checklist
add_sysctl_checks
(
config_checklist
,
arch
)
# populate the checklist with the parsed Kconfig data
# populate the checklist with the parsed Kconfig data
parsed_kconfig_options
=
OrderedDict
()
parsed_kconfig_options
=
OrderedDict
()
parse_kconfig_file
(
parsed_kconfig_options
,
args
.
config
)
parse_kconfig_file
(
parsed_kconfig_options
,
args
.
config
)
...
@@ -280,6 +293,12 @@ def main():
...
@@ -280,6 +293,12 @@ def main():
parse_cmdline_file
(
parsed_cmdline_options
,
args
.
cmdline
)
parse_cmdline_file
(
parsed_cmdline_options
,
args
.
cmdline
)
populate_with_data
(
config_checklist
,
parsed_cmdline_options
,
'cmdline'
)
populate_with_data
(
config_checklist
,
parsed_cmdline_options
,
'cmdline'
)
if
args
.
sysctl
:
# populate the checklist with the parsed sysctl data
parsed_sysctl_options
=
OrderedDict
()
parse_sysctl_file
(
parsed_sysctl_options
,
args
.
sysctl
)
populate_with_data
(
config_checklist
,
parsed_sysctl_options
,
'sysctl'
)
# hackish refinement of the CONFIG_ARCH_MMAP_RND_BITS check
# hackish refinement of the CONFIG_ARCH_MMAP_RND_BITS check
mmap_rnd_bits_max
=
parsed_kconfig_options
.
get
(
'CONFIG_ARCH_MMAP_RND_BITS_MAX'
,
None
)
mmap_rnd_bits_max
=
parsed_kconfig_options
.
get
(
'CONFIG_ARCH_MMAP_RND_BITS_MAX'
,
None
)
if
mmap_rnd_bits_max
:
if
mmap_rnd_bits_max
:
...
@@ -293,6 +312,8 @@ def main():
...
@@ -293,6 +312,8 @@ def main():
all_parsed_options
=
parsed_kconfig_options
# assignment does not copy
all_parsed_options
=
parsed_kconfig_options
# assignment does not copy
if
args
.
cmdline
:
if
args
.
cmdline
:
all_parsed_options
.
update
(
parsed_cmdline_options
)
all_parsed_options
.
update
(
parsed_cmdline_options
)
if
args
.
sysctl
:
all_parsed_options
.
update
(
parsed_sysctl_options
)
print_unknown_options
(
config_checklist
,
all_parsed_options
)
print_unknown_options
(
config_checklist
,
all_parsed_options
)
# finally print the results
# finally print the results
...
@@ -300,22 +321,26 @@ def main():
...
@@ -300,22 +321,26 @@ def main():
sys
.
exit
(
0
)
sys
.
exit
(
0
)
elif
args
.
cmdline
:
elif
args
.
cmdline
:
sys
.
exit
(
'[!] ERROR: checking cmdline doesn
\'
t work without checking Kconfig'
)
sys
.
exit
(
'[!] ERROR: checking cmdline depends on checking Kconfig'
)
elif
args
.
sysctl
:
# TODO: sysctl check should also work separately
sys
.
exit
(
'[!] ERROR: checking sysctl depends on checking Kconfig'
)
if
args
.
print
:
if
args
.
print
:
assert
(
args
.
config
is
None
and
args
.
cmdline
is
None
),
'unexpected args'
assert
(
args
.
config
is
None
and
args
.
cmdline
is
None
and
args
.
sysctl
is
None
),
'unexpected args'
if
mode
and
mode
not
in
(
'verbose'
,
'json'
):
if
mode
and
mode
not
in
(
'verbose'
,
'json'
):
sys
.
exit
(
f
'[!] ERROR: wrong mode "{mode}" for --print'
)
sys
.
exit
(
f
'[!] ERROR: wrong mode "{mode}" for --print'
)
arch
=
args
.
print
arch
=
args
.
print
add_kconfig_checks
(
config_checklist
,
arch
)
add_kconfig_checks
(
config_checklist
,
arch
)
add_cmdline_checks
(
config_checklist
,
arch
)
add_cmdline_checks
(
config_checklist
,
arch
)
add_sysctl_checks
(
config_checklist
,
arch
)
if
mode
!=
'json'
:
if
mode
!=
'json'
:
print
(
f
'[+] Printing kernel security hardening options for {arch}...'
)
print
(
f
'[+] Printing kernel security hardening options for {arch}...'
)
print_checklist
(
mode
,
config_checklist
,
False
)
print_checklist
(
mode
,
config_checklist
,
False
)
sys
.
exit
(
0
)
sys
.
exit
(
0
)
if
args
.
generate
:
if
args
.
generate
:
assert
(
args
.
config
is
None
and
args
.
cmdline
is
None
),
'unexpected args'
assert
(
args
.
config
is
None
and
args
.
cmdline
is
None
and
args
.
sysctl
is
None
),
'unexpected args'
if
mode
:
if
mode
:
sys
.
exit
(
f
'[!] ERROR: wrong mode "{mode}" for --generate'
)
sys
.
exit
(
f
'[!] ERROR: wrong mode "{mode}" for --generate'
)
arch
=
args
.
generate
arch
=
args
.
generate
...
...
kconfig_hardened_check/checks.py
View file @
dc68441b
...
@@ -11,7 +11,7 @@ This module contains knowledge for checks.
...
@@ -11,7 +11,7 @@ This module contains knowledge for checks.
# pylint: disable=missing-function-docstring,line-too-long,invalid-name
# pylint: disable=missing-function-docstring,line-too-long,invalid-name
# pylint: disable=too-many-branches,too-many-statements
# pylint: disable=too-many-branches,too-many-statements
from
.engine
import
KconfigCheck
,
CmdlineCheck
,
VersionCheck
,
OR
,
AND
from
.engine
import
KconfigCheck
,
CmdlineCheck
,
SysctlCheck
,
VersionCheck
,
OR
,
AND
def
add_kconfig_checks
(
l
,
arch
):
def
add_kconfig_checks
(
l
,
arch
):
...
@@ -574,10 +574,9 @@ def normalize_cmdline_options(option, value):
...
@@ -574,10 +574,9 @@ def normalize_cmdline_options(option, value):
return
value
return
value
#
def add_sysctl_checks(l, arch):
def
add_sysctl_checks
(
l
,
arch
):
# TODO: draft of security hardening sysctls:
# TODO: draft of security hardening sysctls:
# kernel.kptr_restrict=2 (or 1?)
# kernel.kptr_restrict=2 (or 1?)
# kernel.dmesg_restrict=1 (also see the kconfig option)
# kernel.perf_event_paranoid=2 (or 3 with a custom patch, see https://lwn.net/Articles/696216/)
# kernel.perf_event_paranoid=2 (or 3 with a custom patch, see https://lwn.net/Articles/696216/)
# kernel.kexec_load_disabled=1
# kernel.kexec_load_disabled=1
# kernel.yama.ptrace_scope=3
# kernel.yama.ptrace_scope=3
...
@@ -605,3 +604,7 @@ def normalize_cmdline_options(option, value):
...
@@ -605,3 +604,7 @@ def normalize_cmdline_options(option, value):
# kernel.oops_limit (think about a proper value)
# kernel.oops_limit (think about a proper value)
# kernel.warn_limit (think about a proper value)
# kernel.warn_limit (think about a proper value)
# net.ipv4.tcp_syncookies=1 (?)
# net.ipv4.tcp_syncookies=1 (?)
#
# Calling the SysctlCheck class constructor:
# SysctlCheck(reason, decision, name, expected)
l
+=
[
SysctlCheck
(
'self_protection'
,
'kspp'
,
'kernel.dmesg_restrict'
,
'1'
)]
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment