Skip to content

Commit ced57b0

Browse files
committed
feat: support optionally disabling module sig verification
Support disabling kernel module signature verification. Note that this does not work when SecureBoot is enabled. Fixes: #11989 Signed-off-by: Noel Georgi <git@frezbo.dev>
1 parent 1e5c4ed commit ced57b0

File tree

13 files changed

+156
-3
lines changed

13 files changed

+156
-3
lines changed

api/resource/definitions/runtime/runtime.proto

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ message SecurityStateSpec {
156156
talos.resource.definitions.enums.RuntimeSELinuxState se_linux_state = 4;
157157
bool booted_with_uki = 5;
158158
talos.resource.definitions.enums.RuntimeFIPSState fips_state = 6;
159+
bool module_signature_enforced = 7;
159160
}
160161

161162
// UniqueMachineTokenSpec is the spec for the machine unique token. Token can be empty if machine wasn't assigned any.

hack/release.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,14 @@ Additionally `talosctl image cache-create` has some changes:
119119
* multiple instances (`--platform=linux/amd64 --platform=linux/arm64`);
120120
"""
121121

122+
[notes.kernel-module]
123+
title = "Kernel Module"
124+
description = """\
125+
Talos now supports optionally disabling kernel module signature verification by setting `module.sig_enforce=0` kernel parameter.
126+
By default module signature verification is enabled (`module.sig_enforce=1`).
127+
When using Factory or Imager supply as `-module.sig_enfore module.sig_enforce=0` kernel parameters to disable module signature enforcement.
128+
"""
129+
122130
[make_deps]
123131

124132
[make_deps.tools]

internal/app/machined/pkg/controllers/runtime/security_state.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"github.com/cosi-project/runtime/pkg/safe"
2222
"github.com/cosi-project/runtime/pkg/state"
2323
"github.com/foxboron/go-uefi/efi"
24+
"github.com/siderolabs/go-procfs/procfs"
2425
"go.uber.org/zap"
2526

2627
machineruntime "github.com/siderolabs/talos/internal/app/machined/pkg/runtime"
@@ -65,7 +66,7 @@ func (ctrl *SecurityStateController) Outputs() []controller.Output {
6566

6667
// Run implements controller.Controller interface.
6768
//
68-
//nolint:gocyclo
69+
//nolint:gocyclo,cyclop
6970
func (ctrl *SecurityStateController) Run(ctx context.Context, r controller.Runtime, _ *zap.Logger) error {
7071
for {
7172
select {
@@ -87,6 +88,7 @@ func (ctrl *SecurityStateController) Run(ctx context.Context, r controller.Runti
8788
var (
8889
secureBootState bool
8990
bootedWithUKI bool
91+
moduleSignatureEnforced bool
9092
pcrSigningKeyFingerprint string
9193
)
9294

@@ -133,6 +135,11 @@ func (ctrl *SecurityStateController) Run(ctx context.Context, r controller.Runti
133135
return fmt.Errorf("failed to get SELinux state: %w", err)
134136
}
135137

138+
moduleSignatureEnforcedInfo := procfs.ProcCmdline().Get(constants.KernelParamEnforceModuleSigVerify).First()
139+
if moduleSignatureEnforcedInfo != nil && *moduleSignatureEnforcedInfo == "1" {
140+
moduleSignatureEnforced = true
141+
}
142+
136143
fipsState := runtimeres.FIPSStateDisabled
137144

138145
if fipsmode.Enabled() {
@@ -149,6 +156,7 @@ func (ctrl *SecurityStateController) Run(ctx context.Context, r controller.Runti
149156
state.TypedSpec().SELinuxState = selinuxState
150157
state.TypedSpec().FIPSState = fipsState
151158
state.TypedSpec().BootedWithUKI = bootedWithUKI
159+
state.TypedSpec().ModuleSignatureEnforced = moduleSignatureEnforced
152160

153161
return nil
154162
}); err != nil {
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// This Source Code Form is subject to the terms of the Mozilla Public
2+
// License, v. 2.0. If a copy of the MPL was not distributed with this
3+
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
4+
5+
//go:build integration_api
6+
7+
package api
8+
9+
import (
10+
"context"
11+
"time"
12+
13+
"github.com/cosi-project/runtime/pkg/resource"
14+
"github.com/cosi-project/runtime/pkg/resource/rtestutils"
15+
"github.com/stretchr/testify/assert"
16+
17+
"github.com/siderolabs/talos/internal/integration/base"
18+
"github.com/siderolabs/talos/pkg/machinery/client"
19+
runtimeres "github.com/siderolabs/talos/pkg/machinery/resources/runtime"
20+
)
21+
22+
// SecuritySuite verifies the security state resource.
23+
type SecuritySuite struct {
24+
base.APISuite
25+
26+
ctx context.Context //nolint:containedctx
27+
ctxCancel context.CancelFunc
28+
}
29+
30+
// SuiteName returns the name of the suite.
31+
func (suite *SecuritySuite) SuiteName() string {
32+
return "api.SecuritySuite"
33+
}
34+
35+
// SetupTest sets up the test.
36+
func (suite *SecuritySuite) SetupTest() {
37+
// make sure API calls have timeout
38+
suite.ctx, suite.ctxCancel = context.WithTimeout(context.Background(), 1*time.Minute)
39+
40+
if suite.Cluster == nil || suite.Cluster.Provisioner() != base.ProvisionerQEMU {
41+
suite.T().Skip("skipping Security test since provisioner is not qemu")
42+
}
43+
}
44+
45+
// TearDownTest tears down the test.
46+
func (suite *SecuritySuite) TearDownTest() {
47+
if suite.ctxCancel != nil {
48+
suite.ctxCancel()
49+
}
50+
}
51+
52+
// TestSecurityState verifies that the security state resource is present and has valid values.
53+
func (suite *SecuritySuite) TestSecurityState() {
54+
node := suite.RandomDiscoveredNodeInternalIP()
55+
ctx := client.WithNode(suite.ctx, node)
56+
57+
rtestutils.AssertResources(ctx, suite.T(), suite.Client.COSI, []resource.ID{runtimeres.SecurityStateID},
58+
func(r *runtimeres.SecurityState, asrt *assert.Assertions) {
59+
asrt.True(r.TypedSpec().ModuleSignatureEnforced, "module signature enforcement should be enabled")
60+
},
61+
)
62+
}
63+
64+
func init() {
65+
allSuites = append(allSuites, &SecuritySuite{})
66+
}

internal/pkg/install/install.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ func RunInstallerContainer(
160160
constants.KernelParamAuditdDisabled,
161161
constants.KernelParamDashboardDisabled,
162162
constants.KernelParamNetIfnames,
163+
constants.KernelParamEnforceModuleSigVerify,
163164
} {
164165
if c := procfs.ProcCmdline().Get(preservedArg).First(); c != nil {
165166
args = append(args, "--extra-kernel-arg", fmt.Sprintf("%s=%s", preservedArg, *c))

pkg/machinery/api/resource/definitions/runtime/runtime.pb.go

Lines changed: 11 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/machinery/api/resource/definitions/runtime/runtime_vtproto.pb.go

Lines changed: 33 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/machinery/constants/constants.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,10 @@ const (
159159
// This param is injected by Equinix Metal and depends on the device ID and datacenter.
160160
KernelParamEquinixMetalEvents = "em.events_url"
161161

162+
// KernelParamEnforceModuleSigVerify is the kernel parameter name to specify module signature verification enforcement.
163+
// see https://github.com/siderolabs/talos/issues/11989
164+
KernelParamEnforceModuleSigVerify = "module.sig_enforce"
165+
162166
// NewRoot is the path where the switchroot target is mounted.
163167
NewRoot = "/root"
164168

pkg/machinery/imager/quirks/quirks.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,3 +286,15 @@ func (q Quirks) SupportsEmbeddedConfig() bool {
286286

287287
return q.v.GTE(minTalosVersionEmbeddedConfig)
288288
}
289+
290+
var minTalosVersionDisableModSigVerify = semver.MustParse("1.12.0")
291+
292+
// SupportsDisablingModuleSignatureVerification returns true if the Talos version supports disabling module signature verification.
293+
func (q Quirks) SupportsDisablingModuleSignatureVerification() bool {
294+
// if the version doesn't parse, we assume it's latest Talos
295+
if q.v == nil {
296+
return true
297+
}
298+
299+
return q.v.GTE(minTalosVersionDisableModSigVerify)
300+
}

pkg/machinery/kernel/kernel.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ func DefaultArgs(quirks quirks.Quirks) []string {
4848
result = append(result, constants.KernelParamSELinux+"=1")
4949
}
5050

51+
if quirks.SupportsDisablingModuleSignatureVerification() {
52+
result = append(result, constants.KernelParamEnforceModuleSigVerify+"=1") // see https://github.com/siderolabs/talos/issues/11989
53+
}
54+
5155
return result
5256
}
5357

0 commit comments

Comments
 (0)