Skip to content

Commit

Permalink
linux: Support setting execution domain via linux personality.
Browse files Browse the repository at this point in the history
Signed-off-by: Aditya Rajan <flouthoc.git@gmail.com>
  • Loading branch information
flouthoc committed Aug 23, 2021
1 parent 16027b8 commit aab68b3
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 0 deletions.
3 changes: 3 additions & 0 deletions libcontainer/configs/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,9 @@ type Config struct {
// RootlessCgroups is set when unlikely to have the full access to cgroups.
// When RootlessCgroups is set, cgroups errors are ignored.
RootlessCgroups bool `json:"rootless_cgroups,omitempty"`

// Personality contains configuration for the Linux personality syscall.
Personality *LinuxPersonality `json:"personality,omitempty"`
}

type (
Expand Down
13 changes: 13 additions & 0 deletions libcontainer/configs/config_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,19 @@ var (
errNoGroupMap = errors.New("User namespaces enabled, but no group mapping found.")
)

// Please check https://man7.org/linux/man-pages/man2/personality.2.html for const details.
// https://raw.githubusercontent.com/torvalds/linux/master/include/uapi/linux/personality.h
const (
PER_LINUX = 0x0000
PER_LINUX32 = 0x0008
)

type LinuxPersonality struct {
// Domain for the personality
// can only contain values "LINUX" and "LINUX32"
Domain int `json:"domain"`
}

// HostUID gets the translated uid for the process on host which could be
// different when user namespaces are enabled.
func (c Config) HostUID(containerId int) (int, error) {
Expand Down
7 changes: 7 additions & 0 deletions libcontainer/container_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,13 @@ func (c *linuxContainer) Set(config configs.Config) error {
func (c *linuxContainer) Start(process *Process) error {
c.m.Lock()
defer c.m.Unlock()
// configure linux personality before starting the process
if c.config.Personality != nil {
err := system.SetLinuxPersonality(c.config.Personality.Domain)
if err != nil {
return err
}
}
if c.config.Cgroups.Resources.SkipDevices {
return &ConfigError{"can't start container with SkipDevices set"}
}
Expand Down
20 changes: 20 additions & 0 deletions libcontainer/integration/exec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,26 @@ func TestIPCBadPath(t *testing.T) {
}
}

func TestPersonality(t *testing.T) {
if testing.Short() {
return
}

config := newTemplateConfig(t, &tParam{})

// change execution domain to i686
config.Personality = &configs.LinuxPersonality{
Domain: configs.PER_LINUX32,
}

out, _, err := runContainer(t, config, "", "/bin/sh", "-c", "uname -a")
ok(t, err)
// output must contain kernel architecture configured as i686
if !strings.Contains(out.Stdout.String(), "i686") {
t.Fatalf("expected kernel architecture i686 configured via personality")
}
}

func TestRlimit(t *testing.T) {
testRlimit(t, false)
}
Expand Down
20 changes: 20 additions & 0 deletions libcontainer/specconv/spec_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,11 @@ func CreateLibcontainerConfig(opts *CreateOpts) (*configs.Config, error) {
MemBwSchema: spec.Linux.IntelRdt.MemBwSchema,
}
}
if spec.Linux.Personality != nil {
config.Personality = &configs.LinuxPersonality{
Domain: getLinuxPersonalityFromStr(string(spec.Linux.Personality.Domain)),
}
}
}
if spec.Process != nil {
config.OomScoreAdj = spec.Process.OOMScoreAdj
Expand Down Expand Up @@ -391,6 +396,21 @@ func convertSecToUSec(value dbus.Variant) (dbus.Variant, error) {
return dbus.MakeVariant(sec), nil
}

// getLinuxPersonalityFromStr converts the string domain received from spec to equivalent integer.
// check libcontainer/configs/config_linux.go
// check https://raw.githubusercontent.com/torvalds/linux/master/include/uapi/linux/personality.h
// valid arguments
// LINUX i.e PER_LINUX (since Linux 1.2.0).
// LINUX32 i.e PER_LINUX32 (since Linux 2.2) LINUX32 will set the uname system call to show a 32 bit CPU type, such as i686.
// everything unknown default to PER_LINUX.
func getLinuxPersonalityFromStr(domain string) int {
// defaults to PER_LINUX
if domain == "LINUX32" {
return configs.PER_LINUX32
}
return configs.PER_LINUX
}

func initSystemdProps(spec *specs.Spec) ([]systemdDbus.Property, error) {
const keyPrefix = "org.systemd.property."
var sp []systemdDbus.Property
Expand Down
12 changes: 12 additions & 0 deletions libcontainer/system/linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
package system

import (
"os"
"os/exec"
"syscall"
"unsafe"

"golang.org/x/sys/unix"
Expand Down Expand Up @@ -108,3 +110,13 @@ func GetSubreaper() (int, error) {

return int(i), nil
}

// SetLinuxPersonality sets the Linux execution personality. For more information see the personality syscall documentation.
// checkout getLinuxPersonalityFromStr() from libcontainer/specconv/spec_linux.go for type conversion.
func SetLinuxPersonality(persona int) error {
_, _, errno := syscall.Syscall(syscall.SYS_PERSONALITY, uintptr(persona), 0, 0)
if errno != 0 {
return &os.SyscallError{Syscall: "set_personality", Err: errno}
}
return nil
}

0 comments on commit aab68b3

Please sign in to comment.