Skip to content

Commit 9e5289e

Browse files
vinceaperriCopilot
andcommitted
fix: Defer to /etc/selinux/config when parameters are not present in azl4
Co-authored-by: Copilot <copilot@github.com>
1 parent 7307ea4 commit 9e5289e

7 files changed

Lines changed: 76 additions & 4 deletions

File tree

toolkit/tools/pkg/imagecustomizerlib/bootcustomizer.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ func (b *BootCustomizer) getSELinuxModeFromCmdline(buildDir string, imageChroot
197197
}
198198

199199
// Get the SELinux mode from the kernel command-line args.
200-
selinuxMode, err := getSELinuxModeFromLinuxArgs(args)
200+
selinuxMode, err := b.distroHandler.GetSELinuxModeFromLinuxArgs(args)
201201
if err != nil {
202202
return imagecustomizerapi.SELinuxModeDefault, false, err
203203
}

toolkit/tools/pkg/imagecustomizerlib/bootcustomizer_test.go

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,12 @@ func TestBootCustomizerSELinuxMode40(t *testing.T) {
185185
err = b.UpdateSELinuxCommandLine(imagecustomizerapi.SELinuxModeDisabled)
186186
assert.NoError(t, err)
187187

188+
// Explicit selinux=0 must read back as Disabled (not Default).
189+
selinuxMode, found, err = b.getSELinuxModeFromCmdline("", nil)
190+
assert.NoError(t, err)
191+
assert.True(t, found)
192+
assert.Equal(t, imagecustomizerapi.SELinuxModeDisabled, selinuxMode)
193+
188194
expectedDefaultGrubFileDiff := `7a8
189195
> GRUB_CMDLINE_LINUX=" selinux=0 "
190196
`
@@ -193,6 +199,12 @@ func TestBootCustomizerSELinuxMode40(t *testing.T) {
193199
err = b.UpdateSELinuxCommandLine(imagecustomizerapi.SELinuxModePermissive)
194200
assert.NoError(t, err)
195201

202+
// "security=selinux selinux=1" without enforcing=1 means the kernel defers to /etc/selinux/config.
203+
selinuxMode, found, err = b.getSELinuxModeFromCmdline("", nil)
204+
assert.NoError(t, err)
205+
assert.True(t, found)
206+
assert.Equal(t, imagecustomizerapi.SELinuxModeDefault, selinuxMode)
207+
196208
expectedDefaultGrubFileDiff = `7a8
197209
> GRUB_CMDLINE_LINUX=" security=selinux selinux=1 "
198210
`
@@ -201,6 +213,12 @@ func TestBootCustomizerSELinuxMode40(t *testing.T) {
201213
err = b.UpdateSELinuxCommandLine(imagecustomizerapi.SELinuxModeForceEnforcing)
202214
assert.NoError(t, err)
203215

216+
// enforcing=1 alongside the security/selinux pair locks the mode to enforcing.
217+
selinuxMode, found, err = b.getSELinuxModeFromCmdline("", nil)
218+
assert.NoError(t, err)
219+
assert.True(t, found)
220+
assert.Equal(t, imagecustomizerapi.SELinuxModeForceEnforcing, selinuxMode)
221+
204222
expectedDefaultGrubFileDiff = `7a8
205223
> GRUB_CMDLINE_LINUX=" security=selinux selinux=1 enforcing=1 "
206224
`
@@ -290,20 +308,21 @@ func calcDiff(t *testing.T, oldPath string, newContent string) string {
290308

291309
func createBootCustomizerFor20(t *testing.T) *BootCustomizer {
292310
return createBootCustomizer(t, filepath.Join(testDir, sampleGrubCfg20Path),
293-
filepath.Join(testDir, sampleDefaultGrub20Path), false)
311+
filepath.Join(testDir, sampleDefaultGrub20Path), false, newAzureLinuxDistroHandler("2.0"))
294312
}
295313

296314
func createBootCustomizerFor30(t *testing.T) *BootCustomizer {
297315
return createBootCustomizer(t, filepath.Join(testDir, sampleGrubCfg30Path),
298-
filepath.Join(testDir, sampleDefaultGrub30Path), true)
316+
filepath.Join(testDir, sampleDefaultGrub30Path), true, newAzureLinuxDistroHandler("3.0"))
299317
}
300318

301319
func createBootCustomizerFor40(t *testing.T) *BootCustomizer {
302320
return createBootCustomizer(t, filepath.Join(testDir, sampleGrubCfg40Path),
303-
filepath.Join(testDir, sampleDefaultGrub40Path), true)
321+
filepath.Join(testDir, sampleDefaultGrub40Path), true, newAzureLinuxDistroHandler("4.0"))
304322
}
305323

306324
func createBootCustomizer(t *testing.T, sampleGrubCfgPath string, sampleDefaultGrubFilePath string, isGrubMkconfig bool,
325+
distroHandler DistroHandler,
307326
) *BootCustomizer {
308327
sampleGrubCfgContent, err := os.ReadFile(sampleGrubCfgPath)
309328
assert.NoError(t, err, "failed to read sample grub.cfg file")
@@ -320,6 +339,7 @@ func createBootCustomizer(t *testing.T, sampleGrubCfgPath string, sampleDefaultG
320339
grubCfgContent: string(sampleGrubCfgContent),
321340
defaultGrubFileContent: string(sampleDefaultGrubFileContent),
322341
bootConfigType: bootConfigType,
342+
distroHandler: distroHandler,
323343
}
324344
return b
325345
}

toolkit/tools/pkg/imagecustomizerlib/distrohandler.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,12 @@ type DistroHandler interface {
5555
// Reports whether SELinux configuration is supported by the tool for this distro.
5656
SELinuxSupported() bool
5757

58+
// GetSELinuxModeFromLinuxArgs interprets parsed kernel command-line args and returns the effective SELinux mode
59+
// the kernel will boot with. Returns SELinuxModeDefault to indicate the caller should fall back to reading
60+
// /etc/selinux/config. Distros differ in how to interpret the absence of any SELinux args (e.g. legacy Azure
61+
// Linux 2.0/3.0 treat missing args as Disabled, while Azure Linux 4.0 defer to the config file).
62+
GetSELinuxModeFromLinuxArgs(args []grubConfigLinuxArg) (imagecustomizerapi.SELinuxMode, error)
63+
5864
// ReadGrub2ConfigFile reads the distro-appropriate grub.cfg file from the chroot.
5965
ReadGrub2ConfigFile(imageChroot safechroot.ChrootInterface) (string, error)
6066

toolkit/tools/pkg/imagecustomizerlib/distrohandler_azurelinux.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,19 @@ func (d *azureLinuxDistroHandler) SELinuxSupported() bool {
108108
return true
109109
}
110110

111+
// GetSELinuxModeFromLinuxArgs interprets parsed kernel command-line args.
112+
// Azure Linux 2.0/3.0 historically treat missing SELinux cmdline args as disabled (their kernels do not honor
113+
// /etc/selinux/config without cmdline args). Azure Linux 4.0 honors /etc/selinux/config when no SELinux cmdline
114+
// args are present, so it must defer instead of returning Disabled.
115+
func (d *azureLinuxDistroHandler) GetSELinuxModeFromLinuxArgs(args []grubConfigLinuxArg,
116+
) (imagecustomizerapi.SELinuxMode, error) {
117+
if d.version == "4.0" {
118+
return getSELinuxModeFromLinuxArgsDeferIfMissing(args)
119+
}
120+
121+
return getSELinuxModeFromLinuxArgs(args)
122+
}
123+
111124
func (d *azureLinuxDistroHandler) ReadGrub2ConfigFile(imageChroot safechroot.ChrootInterface) (string, error) {
112125
return readGrub2ConfigFile(imageChroot, installutils.FedoraGrubCfgFile)
113126
}

toolkit/tools/pkg/imagecustomizerlib/distrohandler_fedora.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,11 @@ func (d *fedoraDistroHandler) SELinuxSupported() bool {
9393
return true
9494
}
9595

96+
func (d *fedoraDistroHandler) GetSELinuxModeFromLinuxArgs(args []grubConfigLinuxArg,
97+
) (imagecustomizerapi.SELinuxMode, error) {
98+
return getSELinuxModeFromLinuxArgsDeferIfMissing(args)
99+
}
100+
96101
func (d *fedoraDistroHandler) ReadGrub2ConfigFile(imageChroot safechroot.ChrootInterface) (string, error) {
97102
return readGrub2ConfigFile(imageChroot, installutils.FedoraGrubCfgFile)
98103
}

toolkit/tools/pkg/imagecustomizerlib/distrohandler_ubuntu.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,11 @@ func (d *ubuntuDistroHandler) SELinuxSupported() bool {
114114
return false
115115
}
116116

117+
func (d *ubuntuDistroHandler) GetSELinuxModeFromLinuxArgs(args []grubConfigLinuxArg,
118+
) (imagecustomizerapi.SELinuxMode, error) {
119+
return getSELinuxModeFromLinuxArgsDeferIfMissing(args)
120+
}
121+
117122
func (d *ubuntuDistroHandler) ReadGrub2ConfigFile(imageChroot safechroot.ChrootInterface) (string, error) {
118123
return readGrub2ConfigFile(imageChroot, installutils.DebianGrubCfgFile)
119124
}

toolkit/tools/pkg/imagecustomizerlib/grubcfgutils.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -762,6 +762,29 @@ func getSELinuxModeFromLinuxArgs(args []grubConfigLinuxArg) (imagecustomizerapi.
762762
return imagecustomizerapi.SELinuxModeDefault, nil
763763
}
764764

765+
// getSELinuxModeFromLinuxArgsDeferIfMissing wraps getSELinuxModeFromLinuxArgs so that absent SELinux cmdline args
766+
// resolve to SELinuxModeDefault (defer to /etc/selinux/config) rather than SELinuxModeDisabled.
767+
//
768+
// Suitable for distros where the kernel honors /etc/selinux/config when no SELinux cmdline args are present
769+
// (e.g. Azure Linux 4.0, Fedora, Ubuntu). Legacy Azure Linux 2.0/3.0 must keep calling getSELinuxModeFromLinuxArgs
770+
// directly to preserve their historical "missing args == disabled" behavior.
771+
func getSELinuxModeFromLinuxArgsDeferIfMissing(args []grubConfigLinuxArg) (imagecustomizerapi.SELinuxMode, error) {
772+
mode, err := getSELinuxModeFromLinuxArgs(args)
773+
if err != nil || mode != imagecustomizerapi.SELinuxModeDisabled {
774+
return mode, err
775+
}
776+
777+
// Distinguish explicit selinux=0 (truly disabled) from missing args (defer to config file).
778+
selinuxValue, err := findKernelCommandLineArgValue(args, "selinux")
779+
if err != nil {
780+
return imagecustomizerapi.SELinuxModeDefault, err
781+
}
782+
if selinuxValue == "0" {
783+
return imagecustomizerapi.SELinuxModeDisabled, nil
784+
}
785+
return imagecustomizerapi.SELinuxModeDefault, nil
786+
}
787+
765788
// Gets the SELinux mode set by the /etc/selinux/config file.
766789
func getSELinuxModeFromConfigFile(imageChroot safechroot.ChrootInterface) (imagecustomizerapi.SELinuxMode, error) {
767790
selinuxConfigFilePath := filepath.Join(imageChroot.RootDir(), installutils.SELinuxConfigFile)

0 commit comments

Comments
 (0)