Skip to content
This repository was archived by the owner on Dec 13, 2018. It is now read-only.

Commit d06a2da

Browse files
author
Mrunal Patel
committed
Merge pull request #385 from crosbymichael/userns-updates
Make usernamespaces work without sidecar process
2 parents cc42996 + afa8443 commit d06a2da

14 files changed

+184
-266
lines changed

error.go

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,3 @@ type Error interface {
5757
// Returns the error code for this error.
5858
Code() ErrorCode
5959
}
60-
61-
type initError struct {
62-
Message string `json:"message,omitempty"`
63-
}
64-
65-
func (i initError) Error() string {
66-
return i.Message
67-
}

generic_error.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ import (
1111

1212
var errorTemplate = template.Must(template.New("error").Parse(`Timestamp: {{.Timestamp}}
1313
Code: {{.ECode}}
14-
{{if .Err }}
15-
Message: {{.Err.Error}}
14+
{{if .Message }}
15+
Message: {{.Message}}
1616
{{end}}
1717
Frames:{{range $i, $frame := .Stack.Frames}}
1818
---
@@ -28,6 +28,7 @@ func newGenericError(err error, c ErrorCode) Error {
2828
return &genericError{
2929
Timestamp: time.Now(),
3030
Err: err,
31+
Message: err.Error(),
3132
ECode: c,
3233
Stack: stacktrace.Capture(1),
3334
}
@@ -41,19 +42,21 @@ func newSystemError(err error) Error {
4142
Timestamp: time.Now(),
4243
Err: err,
4344
ECode: SystemError,
45+
Message: err.Error(),
4446
Stack: stacktrace.Capture(1),
4547
}
4648
}
4749

4850
type genericError struct {
4951
Timestamp time.Time
5052
ECode ErrorCode
51-
Err error
53+
Err error `json:"-"`
54+
Message string
5255
Stack stacktrace.Stacktrace
5356
}
5457

5558
func (e *genericError) Error() string {
56-
return fmt.Sprintf("[%d] %s: %s", e.ECode, e.ECode, e.Err)
59+
return fmt.Sprintf("[%d] %s: %s", e.ECode, e.ECode, e.Message)
5760
}
5861

5962
func (e *genericError) Code() ErrorCode {

linux_console.go

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,9 @@ import (
1212
"github.com/docker/libcontainer/label"
1313
)
1414

15-
const (
16-
containerConsolePath string = "/dev/console"
17-
)
18-
1915
// NewConsole returns an initalized console that can be used within a container by copying bytes
2016
// from the master side to the slave that is attached as the tty for the container's init process.
21-
func NewConsole() (Console, error) {
17+
func NewConsole(uid, gid int) (Console, error) {
2218
master, err := os.OpenFile("/dev/ptmx", syscall.O_RDWR|syscall.O_NOCTTY|syscall.O_CLOEXEC, 0)
2319
if err != nil {
2420
return nil, err
@@ -30,6 +26,12 @@ func NewConsole() (Console, error) {
3026
if err := unlockpt(master); err != nil {
3127
return nil, err
3228
}
29+
if err := os.Chmod(console, 0600); err != nil {
30+
return nil, err
31+
}
32+
if err := os.Chown(console, uid, gid); err != nil {
33+
return nil, err
34+
}
3335
return &linuxConsole{
3436
slavePath: console,
3537
master: master,
@@ -78,16 +80,10 @@ func (c *linuxConsole) Close() error {
7880
func (c *linuxConsole) mount(rootfs, mountLabel string, uid, gid int) error {
7981
oldMask := syscall.Umask(0000)
8082
defer syscall.Umask(oldMask)
81-
if err := os.Chmod(c.slavePath, 0600); err != nil {
82-
return err
83-
}
84-
if err := os.Chown(c.slavePath, uid, gid); err != nil {
85-
return err
86-
}
8783
if err := label.SetFileLabel(c.slavePath, mountLabel); err != nil {
8884
return err
8985
}
90-
dest := filepath.Join(rootfs, containerConsolePath)
86+
dest := filepath.Join(rootfs, "/dev/console")
9187
f, err := os.Create(dest)
9288
if err != nil && !os.IsExist(err) {
9389
return err

linux_container.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,6 @@ func (c *linuxContainer) newInitProcess(p *Process, cmd *exec.Cmd, parentPipe, c
147147
if cmd.SysProcAttr.Credential == nil {
148148
cmd.SysProcAttr.Credential = &syscall.Credential{}
149149
}
150-
t = "_LIBCONTAINER_INITTYPE=userns"
151150
}
152151
cmd.Env = append(cmd.Env, t)
153152
cmd.SysProcAttr.Cloneflags = cloneFlags

linux_factory.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -166,9 +166,7 @@ func (l *LinuxFactory) StartInitialization(pipefd uintptr) (err error) {
166166
// ensure that any data sent from the parent is consumed so it doesn't
167167
// receive ECONNRESET when the child writes to the pipe.
168168
ioutil.ReadAll(pipe)
169-
if err := json.NewEncoder(pipe).Encode(initError{
170-
Message: err.Error(),
171-
}); err != nil {
169+
if err := json.NewEncoder(pipe).Encode(newSystemError(err)); err != nil {
172170
panic(err)
173171
}
174172
}

linux_init.go

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,8 @@ import (
2121
type initType string
2222

2323
const (
24-
initSetns initType = "setns"
25-
initStandard initType = "standard"
26-
initUserns initType = "userns"
27-
initUsernsSetup initType = "userns_setup"
24+
initSetns initType = "setns"
25+
initStandard initType = "standard"
2826
)
2927

3028
type pid struct {
@@ -67,14 +65,6 @@ func newContainerInit(t initType, pipe *os.File) (initer, error) {
6765
return &linuxSetnsInit{
6866
config: config,
6967
}, nil
70-
case initUserns:
71-
return &linuxUsernsInit{
72-
config: config,
73-
}, nil
74-
case initUsernsSetup:
75-
return &linuxUsernsSideCar{
76-
config: config,
77-
}, nil
7868
case initStandard:
7969
return &linuxStandardInit{
8070
config: config,

linux_process.go

Lines changed: 1 addition & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,11 @@ package libcontainer
44

55
import (
66
"encoding/json"
7-
"fmt"
87
"io"
98
"os"
109
"os/exec"
1110
"syscall"
1211

13-
log "github.com/Sirupsen/logrus"
1412
"github.com/docker/libcontainer/cgroups"
1513
"github.com/docker/libcontainer/system"
1614
)
@@ -145,28 +143,12 @@ func (p *initProcess) start() error {
145143
if err := p.createNetworkInterfaces(); err != nil {
146144
return newSystemError(err)
147145
}
148-
// Start the setup process to setup the init process
149-
if p.cmd.SysProcAttr.Cloneflags&syscall.CLONE_NEWUSER != 0 {
150-
parent, err := p.newUsernsSetupProcess()
151-
if err != nil {
152-
return newSystemError(err)
153-
}
154-
if err := parent.start(); err != nil {
155-
if err := parent.terminate(); err != nil {
156-
log.Warn(err)
157-
}
158-
return err
159-
}
160-
if _, err := parent.wait(); err != nil {
161-
return newSystemError(err)
162-
}
163-
}
164146
if err := p.sendConfig(); err != nil {
165147
return newSystemError(err)
166148
}
167149
// wait for the child process to fully complete and receive an error message
168150
// if one was encoutered
169-
var ierr *initError
151+
var ierr *genericError
170152
if err := json.NewDecoder(p.parentPipe).Decode(&ierr); err != nil && err != io.EOF {
171153
return newSystemError(err)
172154
}
@@ -229,26 +211,6 @@ func (p *initProcess) createNetworkInterfaces() error {
229211
return nil
230212
}
231213

232-
func (p *initProcess) newUsernsSetupProcess() (parentProcess, error) {
233-
parentPipe, childPipe, err := newPipe()
234-
if err != nil {
235-
return nil, newSystemError(err)
236-
}
237-
cmd := exec.Command(p.cmd.Args[0], p.cmd.Args[1:]...)
238-
cmd.ExtraFiles = []*os.File{childPipe}
239-
cmd.Dir = p.cmd.Dir
240-
cmd.Env = append(cmd.Env,
241-
fmt.Sprintf("_LIBCONTAINER_INITPID=%d", p.pid()),
242-
fmt.Sprintf("_LIBCONTAINER_INITTYPE=userns_setup"),
243-
)
244-
return &setnsProcess{
245-
cmd: cmd,
246-
childPipe: childPipe,
247-
parentPipe: parentPipe,
248-
config: p.config,
249-
}, nil
250-
}
251-
252214
func (p *initProcess) signal(s os.Signal) error {
253215
return p.cmd.Process.Signal(s)
254216
}

linux_rootfs.go

Lines changed: 40 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -35,52 +35,49 @@ var baseMounts = []*configs.Mount{
3535
Destination: "/dev/pts",
3636
Device: "devpts",
3737
Flags: syscall.MS_NOSUID | syscall.MS_NOEXEC,
38-
Data: "newinstance,ptmxmode=0666,mode=620,gid=5",
38+
Data: "newinstance,ptmxmode=0666,mode=0620,gid=5",
3939
},
4040
}
4141

4242
// setupRootfs sets up the devices, mount points, and filesystems for use inside a
4343
// new mount namespace.
4444
func setupRootfs(config *configs.Config) (err error) {
4545
if err := prepareRoot(config); err != nil {
46-
return err
46+
return newSystemError(err)
4747
}
4848
for _, m := range append(baseMounts, config.Mounts...) {
4949
if err := mount(m, config.Rootfs, config.MountLabel); err != nil {
50-
return err
50+
return newSystemError(err)
5151
}
5252
}
5353
if err := createDevices(config); err != nil {
54-
return err
54+
return newSystemError(err)
5555
}
5656
if err := setupPtmx(config); err != nil {
57-
return err
57+
return newSystemError(err)
5858
}
5959
// stdin, stdout and stderr could be pointing to /dev/null from parent namespace.
60-
// Re-open them inside this namespace.
61-
// FIXME: Need to fix this for user namespaces.
62-
if !config.Namespaces.Contains(configs.NEWUSER) {
63-
if err := reOpenDevNull(config.Rootfs); err != nil {
64-
return err
65-
}
60+
// re-open them inside this namespace.
61+
if err := reOpenDevNull(config.Rootfs); err != nil {
62+
return newSystemError(err)
6663
}
6764
if err := setupDevSymlinks(config.Rootfs); err != nil {
68-
return err
65+
return newSystemError(err)
6966
}
7067
if err := syscall.Chdir(config.Rootfs); err != nil {
71-
return err
68+
return newSystemError(err)
7269
}
7370
if config.NoPivotRoot {
7471
err = msMoveRoot(config.Rootfs)
7572
} else {
7673
err = pivotRoot(config.Rootfs, config.PivotDir)
7774
}
7875
if err != nil {
79-
return err
76+
return newSystemError(err)
8077
}
8178
if config.Readonlyfs {
8279
if err := setReadonly(); err != nil {
83-
return err
80+
return newSystemError(err)
8481
}
8582
}
8683
syscall.Umask(0022)
@@ -202,13 +199,32 @@ func createDevices(config *configs.Config) error {
202199

203200
// Creates the device node in the rootfs of the container.
204201
func createDeviceNode(rootfs string, node *configs.Device) error {
205-
var (
206-
dest = filepath.Join(rootfs, node.Path)
207-
parent = filepath.Dir(dest)
208-
)
209-
if err := os.MkdirAll(parent, 0755); err != nil {
202+
dest := filepath.Join(rootfs, node.Path)
203+
if err := os.MkdirAll(filepath.Dir(dest), 0755); err != nil {
210204
return err
211205
}
206+
if err := mknodDevice(dest, node); err != nil {
207+
if os.IsExist(err) {
208+
return nil
209+
}
210+
if err != syscall.EPERM {
211+
return err
212+
}
213+
// containers running in a user namespace are not allowed to mknod
214+
// devices so we can just bind mount it from the host.
215+
f, err := os.Create(dest)
216+
if err != nil && !os.IsExist(err) {
217+
return err
218+
}
219+
if f != nil {
220+
f.Close()
221+
}
222+
return syscall.Mount(node.Path, dest, "bind", syscall.MS_BIND, "")
223+
}
224+
return nil
225+
}
226+
227+
func mknodDevice(dest string, node *configs.Device) error {
212228
fileMode := node.FileMode
213229
switch node.Type {
214230
case 'c':
@@ -218,13 +234,10 @@ func createDeviceNode(rootfs string, node *configs.Device) error {
218234
default:
219235
return fmt.Errorf("%c is not a valid device type for device %s", node.Type, node.Path)
220236
}
221-
if err := syscall.Mknod(dest, uint32(fileMode), node.Mkdev()); err != nil && !os.IsExist(err) {
222-
return fmt.Errorf("mknod %s %s", node.Path, err)
223-
}
224-
if err := syscall.Chown(dest, int(node.Uid), int(node.Gid)); err != nil {
225-
return fmt.Errorf("chown %s to %d:%d", node.Path, node.Uid, node.Gid)
237+
if err := syscall.Mknod(dest, uint32(fileMode), node.Mkdev()); err != nil {
238+
return err
226239
}
227-
return nil
240+
return syscall.Chown(dest, int(node.Uid), int(node.Gid))
228241
}
229242

230243
func prepareRoot(config *configs.Config) error {
@@ -251,16 +264,8 @@ func setupPtmx(config *configs.Config) error {
251264
return fmt.Errorf("symlink dev ptmx %s", err)
252265
}
253266
if config.Console != "" {
254-
uid, err := config.HostUID()
255-
if err != nil {
256-
return err
257-
}
258-
gid, err := config.HostGID()
259-
if err != nil {
260-
return err
261-
}
262267
console := newConsoleFromPath(config.Console)
263-
return console.mount(config.Rootfs, config.MountLabel, uid, gid)
268+
return console.mount(config.Rootfs, config.MountLabel, 0, 0)
264269
}
265270
return nil
266271
}

0 commit comments

Comments
 (0)