From d9230602e9cc011dc6c2d3e628d02fb4812ead38 Mon Sep 17 00:00:00 2001 From: utam0k Date: Tue, 4 Oct 2022 20:45:50 +0900 Subject: [PATCH] Implement to set a domainname opencontainers/runtime-spec#1156 Signed-off-by: utam0k --- libcontainer/configs/config.go | 3 ++ libcontainer/configs/validate/validator.go | 7 +++-- .../configs/validate/validator_test.go | 30 ++++++++++++++++++- libcontainer/integration/template_test.go | 5 ++-- libcontainer/specconv/spec_linux.go | 1 + libcontainer/standard_init_linux.go | 5 ++++ tests/integration/run.bats | 19 ++++++++++++ 7 files changed, 65 insertions(+), 5 deletions(-) diff --git a/libcontainer/configs/config.go b/libcontainer/configs/config.go index 18955cf95c9..d43ea7860a2 100644 --- a/libcontainer/configs/config.go +++ b/libcontainer/configs/config.go @@ -119,6 +119,9 @@ type Config struct { // Hostname optionally sets the container's hostname if provided Hostname string `json:"hostname"` + // Domainname optionally sets the container's domainname if provided + Domainname string `json:"domainname"` + // Namespaces specifies the container's namespaces that it should setup when cloning the init process // If a namespace is not provided that namespace is shared from the container's parent process Namespaces Namespaces `json:"namespaces"` diff --git a/libcontainer/configs/validate/validator.go b/libcontainer/configs/validate/validator.go index 2027a37203e..483e7a2ff3e 100644 --- a/libcontainer/configs/validate/validator.go +++ b/libcontainer/configs/validate/validator.go @@ -23,7 +23,7 @@ func Validate(config *configs.Config) error { cgroupsCheck, rootfs, network, - hostname, + uts, security, namespaces, sysctl, @@ -75,10 +75,13 @@ func network(config *configs.Config) error { return nil } -func hostname(config *configs.Config) error { +func uts(config *configs.Config) error { if config.Hostname != "" && !config.Namespaces.Contains(configs.NEWUTS) { return errors.New("unable to set hostname without a private UTS namespace") } + if config.Domainname != "" && !config.Namespaces.Contains(configs.NEWUTS) { + return errors.New("unable to set domainname without a private UTS namespace") + } return nil } diff --git a/libcontainer/configs/validate/validator_test.go b/libcontainer/configs/validate/validator_test.go index 59a4033899e..f59d0f2030c 100644 --- a/libcontainer/configs/validate/validator_test.go +++ b/libcontainer/configs/validate/validator_test.go @@ -82,7 +82,25 @@ func TestValidateHostname(t *testing.T) { } } -func TestValidateHostnameWithoutUTSNamespace(t *testing.T) { +func TestValidateUTS(t *testing.T) { + config := &configs.Config{ + Rootfs: "/var", + Domainname: "runc", + Hostname: "runc", + Namespaces: configs.Namespaces( + []configs.Namespace{ + {Type: configs.NEWUTS}, + }, + ), + } + + err := Validate(config) + if err != nil { + t.Errorf("Expected error to not occur: %+v", err) + } +} + +func TestValidateUTSWithoutUTSNamespace(t *testing.T) { config := &configs.Config{ Rootfs: "/var", Hostname: "runc", @@ -92,6 +110,16 @@ func TestValidateHostnameWithoutUTSNamespace(t *testing.T) { if err == nil { t.Error("Expected error to occur but it was nil") } + + config = &configs.Config{ + Rootfs: "/var", + Domainname: "runc", + } + + err = Validate(config) + if err == nil { + t.Error("Expected error to occur but it was nil") + } } func TestValidateSecurityWithMaskPaths(t *testing.T) { diff --git a/libcontainer/integration/template_test.go b/libcontainer/integration/template_test.go index 0e054b55b45..3de1d3e325d 100644 --- a/libcontainer/integration/template_test.go +++ b/libcontainer/integration/template_test.go @@ -129,8 +129,9 @@ func newTemplateConfig(t *testing.T, p *tParam) *configs.Config { ReadonlyPaths: []string{ "/proc/sys", "/proc/sysrq-trigger", "/proc/irq", "/proc/bus", }, - Devices: specconv.AllowedDevices, - Hostname: "integration", + Devices: specconv.AllowedDevices, + Hostname: "integration", + Domainname: "integration", Mounts: []*configs.Mount{ { Source: "proc", diff --git a/libcontainer/specconv/spec_linux.go b/libcontainer/specconv/spec_linux.go index 345c467d0b1..809424a97eb 100644 --- a/libcontainer/specconv/spec_linux.go +++ b/libcontainer/specconv/spec_linux.go @@ -353,6 +353,7 @@ func CreateLibcontainerConfig(opts *CreateOpts) (*configs.Config, error) { NoPivotRoot: opts.NoPivotRoot, Readonlyfs: spec.Root.Readonly, Hostname: spec.Hostname, + Domainname: spec.Domainname, Labels: append(labels, "bundle="+cwd), NoNewKeyring: opts.NoNewKeyring, RootlessEUID: opts.RootlessEUID, diff --git a/libcontainer/standard_init_linux.go b/libcontainer/standard_init_linux.go index 32de78eb20d..a4c01953aeb 100644 --- a/libcontainer/standard_init_linux.go +++ b/libcontainer/standard_init_linux.go @@ -126,6 +126,11 @@ func (l *linuxStandardInit) Init() error { return &os.SyscallError{Syscall: "sethostname", Err: err} } } + if domainname := l.config.Config.Domainname; domainname != "" { + if err := unix.Setdomainname([]byte(domainname)); err != nil { + return &os.SyscallError{Syscall: "setdomainname", Err: err} + } + } if err := apparmor.ApplyProfile(l.config.AppArmorProfile); err != nil { return fmt.Errorf("unable to apply apparmor profile: %w", err) } diff --git a/tests/integration/run.bats b/tests/integration/run.bats index 2cef4fdbc4f..ae4e0fa593a 100644 --- a/tests/integration/run.bats +++ b/tests/integration/run.bats @@ -57,3 +57,22 @@ function teardown() { runc state test_run_keep [ "$status" -ne 0 ] } + +@test "runc run [hostname domainname]" { + update_config ' .process.args |= ["sh"] + | .hostname = "myhostname" + | .domainname= "mydomainname"' + + runc run -d --console-socket "$CONSOLE_SOCKET" test_utc + [ "$status" -eq 0 ] + + # test hostname + runc exec test_utc hostname + [ "$status" -eq 0 ] + [[ "${lines[0]}" == *'myhostname'* ]] + + # test domainname + runc exec test_utc cat /proc/sys/kernel/domainname + [ "$status" -eq 0 ] + [[ "${lines[0]}" == *'mydomainname'* ]] +}