Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for blocking kernel modules #2274

Merged
merged 2 commits into from Jul 18, 2022

Conversation

bcressey
Copy link
Contributor

@bcressey bcressey commented Jul 14, 2022

Issue number:
Fixes #2235
Fixes #2236

Description of changes:
Provide a settings API for allowing or blocking specific kernel modules.

Testing done:
Confirmed that the new settings are available on upgrade, and cleaned up properly on downgrade.

Blocking a module rewrites modprobe.conf:

# apiclient set kernel.modules.sctp.allowed=false
# cat /etc/modprobe.d/modprobe.conf
install sctp /bin/true

A blocked module isn't loaded:

# modprobe -v -n sctp
install /bin/true

# modprobe sctp
modprobe: ERROR: Error running install command '/bin/true' for module sctp: retcode 127
modprobe: ERROR: could not insert 'sctp': Invalid argument

Allowing a module rewrites modprobe.conf:

# apiclient set kernel.modules.sctp.allowed=true
# cat /etc/modprobe.d/modprobe.conf
<no output>

An allowed module can be loaded:

# modprobe -v -n sctp
insmod /lib/modules/5.10.118/kernel/net/sctp/sctp.ko

# modprobe sctp
# grep sctp /proc/modules
sctp 434176 26 - Live 0xffffffffc0745000

Terms of contribution:

By submitting this pull request, I agree that this contribution is dual-licensed under the terms of both the Apache License, version 2.0, and the MIT license.

@bcressey
Copy link
Contributor Author

The 127 return code for a blocked module happens because kmod uses system() to invoke the install command, which tries to run a shell, which isn't available in Bottlerocket.

This seems OK to me even if it's a little incongruous with the expected result of using /bin/true as the install command. That's a bit of an odd choice in its own right, but the various compliance benchmarks have settled on this as the "standard" mechanism, and I wanted to stay consistent with other distros here.

If the return code causes problems in practice, I can look at patching kmod to either always return true, or to use fork/exec rather than system(), but I feel like it's fine for now.

@@ -621,6 +621,17 @@ Here are the metrics settings:
May be set to "none" (the default in older [variants](variants/), up through aws-k8s-1.19), "integrity" (the default for newer [variants](variants/)), or "confidentiality".
**Important note:** this setting cannot be lowered (toward 'none') at runtime.
You must reboot for a change to a lower level to take effect.
* `settings.kernel.modules.<name>.allowed`: Whether the named kernel module is allowed to be loaded.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you considered having a blocked list? The current API implementation doesn't allow us to delete keys in the settings so if I want to allow a module in the current scheme, I have to set the allowed flag as true, which practically has the same effect as not having the setting at all. With this scheme, users could end up with many keys that they might not really need if they later decide to allow some of the previously blocked modules. But with the blocked list, they only have to modify one list, instead of many keys.

Also with a list, you can save yourself the extra if and unless statements in the handlebars template:

{{#each settings.kernel.modules.blocked}}
install {{this}} /bin/true
{{/each}}

And probably the extra KmodSetting type.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did consider it. The problem with lists is that they can't be incrementally updated; you have to reapply the current state with the desired additions or removals to get to the desired state. That makes it difficult to document independent steps for disabling individual modules, which is something I had to do for the CIS benchmark.

Copy link
Contributor

@cbgbt cbgbt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! 🚀

Copy link
Contributor

@zmrow zmrow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😶‍🌫️

For compliance or policy reasons, the system administrator might want
to prevent certain kernel modules from being loaded, if they are not
expected to be used.

This isn't meant to be an ironclad guarantee that the desired kernel
functionality will never be available. The module could be built into
the kernel instead, or loaded early in the boot, or a core dependency
of another required module.

Signed-off-by: Ben Cressey <bcressey@amazon.com>
Clean up the kernel modules setting and metadata on downgrade, since
older releases don't support this functionality.

Signed-off-by: Ben Cressey <bcressey@amazon.com>
@bcressey
Copy link
Contributor Author

Rebased to fix the merge conflict around migrations.

@bcressey bcressey merged commit 9b9b32a into bottlerocket-os:develop Jul 18, 2022
@bcressey bcressey deleted the kernel-modules-setting branch July 18, 2022 13:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

disable kernel support for uncommon network protocols disable kernel support for unused filesystems
7 participants