summaryrefslogtreecommitdiffhomepage
path: root/runsc/config
diff options
context:
space:
mode:
Diffstat (limited to 'runsc/config')
-rw-r--r--runsc/config/config.go6
-rw-r--r--runsc/config/config_test.go87
-rw-r--r--runsc/config/flags.go37
3 files changed, 130 insertions, 0 deletions
diff --git a/runsc/config/config.go b/runsc/config/config.go
index bca27ebf1..f30f79f68 100644
--- a/runsc/config/config.go
+++ b/runsc/config/config.go
@@ -157,6 +157,12 @@ type Config struct {
// Enables FUSE usage.
FUSE bool `flag:"fuse"`
+ // Allows overriding of flags in OCI annotations.
+ AllowFlagOverride bool `flag:"allow-flag-override"`
+
+ // Enables seccomp inside the sandbox.
+ OCISeccomp bool `flag:"oci-seccomp"`
+
// TestOnlyAllowRunAsCurrentUserWithoutChroot should only be used in
// tests. It allows runsc to start the sandbox process as the current
// user, and without chrooting the sandbox process. This can be
diff --git a/runsc/config/config_test.go b/runsc/config/config_test.go
index af7867a2a..fb162b7eb 100644
--- a/runsc/config/config_test.go
+++ b/runsc/config/config_test.go
@@ -183,3 +183,90 @@ func TestValidationFail(t *testing.T) {
})
}
}
+
+func TestOverride(t *testing.T) {
+ c, err := NewFromFlags()
+ if err != nil {
+ t.Fatal(err)
+ }
+ c.AllowFlagOverride = true
+
+ t.Run("string", func(t *testing.T) {
+ c.RootDir = "foobar"
+ if err := c.Override("root", "bar"); err != nil {
+ t.Fatalf("Override(root, bar) failed: %v", err)
+ }
+ defer setDefault("root")
+ if c.RootDir != "bar" {
+ t.Errorf("Override(root, bar) didn't work: %+v", c)
+ }
+ })
+
+ t.Run("bool", func(t *testing.T) {
+ c.Debug = true
+ if err := c.Override("debug", "false"); err != nil {
+ t.Fatalf("Override(debug, false) failed: %v", err)
+ }
+ defer setDefault("debug")
+ if c.Debug {
+ t.Errorf("Override(debug, false) didn't work: %+v", c)
+ }
+ })
+
+ t.Run("enum", func(t *testing.T) {
+ c.FileAccess = FileAccessShared
+ if err := c.Override("file-access", "exclusive"); err != nil {
+ t.Fatalf("Override(file-access, exclusive) failed: %v", err)
+ }
+ defer setDefault("file-access")
+ if c.FileAccess != FileAccessExclusive {
+ t.Errorf("Override(file-access, exclusive) didn't work: %+v", c)
+ }
+ })
+}
+
+func TestOverrideDisabled(t *testing.T) {
+ c, err := NewFromFlags()
+ if err != nil {
+ t.Fatal(err)
+ }
+ const errMsg = "flag override disabled"
+ if err := c.Override("root", "path"); err == nil || !strings.Contains(err.Error(), errMsg) {
+ t.Errorf("Override() wrong error: %v", err)
+ }
+}
+
+func TestOverrideError(t *testing.T) {
+ c, err := NewFromFlags()
+ if err != nil {
+ t.Fatal(err)
+ }
+ c.AllowFlagOverride = true
+ for _, tc := range []struct {
+ name string
+ value string
+ error string
+ }{
+ {
+ name: "invalid",
+ value: "valid",
+ error: `flag "invalid" not found`,
+ },
+ {
+ name: "debug",
+ value: "invalid",
+ error: "error setting flag debug",
+ },
+ {
+ name: "file-access",
+ value: "invalid",
+ error: "invalid file access type",
+ },
+ } {
+ t.Run(tc.name, func(t *testing.T) {
+ if err := c.Override(tc.name, tc.value); err == nil || !strings.Contains(err.Error(), tc.error) {
+ t.Errorf("Override(%q, %q) wrong error: %v", tc.name, tc.value, err)
+ }
+ })
+ }
+}
diff --git a/runsc/config/flags.go b/runsc/config/flags.go
index 488a4b9fb..a5f25cfa2 100644
--- a/runsc/config/flags.go
+++ b/runsc/config/flags.go
@@ -48,6 +48,7 @@ func RegisterFlags() {
flag.Bool("log-packets", false, "enable network packet logging.")
flag.String("debug-log-format", "text", "log format: text (default), json, or json-k8s.")
flag.Bool("alsologtostderr", false, "send log messages to stderr.")
+ flag.Bool("allow-flag-override", false, "allow OCI annotations (dev.gvisor.flag.<name>) to override flags for debugging.")
// Debugging flags: strace related
flag.Bool("strace", false, "enable strace.")
@@ -62,6 +63,7 @@ func RegisterFlags() {
flag.Bool("rootless", false, "it allows the sandbox to be started with a user that is not root. Sandbox and Gofer processes may run with same privileges as current user.")
flag.Var(leakModePtr(refs.NoLeakChecking), "ref-leak-mode", "sets reference leak check mode: disabled (default), log-names, log-traces.")
flag.Bool("cpu-num-from-quota", false, "set cpu number to cpu quota (least integer greater or equal to quota value, but not less than 2)")
+ flag.Bool("oci-seccomp", false, "Enables loading OCI seccomp filters inside the sandbox.")
// Flags that control sandbox runtime behavior: FS related.
flag.Var(fileAccessTypePtr(FileAccessExclusive), "file-access", "specifies which filesystem to use for the root mount: exclusive (default), shared. Volume mounts are always shared.")
@@ -149,6 +151,41 @@ func (c *Config) ToFlags() []string {
return rv
}
+// Override writes a new value to a flag.
+func (c *Config) Override(name string, value string) error {
+ if !c.AllowFlagOverride {
+ return fmt.Errorf("flag override disabled, use --allow-flag-override to enable it")
+ }
+
+ obj := reflect.ValueOf(c).Elem()
+ st := obj.Type()
+ for i := 0; i < st.NumField(); i++ {
+ f := st.Field(i)
+ fieldName, ok := f.Tag.Lookup("flag")
+ if !ok || fieldName != name {
+ // Not a flag field, or flag name doesn't match.
+ continue
+ }
+ fl := flag.CommandLine.Lookup(name)
+ if fl == nil {
+ // Flag must exist if there is a field match above.
+ panic(fmt.Sprintf("Flag %q not found", name))
+ }
+
+ // Use flag to convert the string value to the underlying flag type, using
+ // the same rules as the command-line for consistency.
+ if err := fl.Value.Set(value); err != nil {
+ return fmt.Errorf("error setting flag %s=%q: %w", name, value, err)
+ }
+ x := reflect.ValueOf(flag.Get(fl.Value))
+ obj.Field(i).Set(x)
+
+ // Validates the config again to ensure it's left in a consistent state.
+ return c.validate()
+ }
+ return fmt.Errorf("flag %q not found. Cannot set it to %q", name, value)
+}
+
func getVal(field reflect.Value) string {
if str, ok := field.Addr().Interface().(fmt.Stringer); ok {
return str.String()