From cd08a85f705a7b67d516137686e16403ea808307 Mon Sep 17 00:00:00 2001 From: Cyril Zhang Date: Wed, 2 Jun 2021 12:45:04 -0700 Subject: [PATCH] Add racct limit option --- cmd/runj/create.go | 10 ++++++++ cmd/runj/delete.go | 4 +++ jail/limit.go | 57 +++++++++++++++++++++++++++++++++++++++++++ runtimespec/config.go | 25 +++++++++++++++++++ 4 files changed, 96 insertions(+) create mode 100644 jail/limit.go diff --git a/cmd/runj/create.go b/cmd/runj/create.go index 121b4b5..9c3fca4 100644 --- a/cmd/runj/create.go +++ b/cmd/runj/create.go @@ -137,6 +137,16 @@ the console's pseudoterminal`) if err := jail.CreateJail(cmd.Context(), confPath); err != nil { return err } + err = jail.Limit(id, ociConfig) + if err != nil { + return err + } + defer func() { + if err == nil { + return + } + jail.Unlimit(id, ociConfig) + }() err = jail.Mount(ociConfig) if err != nil { return err diff --git a/cmd/runj/delete.go b/cmd/runj/delete.go index 23ba2f8..37bc134 100644 --- a/cmd/runj/delete.go +++ b/cmd/runj/delete.go @@ -59,6 +59,10 @@ func deleteCommand() *cobra.Command { if ociConfig == nil { return errors.New("OCI config is required") } + err = jail.Unlimit(id, ociConfig) + if err != nil { + return err + } err = jail.Unmount(ociConfig) if err != nil { return err diff --git a/jail/limit.go b/jail/limit.go new file mode 100644 index 0000000..c4543af --- /dev/null +++ b/jail/limit.go @@ -0,0 +1,57 @@ +package jail + +import ( + "bytes" + "os/exec" + + "go.sbk.wtf/runj/runtimespec" +) + +// Limit uses rctl to add the rct rules +func Limit(id string, ociConfig *runtimespec.Spec) error { + if ociConfig.FreeBSD == nil { + return nil + } + for _, racctLimit := range ociConfig.FreeBSD.RacctLimits { + rule := makeRCTLRule(id, &racctLimit) + cmd := exec.Command("rctl", "-a", rule) + err := cmd.Run() + if err != nil { + return err + } + } + return nil +} + +// Unlimit uses rctl to remove the rctl rules +func Unlimit(id string, ociConfig *runtimespec.Spec) error { + if ociConfig.FreeBSD == nil { + return nil + } + for _, racctLimit := range ociConfig.FreeBSD.RacctLimits { + rule := makeRCTLRule(id, &racctLimit) + cmd := exec.Command("rctl", "-r", rule) + err := cmd.Run() + if err != nil { + return err + } + } + return nil +} + +func makeRCTLRule(id string, racctLimit *runtimespec.RacctLimit) string { + buf := bytes.Buffer{} + buf.WriteString("jail:") + buf.WriteString(id) + buf.WriteString(":") + buf.WriteString(racctLimit.Resource) + buf.WriteString(":") + buf.WriteString(racctLimit.Action) + buf.WriteString("=") + buf.WriteString(racctLimit.Amount) + if racctLimit.Per != "" { + buf.WriteString("/") + buf.WriteString(racctLimit.Per) + } + return buf.String() +} diff --git a/runtimespec/config.go b/runtimespec/config.go index 4166b59..c7a5b21 100644 --- a/runtimespec/config.go +++ b/runtimespec/config.go @@ -53,6 +53,11 @@ type Spec struct { VM *VM `json:"vm,omitempty" platform:"vm"` */ // End of modification + + // Modification by Cyril Zhang + // FreeBSD is platform-specific configuration for FreeBSD based containers. + FreeBSD *FreeBSD `json:"freebsd,omitempty" platform:"freebsd"` + // End of modification } // Modification by Samuel Karp @@ -135,6 +140,26 @@ type Mount struct { Options []string `json:"options,omitempty"` } +// Modification by Cyril Zhang +// FreeBSD contains platform-specific configuration for FreeBSD based containers. +type FreeBSD struct { + // RacctLimits specifies racct rules to apply to this jail. + RacctLimits []RacctLimit `json:"racct,omitempty"` +} + +// RacctLimit is a racct rule to apply to a jail. +type RacctLimit struct { + // Resource is the resource to set a limit on. + Resource string `json:"resource"` + // Action is what will happen if a process exceeds the allowed amount. + Action string `json:"action"` + // Amount is the allowed amount of the resource. + Amount string `json:"amount"` + // Per defines the entity that the amount applies to. + Per string `json:"per,omitempty"` +} +// End of modification + // Modification by Samuel Karp /* Omitted type definitions for: