Skip to content

Commit 1a913c7

Browse files
committed
*: correctly chown() consoles
In user namespaces, we need to make sure we don't chown() the console to unmapped users. This means we need to get both the UID and GID of the root user in the container when changing the owner. Signed-off-by: Aleksa Sarai <[email protected]>
1 parent 60eb77d commit 1a913c7

File tree

6 files changed

+23
-17
lines changed

6 files changed

+23
-17
lines changed

libcontainer/integration/execin_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ func TestExecInTTY(t *testing.T) {
218218
Args: []string{"ps"},
219219
Env: standardEnvironment,
220220
}
221-
console, err := ps.NewConsole(0)
221+
console, err := ps.NewConsole(0, 0)
222222
copy := make(chan struct{})
223223
go func() {
224224
io.Copy(&stdout, console)

libcontainer/process.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,8 @@ type IO struct {
102102
}
103103

104104
// NewConsole creates new console for process and returns it
105-
func (p *Process) NewConsole(rootuid int) (Console, error) {
106-
console, err := NewConsole(rootuid, rootuid)
105+
func (p *Process) NewConsole(rootuid, rootgid int) (Console, error) {
106+
console, err := NewConsole(rootuid, rootgid)
107107
if err != nil {
108108
return nil, err
109109
}

libcontainer/process_linux.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -447,7 +447,7 @@ func getPipeFds(pid int) ([]string, error) {
447447

448448
// InitializeIO creates pipes for use with the process's STDIO
449449
// and returns the opposite side for each
450-
func (p *Process) InitializeIO(rootuid int) (i *IO, err error) {
450+
func (p *Process) InitializeIO(rootuid, rootgid int) (i *IO, err error) {
451451
var fds []uintptr
452452
i = &IO{}
453453
// cleanup in case of an error
@@ -479,7 +479,7 @@ func (p *Process) InitializeIO(rootuid int) (i *IO, err error) {
479479
p.Stderr, i.Stderr = w, r
480480
// change ownership of the pipes incase we are in a user namespace
481481
for _, fd := range fds {
482-
if err := syscall.Fchown(int(fd), rootuid, rootuid); err != nil {
482+
if err := syscall.Fchown(int(fd), rootuid, rootgid); err != nil {
483483
return nil, err
484484
}
485485
}

restore.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ using the runc checkpoint command.`,
117117
func restoreContainer(context *cli.Context, spec *specs.Spec, config *configs.Config, imagePath string) (code int, err error) {
118118
var (
119119
rootuid = 0
120+
rootgid = 0
120121
id = context.Args().First()
121122
)
122123
factory, err := loadFactory(context)
@@ -149,7 +150,7 @@ func restoreContainer(context *cli.Context, spec *specs.Spec, config *configs.Co
149150
defer destroy(container)
150151
}
151152
process := &libcontainer.Process{}
152-
tty, err := setupIO(process, rootuid, "", false, detach)
153+
tty, err := setupIO(process, rootuid, rootgid, "", false, detach)
153154
if err != nil {
154155
return -1, err
155156
}

tty.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ import (
1414

1515
// setup standard pipes so that the TTY of the calling runc process
1616
// is not inherited by the container.
17-
func createStdioPipes(p *libcontainer.Process, rootuid int) (*tty, error) {
18-
i, err := p.InitializeIO(rootuid)
17+
func createStdioPipes(p *libcontainer.Process, rootuid, rootgid int) (*tty, error) {
18+
i, err := p.InitializeIO(rootuid, rootgid)
1919
if err != nil {
2020
return nil, err
2121
}
@@ -52,14 +52,14 @@ func (t *tty) copyIO(w io.Writer, r io.ReadCloser) {
5252
r.Close()
5353
}
5454

55-
func createTty(p *libcontainer.Process, rootuid int, consolePath string) (*tty, error) {
55+
func createTty(p *libcontainer.Process, rootuid, rootgid int, consolePath string) (*tty, error) {
5656
if consolePath != "" {
5757
if err := p.ConsoleFromPath(consolePath); err != nil {
5858
return nil, err
5959
}
6060
return &tty{}, nil
6161
}
62-
console, err := p.NewConsole(rootuid)
62+
console, err := p.NewConsole(rootuid, rootgid)
6363
if err != nil {
6464
return nil, err
6565
}

utils_linux.go

+12-7
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ func newProcess(p specs.Process) (*libcontainer.Process, error) {
9292
return lp, nil
9393
}
9494

95-
func dupStdio(process *libcontainer.Process, rootuid int) error {
95+
func dupStdio(process *libcontainer.Process, rootuid, rootgid int) error {
9696
process.Stdin = os.Stdin
9797
process.Stdout = os.Stdout
9898
process.Stderr = os.Stderr
@@ -101,7 +101,7 @@ func dupStdio(process *libcontainer.Process, rootuid int) error {
101101
os.Stdout.Fd(),
102102
os.Stderr.Fd(),
103103
} {
104-
if err := syscall.Fchown(int(fd), rootuid, rootuid); err != nil {
104+
if err := syscall.Fchown(int(fd), rootuid, rootgid); err != nil {
105105
return err
106106
}
107107
}
@@ -123,22 +123,22 @@ func destroy(container libcontainer.Container) {
123123

124124
// setupIO sets the proper IO on the process depending on the configuration
125125
// If there is a nil error then there must be a non nil tty returned
126-
func setupIO(process *libcontainer.Process, rootuid int, console string, createTTY, detach bool) (*tty, error) {
126+
func setupIO(process *libcontainer.Process, rootuid, rootgid int, console string, createTTY, detach bool) (*tty, error) {
127127
// detach and createTty will not work unless a console path is passed
128128
// so error out here before changing any terminal settings
129129
if createTTY && detach && console == "" {
130130
return nil, fmt.Errorf("cannot allocate tty if runc will detach")
131131
}
132132
if createTTY {
133-
return createTty(process, rootuid, console)
133+
return createTty(process, rootuid, rootgid, console)
134134
}
135135
if detach {
136-
if err := dupStdio(process, rootuid); err != nil {
136+
if err := dupStdio(process, rootuid, rootgid); err != nil {
137137
return nil, err
138138
}
139139
return &tty{}, nil
140140
}
141-
return createStdioPipes(process, rootuid)
141+
return createStdioPipes(process, rootuid, rootgid)
142142
}
143143

144144
// createPidFile creates a file with the processes pid inside it atomically
@@ -215,7 +215,12 @@ func (r *runner) run(config *specs.Process) (int, error) {
215215
r.destroy()
216216
return -1, err
217217
}
218-
tty, err := setupIO(process, rootuid, r.console, config.Terminal, r.detach)
218+
rootgid, err := r.container.Config().HostGID()
219+
if err != nil {
220+
r.destroy()
221+
return -1, err
222+
}
223+
tty, err := setupIO(process, rootuid, rootgid, r.console, config.Terminal, r.detach)
219224
if err != nil {
220225
r.destroy()
221226
return -1, err

0 commit comments

Comments
 (0)