From 786ea01a646c4fa73d7c619935681cc4c6394f2c Mon Sep 17 00:00:00 2001 From: Brent Baude Date: Wed, 26 Jun 2024 15:22:30 -0500 Subject: [PATCH] Error when machine memory exceeds system memory Close loophole that would allow you to assign more memory than the system has to a podman machine Fixes: #18206 Signed-off-by: Brent Baude --- cmd/podman/machine/init.go | 21 +++++++++++++++++++++ cmd/podman/machine/set.go | 3 +++ pkg/machine/e2e/init_test.go | 14 +++++++++++++- pkg/machine/e2e/set_test.go | 5 +++++ 4 files changed, 42 insertions(+), 1 deletion(-) diff --git a/cmd/podman/machine/init.go b/cmd/podman/machine/init.go index bc3aac3dd3..7759304544 100644 --- a/cmd/podman/machine/init.go +++ b/cmd/podman/machine/init.go @@ -7,6 +7,7 @@ import ( "os" "github.com/containers/common/pkg/completion" + "github.com/containers/common/pkg/strongunits" "github.com/containers/podman/v5/cmd/podman/registry" ldefine "github.com/containers/podman/v5/libpod/define" "github.com/containers/podman/v5/libpod/events" @@ -14,6 +15,7 @@ import ( "github.com/containers/podman/v5/pkg/machine/define" "github.com/containers/podman/v5/pkg/machine/shim" "github.com/containers/podman/v5/pkg/machine/vmconfigs" + "github.com/shirou/gopsutil/v3/mem" "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -196,6 +198,12 @@ func initMachine(cmd *cobra.Command, args []string) error { initOpts.UserModeNetworking = &initOptionalFlags.UserModeNetworking } + if cmd.Flags().Changed("memory") { + if err := checkMaxMemory(strongunits.MiB(initOpts.Memory)); err != nil { + return err + } + } + // TODO need to work this back in // if finished, err := vm.Init(initOpts); err != nil || !finished { // // Finished = true, err = nil - Success! Log a message with further instructions @@ -226,3 +234,16 @@ func initMachine(cmd *cobra.Command, args []string) error { fmt.Printf("To start your machine run:\n\n\tpodman machine start%s\n\n", extra) return err } + +// checkMaxMemory gets the total system memory and compares it to the variable. if the variable +// is larger than the total memory, it returns an error +func checkMaxMemory(newMem strongunits.MiB) error { + memStat, err := mem.VirtualMemory() + if err != nil { + return err + } + if total := strongunits.B(memStat.Total); strongunits.B(memStat.Total) < newMem.ToBytes() { + return fmt.Errorf("requested amount of memory (%d MB) greater than total system memory (%d MB)", newMem, total) + } + return nil +} diff --git a/cmd/podman/machine/set.go b/cmd/podman/machine/set.go index e1c1072fa7..07736bd507 100644 --- a/cmd/podman/machine/set.go +++ b/cmd/podman/machine/set.go @@ -111,6 +111,9 @@ func setMachine(cmd *cobra.Command, args []string) error { } if cmd.Flags().Changed("memory") { newMemory := strongunits.MiB(setFlags.Memory) + if err := checkMaxMemory(newMemory); err != nil { + return err + } setOpts.Memory = &newMemory } if cmd.Flags().Changed("disk-size") { diff --git a/pkg/machine/e2e/init_test.go b/pkg/machine/e2e/init_test.go index 4b0d9df3ce..30e7b74f56 100644 --- a/pkg/machine/e2e/init_test.go +++ b/pkg/machine/e2e/init_test.go @@ -9,11 +9,13 @@ import ( "strings" "time" + "github.com/containers/common/pkg/strongunits" "github.com/containers/podman/v5/pkg/machine/define" "github.com/containers/podman/v5/utils" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" . "github.com/onsi/gomega/gexec" + "github.com/shirou/gopsutil/v3/mem" "github.com/sirupsen/logrus" ) @@ -35,7 +37,7 @@ var _ = Describe("podman machine init", func() { cpus = 1 } - It("bad init name", func() { + It("bad init", func() { i := initMachine{} reallyLongName := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" session, err := mb.setName(reallyLongName).setCmd(&i).run() @@ -77,6 +79,16 @@ var _ = Describe("podman machine init", func() { Expect(err).ToNot(HaveOccurred()) Expect(session).To(Exit(125)) Expect(session.errorToString()).To(ContainSubstring(`invalid username "-/a": names must match [a-zA-Z0-9][a-zA-Z0-9_.-]*: invalid argument`)) + + // this comes in bytes + memStat, err := mem.VirtualMemory() + Expect(err).ToNot(HaveOccurred()) + total := strongunits.ToMib(strongunits.B(memStat.Total)) + 1024 + + badMem := initMachine{} + badMemSession, err := mb.setCmd(badMem.withMemory(uint(total))).run() + Expect(err).ToNot(HaveOccurred()) + Expect(badMemSession).To(Exit(125)) }) It("simple init", func() { diff --git a/pkg/machine/e2e/set_test.go b/pkg/machine/e2e/set_test.go index f7b94b2e7c..04855c8cdf 100644 --- a/pkg/machine/e2e/set_test.go +++ b/pkg/machine/e2e/set_test.go @@ -33,6 +33,11 @@ var _ = Describe("podman machine set", func() { Expect(err).ToNot(HaveOccurred()) Expect(session).To(Exit(0)) + setMem := setMachine{} + SetMemSession, err := mb.setName(name).setCmd(setMem.withMemory(524288)).run() + Expect(err).ToNot(HaveOccurred()) + Expect(SetMemSession).To(Exit(125)) + set := setMachine{} setSession, err := mb.setName(name).setCmd(set.withCPUs(2).withDiskSize(102).withMemory(4096)).run() Expect(err).ToNot(HaveOccurred())