cos-gpu-installer: remove code of modifying kernel command line
As discussed, cos-gpu-installer won't be responsible of
modifying kernel command line. It's caller's responsibility to make sure
kernel command line is configured correctly.
Besides, correct a few errors in the code.
1) fix some compiling error
2) fix a bug that environment variables were not set if toolchain was
preloaded.
3) fix a bug that the error of first calling Nvidia installer should not
be checked.
Change-Id: I18cc451da12d14178f5df59743db4df01daedfb5
diff --git a/src/cmd/cos_gpu_installer/internal/commands/install.go b/src/cmd/cos_gpu_installer/internal/commands/install.go
index 75a988c..2ef3611 100644
--- a/src/cmd/cos_gpu_installer/internal/commands/install.go
+++ b/src/cmd/cos_gpu_installer/internal/commands/install.go
@@ -3,6 +3,8 @@
import (
"context"
+ "fmt"
+ "io/ioutil"
"path/filepath"
"flag"
@@ -28,7 +30,7 @@
type InstallCommand struct {
driverVersion string
hostInstallDir string
- enforceSigning bool
+ unsignedDriver bool
internalDownload bool
debug bool
}
@@ -48,8 +50,10 @@
"The GPU driver verion to install. It will install the default GPU driver if the flag is not set explicitly.")
f.StringVar(&c.hostInstallDir, "dir", "/var/lib/nvidia",
"Host directory that GPU drivers should be installed to")
- f.BoolVar(&c.enforceSigning, "enforce-signing", true,
- "Whether to enforce GPU drivers being signed. Setting to false will disable kernel module signing security feature.")
+ f.BoolVar(&c.unsignedDriver, "allow-unsigned-driver", false,
+ "Whether to allow load unsigned GPU drivers. "+
+ "If this flag is set to true, module signing security features must be disabled on the host for driver installation to succeed. "+
+ "This flag is only for debugging.")
// TODO(mikewu): change this flag to a bucket prefix string.
f.BoolVar(&c.internalDownload, "internal-download", false,
"Whether to try to download files from Google internal server. This is only useful for internal developing.")
@@ -67,7 +71,7 @@
log.Infof("Running on COS build id %s", envReader.BuildNumber())
- downloader := &cos.GCSDownloader{envReader, c.internalDownload}
+ downloader := cos.NewGCSDownloader(envReader, c.internalDownload)
if c.driverVersion == "" {
defaultVersion, err := installer.GetDefaultGPUDriverVersion(downloader)
if err != nil {
@@ -78,19 +82,20 @@
}
log.Infof("Installing GPU driver version %s", c.driverVersion)
- if !c.enforceSigning {
- log.Info("Doesn't enforce signing. Need to disable module locking.")
- if err := cos.DisableKernelModuleLocking(); err != nil {
- c.logError(errors.Wrap(err, "failed to configure kernel module locking"))
- return subcommands.ExitFailure
+ if c.unsignedDriver {
+ kernelCmdline, err := ioutil.ReadFile("/proc/cmdline")
+ if err != nil {
+ c.logError(fmt.Errorf("failed to read kernel command line: %v", err))
+ }
+ if !cos.CheckKernelModuleSigning(string(kernelCmdline)) {
+ log.Warning("Current kernel command line does not support unsigned kernel modules. Not enforcing kernel module signing may cause installation fail.")
}
}
-
hostInstallDir := filepath.Join(hostRootPath, c.hostInstallDir)
cacher := installer.NewCacher(hostInstallDir, envReader.BuildNumber(), c.driverVersion)
if isCached, err := cacher.IsCached(); isCached && err == nil {
log.Info("Found cached version, NOT building the drivers.")
- if err := installer.ConfigureCachedInstalltion(hostInstallDir, c.enforceSigning); err != nil {
+ if err := installer.ConfigureCachedInstalltion(hostInstallDir, !c.unsignedDriver); err != nil {
c.logError(errors.Wrap(err, "failed to configure cached installation"))
return subcommands.ExitFailure
}
@@ -121,7 +126,7 @@
}
defer func() { callback <- 0 }()
- if c.enforceSigning {
+ if !c.unsignedDriver {
if err := signing.DownloadDriverSignatures(downloader, c.driverVersion); err != nil {
return errors.Wrap(err, "failed to download driver signature")
}
@@ -140,7 +145,7 @@
return errors.Wrap(err, "failed to install toolchain")
}
- if err := installer.RunDriverInstaller(installerFile, c.enforceSigning); err != nil {
+ if err := installer.RunDriverInstaller(installerFile, !c.unsignedDriver); err != nil {
return errors.Wrap(err, "failed to run GPU driver installer")
}
if err := cacher.Cache(); err != nil {
diff --git a/src/cmd/cos_gpu_installer/internal/commands/list.go b/src/cmd/cos_gpu_installer/internal/commands/list.go
index 63ec447..4b4e095 100644
--- a/src/cmd/cos_gpu_installer/internal/commands/list.go
+++ b/src/cmd/cos_gpu_installer/internal/commands/list.go
@@ -47,7 +47,7 @@
return subcommands.ExitFailure
}
log.Infof("Running on COS build id %s", envReader.BuildNumber())
- downloader := &cos.GCSDownloader{envReader, c.internalDownload}
+ downloader := cos.NewGCSDownloader(envReader, c.internalDownload)
artifacts, err := downloader.ListExtensionArtifacts("gpu")
if err != nil {
c.logError(errors.Wrap(err, "failed to list gpu extension artifacts"))
diff --git a/src/cmd/cos_gpu_installer/internal/installer/installer.go b/src/cmd/cos_gpu_installer/internal/installer/installer.go
index 0b8d6b4..654240c 100644
--- a/src/cmd/cos_gpu_installer/internal/installer/installer.go
+++ b/src/cmd/cos_gpu_installer/internal/installer/installer.go
@@ -22,7 +22,7 @@
const (
gpuInstallDirContainer = "/usr/local/nvidia"
- defaultGPUDriverFile = "default_version"
+ defaultGPUDriverFile = "gpu_default_version"
precompiledInstallerURLFormat = "https://storage.googleapis.com/nvidia-drivers-%s-public/nvidia-cos-project/%s/tesla/%s_00/%s/NVIDIA-Linux-x86_64-%s_%s-%s.cos"
defaultFilePermission = 0755
)
@@ -140,9 +140,8 @@
if needSigned {
// Run installer to compile drivers. Expect the command to fail as the drivers are not signed yet.
- if err := utils.RunCommandAndLogOutput(cmd, true); err != nil {
- return errors.Wrap(err, "failed to run GPU driver installer")
- }
+ utils.RunCommandAndLogOutput(cmd, true)
+
// sign GPU drivers.
kernelFiles, err := ioutil.ReadDir(filepath.Join(extractDir, "kernel"))
if err != nil {
@@ -184,9 +183,9 @@
}
// GetDefaultGPUDriverVersion gets the default GPU driver version.
-func GetDefaultGPUDriverVersion(downloader cos.ExtensionsDownloader) (string, error) {
+func GetDefaultGPUDriverVersion(downloader cos.ArtifactsDownloader) (string, error) {
log.Info("Getting the default GPU driver version")
- content, err := downloader.GetExtensionArtifact(cos.GpuExtension, defaultGPUDriverFile)
+ content, err := downloader.GetArtifact(defaultGPUDriverFile)
if err != nil {
return "", errors.Wrapf(err, "failed to get default GPU driver version")
}
diff --git a/src/pkg/cos/artifacts.go b/src/pkg/cos/artifacts.go
index 616778e..bb2f0bb 100644
--- a/src/pkg/cos/artifacts.go
+++ b/src/pkg/cos/artifacts.go
@@ -42,6 +42,11 @@
Internal bool
}
+// NewGCSDownloader creates a GCSDownloader instance.
+func NewGCSDownloader(e *EnvReader, i bool) *GCSDownloader {
+ return &GCSDownloader{e, i}
+}
+
// DownloadKernelSrc downloads COS kernel sources to destination directory.
func (d *GCSDownloader) DownloadKernelSrc(destDir string) error {
return d.DownloadArtifact(destDir, kernelSrcArchive)
diff --git a/src/pkg/cos/cos.go b/src/pkg/cos/cos.go
index c431c00..c75f7c5 100644
--- a/src/pkg/cos/cos.go
+++ b/src/pkg/cos/cos.go
@@ -8,7 +8,6 @@
"os/exec"
"path/filepath"
"strings"
- "syscall"
"cos.googlesource.com/cos/tools/src/pkg/utils"
@@ -25,63 +24,20 @@
execCommand = exec.Command
)
-// DisableKernelModuleLocking disables kernel modules signing enforcement and loadpin so that unsigned kernel modules
-// can be loaded to COS kernel.
-func DisableKernelModuleLocking() error {
- log.Info("Checking if third party kernel modules can be installed")
+// CheckKernelModuleSigning checks whether kernel module signing related options present.
+func CheckKernelModuleSigning(kernelCmdline string) bool {
+ log.Info("Checking kernel module signing.")
- mountDir, err := ioutil.TempDir("", "mountdir")
- if err != nil {
- return errors.Wrap(err, "failed to create mount dir")
- }
-
- if err := syscall.Mount(espPartition, mountDir, "vfat", 0, ""); err != nil {
- return errors.Wrap(err, "failed to mount path")
- }
-
- grubCfgPath := filepath.Join(mountDir, "esp/efi/boot/grub.cfg")
- grubCfg, err := ioutil.ReadFile(grubCfgPath)
- if err != nil {
- return errors.Wrapf(err, "failed to read grub config from %s", grubCfgPath)
- }
-
- grubCfgStr := string(grubCfg)
- needReboot := false
for _, kernelOption := range []string{
- "module.sig_enforce",
- "loadpin.enforce",
- "loadpin.enabled",
+ "loadpin.exclude=kernel-module",
+ "modules-load=loadpin_trigger",
+ "module.sig_enforce=1",
} {
- if newGrubCfgStr, needRebootOption := disableKernelOptionFromGrubCfg(kernelOption, grubCfgStr); needRebootOption {
- needReboot = true
- grubCfgStr = newGrubCfgStr
+ if !strings.Contains(kernelCmdline, kernelOption) {
+ return false
}
}
-
- if needReboot {
- log.Info("Modifying grub config to disable module locking.")
- if err := os.Rename(grubCfgPath, grubCfgPath+".orig"); err != nil {
- return errors.Wrapf(err, "failed to rename file %s", grubCfgPath)
- }
- if err := ioutil.WriteFile(grubCfgPath, []byte(grubCfgStr), 0644); err != nil {
- return errors.Wrapf(err, "failed to write to file %s", grubCfgPath)
- }
- } else {
- log.Info("Module locking has been disabled.")
- }
-
- syscall.Sync()
- if err := syscall.Unmount(mountDir, 0); err != nil {
- return err
- }
-
- if needReboot {
- log.Warning("Rebooting")
- if err := syscall.Reboot(syscall.LINUX_REBOOT_CMD_RESTART); err != nil {
- return errors.Wrap(err, "failed to reboot")
- }
- }
- return nil
+ return true
}
// SetCompilationEnv sets compilation environment variables (e.g. CC, CXX) for third-party kernel module compilation.
@@ -119,15 +75,14 @@
}
if empty, _ := utils.IsDirEmpty(destDir); !empty {
log.Info("Found existing toolchain. Skipping download and installation")
- return nil
- }
+ } else {
+ if err := downloader.DownloadToolchain(destDir); err != nil {
+ return errors.Wrap(err, "failed to download toolchain")
+ }
- if err := downloader.DownloadToolchain(destDir); err != nil {
- return errors.Wrap(err, "failed to download toolchain")
- }
-
- if err := exec.Command("tar", "xf", filepath.Join(destDir, toolchainArchive), "-C", destDir).Run(); err != nil {
- return errors.Wrap(err, "failed to extract toolchain archive tarball")
+ if err := exec.Command("tar", "xf", filepath.Join(destDir, toolchainArchive), "-C", destDir).Run(); err != nil {
+ return errors.Wrap(err, "failed to extract toolchain archive tarball")
+ }
}
log.Info("Configuring environment variables for cross-compilation")
diff --git a/src/pkg/cos/cos_test.go b/src/pkg/cos/cos_test.go
index f031491..e28ac2b 100644
--- a/src/pkg/cos/cos_test.go
+++ b/src/pkg/cos/cos_test.go
@@ -207,55 +207,65 @@
func TestDisableKernelOptionFromGrubCfg(t *testing.T) {
for _, tc := range []struct {
- testName string
- kernelOption string
- grubCfg string
- expectedNewGrubCfg string
- expectedNeedReboot bool
+ testName string
+ kernelCmdLine string
+ expectedReturn bool
}{
{
- "LoadPin",
- "loadpin.enabled",
-
- `BOOT_IMAGE=/syslinux/vmlinuz.A init=/usr/lib/systemd/systemd boot=local rootwait ro noresume noswap ` +
- `loglevel=7 noinitrd console=ttyS0 security=apparmor virtio_net.napi_tx=1 ` +
- `systemd.unified_cgroup_hierarchy=false systemd.legacy_systemd_cgroup_controller=false csm.disabled=1 ` +
- `dm_verity.error_behavior=3 dm_verity.max_bios=-1 dm_verity.dev_wait=1 i915.modeset=1 cros_efi root=/dev/dm-0 ` +
- `"dm=1 vroot none ro 1,0 2539520 verity payload=PARTUUID=36547742-9356-EF4E-B9AD-F8DED2F6D087 ` +
- `hashtree=PARTUUID=36547742-9356-EF4E-B9AD-F8DED2F6D087 hashstart=2539520 alg=sha256 ` +
- `root_hexdigest=0ff80250bd97ad47a65e7cd330ab70bcf5013d7a86817dca59fcac77f0ba1a8f ` +
- `salt=414038a6ed9b1f528c327aff4eac16ad5ca4a6699d142ae096e90374af907c34`,
-
- `BOOT_IMAGE=/syslinux/vmlinuz.A init=/usr/lib/systemd/systemd boot=local rootwait ro noresume noswap ` +
- `loglevel=7 noinitrd console=ttyS0 security=apparmor virtio_net.napi_tx=1 ` +
- `systemd.unified_cgroup_hierarchy=false systemd.legacy_systemd_cgroup_controller=false csm.disabled=1 ` +
- `dm_verity.error_behavior=3 dm_verity.max_bios=-1 dm_verity.dev_wait=1 i915.modeset=1 cros_efi loadpin.enabled=0 root=/dev/dm-0 ` +
- `"dm=1 vroot none ro 1,0 2539520 verity payload=PARTUUID=36547742-9356-EF4E-B9AD-F8DED2F6D087 ` +
- `hashtree=PARTUUID=36547742-9356-EF4E-B9AD-F8DED2F6D087 hashstart=2539520 alg=sha256 ` +
- `root_hexdigest=0ff80250bd97ad47a65e7cd330ab70bcf5013d7a86817dca59fcac77f0ba1a8f ` +
- `salt=414038a6ed9b1f528c327aff4eac16ad5ca4a6699d142ae096e90374af907c34`,
- true,
+ testName: "OptionsPresent",
+ kernelCmdLine: `BOOT_IMAGE=/syslinux/vmlinuz.A init=/usr/lib/systemd/systemd boot=local rootwait ro noresume noswap loglevel=7 ` +
+ `noinitrd console=ttyS0 security=apparmor virtio_net.napi_tx=1 systemd.unified_cgroup_hierarchy=false ` +
+ `systemd.legacy_systemd_cgroup_controller=false csm.disabled=1 dm_verity.error_behavior=3 dm_verity.max_bios=-1 ` +
+ `dm_verity.dev_wait=1 i915.modeset=1 cros_efi module.sig_enforce=1 modules-load=loadpin_trigger ` +
+ `loadpin.exclude=kernel-module root=/dev/dm-0 "dm=1 vroot none ro 1,0 4077568 verity ` +
+ `payload=PARTUUID=00CE255B-DB42-1E47-A62B-735C7A9A7397 hashtree=PARTUUID=00CE255B-DB42-1E47-A62B-735C7A9A7397 ` +
+ `hashstart=4077568 alg=sha256 root_hexdigest=8a2cfc7097aa7ddfe4101611fad9dd1df59f9c29cfa9b1a5d18f55ae68c9eed5 ` +
+ `salt=65697f247db9275b9e9830d275ca6b830c156187403f6210b2ebcb11c8beaa57"`,
+ expectedReturn: true,
},
{
- "LoadPinEnabled",
- "loadpin.enabled",
- "cros_efi loadpin.enabled=1",
- "cros_efi loadpin.enabled=0",
- true,
+ testName: "MissingLoadpinExclude",
+ kernelCmdLine: `BOOT_IMAGE=/syslinux/vmlinuz.A init=/usr/lib/systemd/systemd boot=local rootwait ro noresume noswap loglevel=7 ` +
+ `noinitrd console=ttyS0 security=apparmor virtio_net.napi_tx=1 systemd.unified_cgroup_hierarchy=false ` +
+ `systemd.legacy_systemd_cgroup_controller=false csm.disabled=1 dm_verity.error_behavior=3 dm_verity.max_bios=-1 ` +
+ `dm_verity.dev_wait=1 i915.modeset=1 cros_efi module.sig_enforce=1 modules-load=loadpin_trigger ` +
+ `root=/dev/dm-0 "dm=1 vroot none ro 1,0 4077568 verity ` +
+ `payload=PARTUUID=00CE255B-DB42-1E47-A62B-735C7A9A7397 hashtree=PARTUUID=00CE255B-DB42-1E47-A62B-735C7A9A7397 ` +
+ `hashstart=4077568 alg=sha256 root_hexdigest=8a2cfc7097aa7ddfe4101611fad9dd1df59f9c29cfa9b1a5d18f55ae68c9eed5 ` +
+ `salt=65697f247db9275b9e9830d275ca6b830c156187403f6210b2ebcb11c8beaa57"`,
+ expectedReturn: false,
},
{
- "LoadPinDisabled",
- "loadpin.enabled",
- "cros_efi loadpin.enabled=0",
- "cros_efi loadpin.enabled=0",
- false,
+ testName: "MissingLoadpinTrigger",
+ kernelCmdLine: `BOOT_IMAGE=/syslinux/vmlinuz.A init=/usr/lib/systemd/systemd boot=local rootwait ro noresume noswap loglevel=7 ` +
+ `noinitrd console=ttyS0 security=apparmor virtio_net.napi_tx=1 systemd.unified_cgroup_hierarchy=false ` +
+ `systemd.legacy_systemd_cgroup_controller=false csm.disabled=1 dm_verity.error_behavior=3 dm_verity.max_bios=-1 ` +
+ `dm_verity.dev_wait=1 i915.modeset=1 cros_efi module.sig_enforce=1 ` +
+ `loadpin.exclude=kernel-module root=/dev/dm-0 "dm=1 vroot none ro 1,0 4077568 verity ` +
+ `payload=PARTUUID=00CE255B-DB42-1E47-A62B-735C7A9A7397 hashtree=PARTUUID=00CE255B-DB42-1E47-A62B-735C7A9A7397 ` +
+ `hashstart=4077568 alg=sha256 root_hexdigest=8a2cfc7097aa7ddfe4101611fad9dd1df59f9c29cfa9b1a5d18f55ae68c9eed5 ` +
+ `salt=65697f247db9275b9e9830d275ca6b830c156187403f6210b2ebcb11c8beaa57"`,
+ expectedReturn: false,
+ },
+ {
+ testName: "MissingSigEnforce",
+ kernelCmdLine: `BOOT_IMAGE=/syslinux/vmlinuz.A init=/usr/lib/systemd/systemd boot=local rootwait ro noresume noswap loglevel=7 ` +
+ `noinitrd console=ttyS0 security=apparmor virtio_net.napi_tx=1 systemd.unified_cgroup_hierarchy=false ` +
+ `systemd.legacy_systemd_cgroup_controller=false csm.disabled=1 dm_verity.error_behavior=3 dm_verity.max_bios=-1 ` +
+ `dm_verity.dev_wait=1 i915.modeset=1 cros_efi modules-load=loadpin_trigger ` +
+ `loadpin.exclude=kernel-module root=/dev/dm-0 "dm=1 vroot none ro 1,0 4077568 verity ` +
+ `payload=PARTUUID=00CE255B-DB42-1E47-A62B-735C7A9A7397 hashtree=PARTUUID=00CE255B-DB42-1E47-A62B-735C7A9A7397 ` +
+ `hashstart=4077568 alg=sha256 root_hexdigest=8a2cfc7097aa7ddfe4101611fad9dd1df59f9c29cfa9b1a5d18f55ae68c9eed5 ` +
+ `salt=65697f247db9275b9e9830d275ca6b830c156187403f6210b2ebcb11c8beaa57"`,
+ expectedReturn: false,
},
} {
- newGrubCfg, needReboot := disableKernelOptionFromGrubCfg(tc.kernelOption, tc.grubCfg)
- if newGrubCfg != tc.expectedNewGrubCfg || needReboot != tc.expectedNeedReboot {
- t.Errorf("%v: Unexpected output:\nexpect grubcfg: %v\ngot grubcfg: %v\nexpect needReboot: %v, got needReboot: %v",
- tc.testName, tc.expectedNewGrubCfg, newGrubCfg, tc.expectedNeedReboot, needReboot)
- }
+ t.Run(tc.testName, func(t *testing.T) {
+ ret := CheckKernelModuleSigning(tc.kernelCmdLine)
+ if ret != tc.expectedReturn {
+ t.Errorf("Unexpected output:%v, expect: %v", ret, tc.expectedReturn)
+ }
+ })
}
}