Skip to content

Commit 6aa4d8d

Browse files
authored
Merge pull request #4082 from Zheaoli/manjusaka/support-personality
carry #3126: linux: Support setting execution domain via linux personality
2 parents edd00eb + 98511bb commit 6aa4d8d

File tree

9 files changed

+129
-1
lines changed

9 files changed

+129
-1
lines changed

docs/spec-conformance.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ The following features are not implemented yet:
77

88
Spec version | Feature | PR
99
-------------|------------------------------------------|----------------------------------------------------------
10-
v1.0.2 | `.linux.personality` | [#3126](https://github.com/opencontainers/runc/pull/3126)
1110
v1.1.0 | `SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV` | [#3862](https://github.com/opencontainers/runc/pull/3862)
1211
v1.1.0 | rsvd hugetlb cgroup | TODO ([#3859](https://github.com/opencontainers/runc/issues/3859))
1312
v1.1.0 | `.process.ioPriority` | [#3783](https://github.com/opencontainers/runc/pull/3783)

libcontainer/configs/config.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,9 @@ type Config struct {
219219

220220
// Scheduler represents the scheduling attributes for a process.
221221
Scheduler *Scheduler `json:"scheduler,omitempty"`
222+
223+
// Personality contains configuration for the Linux personality syscall.
224+
Personality *LinuxPersonality `json:"personality,omitempty"`
222225
}
223226

224227
// Scheduler is based on the Linux sched_setattr(2) syscall.

libcontainer/configs/config_linux.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,19 @@ var (
99
errNoGroupMap = errors.New("User namespaces enabled, but no group mapping found.")
1010
)
1111

12+
// Please check https://man7.org/linux/man-pages/man2/personality.2.html for const details.
13+
// https://raw.githubusercontent.com/torvalds/linux/master/include/uapi/linux/personality.h
14+
const (
15+
PerLinux = 0x0000
16+
PerLinux32 = 0x0008
17+
)
18+
19+
type LinuxPersonality struct {
20+
// Domain for the personality
21+
// can only contain values "LINUX" and "LINUX32"
22+
Domain int `json:"domain"`
23+
}
24+
1225
// HostUID gets the translated uid for the process on host which could be
1326
// different when user namespaces are enabled.
1427
func (c Config) HostUID(containerId int) (int, error) {

libcontainer/init_linux.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -654,6 +654,10 @@ func setupScheduler(config *configs.Config) error {
654654
return nil
655655
}
656656

657+
func setupPersonality(config *configs.Config) error {
658+
return system.SetLinuxPersonality(config.Personality.Domain)
659+
}
660+
657661
// signalAllProcesses freezes then iterates over all the processes inside the
658662
// manager's cgroups sending the signal s to them.
659663
func signalAllProcesses(m cgroups.Manager, s unix.Signal) error {

libcontainer/setns_init_linux.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,11 @@ func (l *linuxSetnsInit) Init() error {
9393
if err := apparmor.ApplyProfile(l.config.AppArmorProfile); err != nil {
9494
return err
9595
}
96+
if l.config.Config.Personality != nil {
97+
if err := setupPersonality(l.config.Config); err != nil {
98+
return err
99+
}
100+
}
96101
// Check for the arg early to make sure it exists.
97102
name, err := exec.LookPath(l.config.Args[0])
98103
if err != nil {

libcontainer/specconv/spec_linux.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,18 @@ func CreateLibcontainerConfig(opts *CreateOpts) (*configs.Config, error) {
434434
MemBwSchema: spec.Linux.IntelRdt.MemBwSchema,
435435
}
436436
}
437+
if spec.Linux.Personality != nil {
438+
if len(spec.Linux.Personality.Flags) > 0 {
439+
logrus.Warnf("ignoring unsupported personality flags: %+v because personality flag has not supported at this time", spec.Linux.Personality.Flags)
440+
}
441+
domain, err := getLinuxPersonalityFromStr(string(spec.Linux.Personality.Domain))
442+
if err != nil {
443+
return nil, err
444+
}
445+
config.Personality = &configs.LinuxPersonality{
446+
Domain: domain,
447+
}
448+
}
437449
}
438450

439451
// Set the host UID that should own the container's cgroup.
@@ -571,6 +583,16 @@ func checkPropertyName(s string) error {
571583
return nil
572584
}
573585

586+
// getLinuxPersonalityFromStr converts the string domain received from spec to equivalent integer.
587+
func getLinuxPersonalityFromStr(domain string) (int, error) {
588+
if domain == string(specs.PerLinux32) {
589+
return configs.PerLinux32, nil
590+
} else if domain == string(specs.PerLinux) {
591+
return configs.PerLinux, nil
592+
}
593+
return -1, fmt.Errorf("invalid personality domain %s", domain)
594+
}
595+
574596
// Some systemd properties are documented as having "Sec" suffix
575597
// (e.g. TimeoutStopSec) but are expected to have "USec" suffix
576598
// here, so let's provide conversion to improve compatibility.

libcontainer/standard_init_linux.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,14 @@ func (l *linuxStandardInit) Init() error {
233233
return err
234234
}
235235
}
236+
237+
// Set personality if specified.
238+
if l.config.Config.Personality != nil {
239+
if err := setupPersonality(l.config.Config); err != nil {
240+
return err
241+
}
242+
}
243+
236244
// Close the pipe to signal that we have completed our init.
237245
logrus.Debugf("init: closing the pipe to signal completion")
238246
_ = l.pipe.Close()

libcontainer/system/linux.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,3 +214,13 @@ func Copy(dst io.Writer, src io.Reader) (copied int64, err error) {
214214
fallback:
215215
return io.Copy(dst, src)
216216
}
217+
218+
// SetLinuxPersonality sets the Linux execution personality. For more information see the personality syscall documentation.
219+
// checkout getLinuxPersonalityFromStr() from libcontainer/specconv/spec_linux.go for type conversion.
220+
func SetLinuxPersonality(personality int) error {
221+
_, _, errno := unix.Syscall(unix.SYS_PERSONALITY, uintptr(personality), 0, 0)
222+
if errno != 0 {
223+
return &os.SyscallError{Syscall: "set_personality", Err: errno}
224+
}
225+
return nil
226+
}

tests/integration/personality.bats

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#!/usr/bin/env bats
2+
3+
load helpers
4+
5+
function setup() {
6+
requires arch_x86_64
7+
setup_busybox
8+
}
9+
10+
function teardown() {
11+
teardown_bundle
12+
}
13+
14+
@test "runc run personality for i686" {
15+
update_config '
16+
.process.args = ["/bin/sh", "-c", "uname -a"]
17+
| .linux.personality = {
18+
"domain": "LINUX32",
19+
"flags": []
20+
}'
21+
22+
runc run test_busybox
23+
[ "$status" -eq 0 ]
24+
[[ "$output" == *"i686"* ]]
25+
}
26+
27+
@test "runc run personality with exec for i686" {
28+
update_config '
29+
.linux.personality = {
30+
"domain": "LINUX32",
31+
}'
32+
33+
runc run -d --console-socket "$CONSOLE_SOCKET" test_busybox
34+
[ "$status" -eq 0 ]
35+
runc exec test_busybox /bin/sh -c "uname -a"
36+
[ "$status" -eq 0 ]
37+
[[ "$output" == *"i686"* ]]
38+
}
39+
40+
@test "runc run personality for x86_64" {
41+
update_config '
42+
.process.args = ["/bin/sh", "-c", "uname -a"]
43+
| .linux.personality = {
44+
"domain": "LINUX",
45+
"flags": []
46+
}'
47+
48+
runc run test_busybox
49+
[ "$status" -eq 0 ]
50+
[[ "$output" == *"x86_64"* ]]
51+
}
52+
53+
@test "runc run personality with exec for x86_64" {
54+
update_config '
55+
.linux.personality = {
56+
"domain": "LINUX",
57+
}'
58+
59+
runc run -d --console-socket "$CONSOLE_SOCKET" test_busybox
60+
[ "$status" -eq 0 ]
61+
runc exec test_busybox /bin/sh -c "uname -a"
62+
[ "$status" -eq 0 ]
63+
[[ "$output" == *"x86_64"* ]]
64+
}

0 commit comments

Comments
 (0)