diff --git a/api/server/server.go b/api/server/server.go index 83e2112766..9f88d1ad79 100644 --- a/api/server/server.go +++ b/api/server/server.go @@ -27,10 +27,10 @@ import ( "github.com/docker/docker/pkg/listenbuffer" "github.com/docker/docker/pkg/parsers" "github.com/docker/docker/pkg/systemd" - "github.com/docker/docker/pkg/user" "github.com/docker/docker/pkg/version" "github.com/docker/docker/registry" "github.com/docker/docker/utils" + "github.com/docker/libcontainer/user" "github.com/gorilla/mux" ) diff --git a/builder/builder.go b/builder/builder.go index 7f59efcc0f..7a94f2793a 100644 --- a/builder/builder.go +++ b/builder/builder.go @@ -121,7 +121,7 @@ func (b *buildFile) CmdFrom(name string) error { b.config = image.Config } if b.config.Env == nil || len(b.config.Env) == 0 { - b.config.Env = append(b.config.Env, "HOME=/", "PATH="+daemon.DefaultPathEnv) + b.config.Env = append(b.config.Env, "PATH="+daemon.DefaultPathEnv) } // Process ONBUILD triggers if they exist if nTriggers := len(b.config.OnBuild); nTriggers != 0 { diff --git a/daemon/container.go b/daemon/container.go index 537cfc6a75..d62eb6d2fa 100644 --- a/daemon/container.go +++ b/daemon/container.go @@ -1043,9 +1043,12 @@ func (container *Container) setupLinkedContainers() ([]string, error) { func (container *Container) createDaemonEnvironment(linkedEnv []string) []string { // Setup environment env := []string{ - "HOME=/", "PATH=" + DefaultPathEnv, "HOSTNAME=" + container.Config.Hostname, + // Note: we don't set HOME here because it'll get autoset intelligently + // based on the value of USER inside dockerinit, but only if it isn't + // set already (ie, that can be overridden by setting HOME via -e or ENV + // in a Dockerfile). } if container.Config.Tty { env = append(env, "TERM=xterm") diff --git a/hack/vendor.sh b/hack/vendor.sh index 6b780f0fa8..f916e1fcf0 100755 --- a/hack/vendor.sh +++ b/hack/vendor.sh @@ -63,4 +63,4 @@ mv tmp-tar src/code.google.com/p/go/src/pkg/archive/tar clone git github.com/godbus/dbus v1 clone git github.com/coreos/go-systemd v2 -clone git github.com/docker/libcontainer e6a43c1c2b9f769deb96348a0a93417cd48a36d8 +clone git github.com/docker/libcontainer bc06326a5e7decdc4191d1367de8439b9d83c450 diff --git a/integration-cli/docker_cli_build_test.go b/integration-cli/docker_cli_build_test.go index 7d22ddef4f..57d004ea80 100644 --- a/integration-cli/docker_cli_build_test.go +++ b/integration-cli/docker_cli_build_test.go @@ -723,7 +723,7 @@ func TestBuildRelativeWorkdir(t *testing.T) { func TestBuildEnv(t *testing.T) { name := "testbuildenv" - expected := "[HOME=/ PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin PORT=2375]" + expected := "[PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin PORT=2375]" defer deleteImages(name) _, err := buildImage(name, `FROM busybox diff --git a/integration-cli/docker_cli_run_test.go b/integration-cli/docker_cli_run_test.go index 63d3b133f1..cd3f302f10 100644 --- a/integration-cli/docker_cli_run_test.go +++ b/integration-cli/docker_cli_run_test.go @@ -657,7 +657,7 @@ func TestRunTwoConcurrentContainers(t *testing.T) { } func TestEnvironment(t *testing.T) { - cmd := exec.Command(dockerBinary, "run", "-h", "testing", "-e=FALSE=true", "-e=TRUE", "-e=TRICKY", "busybox", "env") + cmd := exec.Command(dockerBinary, "run", "-h", "testing", "-e=FALSE=true", "-e=TRUE", "-e=TRICKY", "-e=HOME=", "busybox", "env") cmd.Env = append(os.Environ(), "TRUE=false", "TRICKY=tri\ncky\n", @@ -676,13 +676,13 @@ func TestEnvironment(t *testing.T) { goodEnv := []string{ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", - "HOME=/", "HOSTNAME=testing", "FALSE=true", "TRUE=false", "TRICKY=tri", "cky", "", + "HOME=/root", } sort.Strings(goodEnv) if len(goodEnv) != len(actualEnv) { diff --git a/vendor/src/github.com/docker/libcontainer/.travis.yml b/vendor/src/github.com/docker/libcontainer/.travis.yml index 7040d0bd71..331227af01 100644 --- a/vendor/src/github.com/docker/libcontainer/.travis.yml +++ b/vendor/src/github.com/docker/libcontainer/.travis.yml @@ -21,10 +21,10 @@ install: - if [ -z "$TRAVIS_GLOBAL_WTF" ]; then go env; fi - go get -d -v ./... - if [ "$TRAVIS_GLOBAL_WTF" ]; then - export DOCKER_PATH="${GOPATH%%:*}/src/github.com/dotcloud/docker"; + export DOCKER_PATH="${GOPATH%%:*}/src/github.com/docker/docker"; mkdir -p "$DOCKER_PATH/hack/make"; - ( cd "$DOCKER_PATH/hack/make" && wget -c 'https://raw.githubusercontent.com/dotcloud/docker/master/hack/make/'{.validate,validate-dco,validate-gofmt} ); - sed -i 's!dotcloud/docker!docker/libcontainer!' "$DOCKER_PATH/hack/make/.validate"; + ( cd "$DOCKER_PATH/hack/make" && wget -c 'https://raw.githubusercontent.com/docker/docker/master/hack/make/'{.validate,validate-dco,validate-gofmt} ); + sed -i 's!docker/docker!docker/libcontainer!' "$DOCKER_PATH/hack/make/.validate"; fi script: diff --git a/vendor/src/github.com/docker/libcontainer/CONTRIBUTORS_GUIDE.md b/vendor/src/github.com/docker/libcontainer/CONTRIBUTORS_GUIDE.md index f02689625c..07bf22a031 100644 --- a/vendor/src/github.com/docker/libcontainer/CONTRIBUTORS_GUIDE.md +++ b/vendor/src/github.com/docker/libcontainer/CONTRIBUTORS_GUIDE.md @@ -176,7 +176,7 @@ One way to automate this, is customise your get ``commit.template`` by adding a ``prepare-commit-msg`` hook to your libcontainer checkout: ``` -curl -o .git/hooks/prepare-commit-msg https://raw.githubusercontent.com/dotcloud/docker/master/contrib/prepare-commit-msg.hook && chmod +x .git/hooks/prepare-commit-msg +curl -o .git/hooks/prepare-commit-msg https://raw.githubusercontent.com/docker/docker/master/contrib/prepare-commit-msg.hook && chmod +x .git/hooks/prepare-commit-msg ``` * Note: the above script expects to find your GitHub user name in ``git config --get github.user`` diff --git a/vendor/src/github.com/docker/libcontainer/cgroups/fs/apply_raw.go b/vendor/src/github.com/docker/libcontainer/cgroups/fs/apply_raw.go index e9c06e1e2c..2d1a15239f 100644 --- a/vendor/src/github.com/docker/libcontainer/cgroups/fs/apply_raw.go +++ b/vendor/src/github.com/docker/libcontainer/cgroups/fs/apply_raw.go @@ -150,6 +150,10 @@ func (raw *data) parent(subsystem string) (string, error) { } func (raw *data) path(subsystem string) (string, error) { + // If the cgroup name/path is absolute do not look relative to the cgroup of the init process. + if filepath.IsAbs(raw.cgroup) { + return filepath.Join(raw.root, subsystem, raw.cgroup), nil + } parent, err := raw.parent(subsystem) if err != nil { return "", err diff --git a/vendor/src/github.com/docker/libcontainer/cgroups/fs/utils_test.go b/vendor/src/github.com/docker/libcontainer/cgroups/fs/utils_test.go index 63d743f06e..6ea59bc506 100644 --- a/vendor/src/github.com/docker/libcontainer/cgroups/fs/utils_test.go +++ b/vendor/src/github.com/docker/libcontainer/cgroups/fs/utils_test.go @@ -5,6 +5,8 @@ import ( "os" "path/filepath" "testing" + + "github.com/docker/libcontainer/cgroups" ) const ( @@ -66,3 +68,20 @@ func TestGetCgroupParamsInt(t *testing.T) { t.Fatal("Expecting error, got none") } } + +func TestAbsolutePathHandling(t *testing.T) { + testCgroup := cgroups.Cgroup{ + Name: "bar", + Parent: "/foo", + } + cgroupData := data{ + root: "/sys/fs/cgroup", + cgroup: "/foo/bar", + c: &testCgroup, + pid: 1, + } + expectedPath := filepath.Join(cgroupData.root, "cpu", testCgroup.Parent, testCgroup.Name) + if path, err := cgroupData.path("cpu"); path != expectedPath || err != nil { + t.Fatalf("expected path %s but got %s %s", expectedPath, path, err) + } +} diff --git a/vendor/src/github.com/docker/libcontainer/label/label.go b/vendor/src/github.com/docker/libcontainer/label/label.go index 5c8228cdde..73869b36cf 100644 --- a/vendor/src/github.com/docker/libcontainer/label/label.go +++ b/vendor/src/github.com/docker/libcontainer/label/label.go @@ -2,6 +2,13 @@ package label +// InitLabels returns the process label and file labels to be used within +// the container. A list of options can be passed into this function to alter +// the labels. +func InitLabels(options []string) (string, string, error) { + return "", "", nil +} + func GenLabels(options string) (string, string, error) { return "", "", nil } @@ -22,7 +29,7 @@ func Relabel(path string, fileLabel string, relabel string) error { return nil } -func GetPidCon(pid int) (string, error) { +func GetPidLabel(pid int) (string, error) { return "", nil } diff --git a/vendor/src/github.com/docker/libcontainer/label/label_selinux.go b/vendor/src/github.com/docker/libcontainer/label/label_selinux.go index aa502a3d6f..5b1380a2be 100644 --- a/vendor/src/github.com/docker/libcontainer/label/label_selinux.go +++ b/vendor/src/github.com/docker/libcontainer/label/label_selinux.go @@ -9,30 +9,49 @@ import ( "github.com/docker/libcontainer/selinux" ) -func GenLabels(options string) (string, string, error) { +// InitLabels returns the process label and file labels to be used within +// the container. A list of options can be passed into this function to alter +// the labels. The labels returned will include a random MCS String, that is +// guaranteed to be unique. +func InitLabels(options []string) (string, string, error) { if !selinux.SelinuxEnabled() { return "", "", nil } var err error processLabel, mountLabel := selinux.GetLxcContexts() if processLabel != "" { - var ( - s = strings.Fields(options) - l = len(s) - ) - if l > 0 { - pcon := selinux.NewContext(processLabel) - for i := 0; i < l; i++ { - o := strings.Split(s[i], "=") - pcon[o[0]] = o[1] + pcon := selinux.NewContext(processLabel) + mcon := selinux.NewContext(mountLabel) + for _, opt := range options { + if opt == "disable" { + return "", "", nil + } + if i := strings.Index(opt, ":"); i == -1 { + return "", "", fmt.Errorf("Bad SELinux Option") + } + con := strings.SplitN(opt, ":", 2) + pcon[con[0]] = con[1] + if con[0] == "level" || con[0] == "user" { + mcon[con[0]] = con[1] } - processLabel = pcon.Get() - mountLabel, err = selinux.CopyLevel(processLabel, mountLabel) } + processLabel = pcon.Get() + mountLabel = mcon.Get() } return processLabel, mountLabel, err } +// DEPRECATED: The GenLabels function is only to be used during the transition to the official API. +func GenLabels(options string) (string, string, error) { + return InitLabels(strings.Fields(options)) +} + +// FormatMountLabel returns a string to be used by the mount command. +// The format of this string will be used to alter the labeling of the mountpoint. +// The string returned is suitable to be used as the options field of the mount command. +// If you need to have additional mount point options, you can pass them in as +// the first parameter. Second parameter is the label that you wish to apply +// to all content in the mount point. func FormatMountLabel(src, mountLabel string) string { if mountLabel != "" { switch src { @@ -45,6 +64,8 @@ func FormatMountLabel(src, mountLabel string) string { return src } +// SetProcessLabel takes a process label and tells the kernel to assign the +// label to the next program executed by the current process. func SetProcessLabel(processLabel string) error { if selinux.SelinuxEnabled() { return selinux.Setexeccon(processLabel) @@ -52,6 +73,9 @@ func SetProcessLabel(processLabel string) error { return nil } +// GetProcessLabel returns the process label that the kernel will assign +// to the next program executed by the current process. If "" is returned +// this indicates that the default labeling will happen for the process. func GetProcessLabel() (string, error) { if selinux.SelinuxEnabled() { return selinux.Getexeccon() @@ -59,6 +83,7 @@ func GetProcessLabel() (string, error) { return "", nil } +// SetFileLabel modifies the "path" label to the specified file label func SetFileLabel(path string, fileLabel string) error { if selinux.SelinuxEnabled() && fileLabel != "" { return selinux.Setfilecon(path, fileLabel) @@ -83,17 +108,22 @@ func Relabel(path string, fileLabel string, relabel string) error { return selinux.Chcon(path, fileLabel, true) } -func GetPidCon(pid int) (string, error) { +// GetPidLabel will return the label of the process running with the specified pid +func GetPidLabel(pid int) (string, error) { if !selinux.SelinuxEnabled() { return "", nil } return selinux.Getpidcon(pid) } +// Init initialises the labeling system func Init() { selinux.SelinuxEnabled() } +// ReserveLabel will record the fact that the MCS label has already been used. +// This will prevent InitLabels from using the MCS label in a newly created +// container func ReserveLabel(label string) error { selinux.ReserveLabel(label) return nil diff --git a/vendor/src/github.com/docker/libcontainer/label/label_selinux_test.go b/vendor/src/github.com/docker/libcontainer/label/label_selinux_test.go new file mode 100644 index 0000000000..c83654f6b5 --- /dev/null +++ b/vendor/src/github.com/docker/libcontainer/label/label_selinux_test.go @@ -0,0 +1,48 @@ +// +build selinux,linux + +package label + +import ( + "testing" + + "github.com/docker/libcontainer/selinux" +) + +func TestInit(t *testing.T) { + if selinux.SelinuxEnabled() { + var testNull []string + plabel, mlabel, err := InitLabels(testNull) + if err != nil { + t.Log("InitLabels Failed") + t.Fatal(err) + } + testDisabled := []string{"disable"} + plabel, mlabel, err = InitLabels(testDisabled) + if err != nil { + t.Log("InitLabels Disabled Failed") + t.Fatal(err) + } + if plabel != "" { + t.Log("InitLabels Disabled Failed") + t.Fatal() + } + testUser := []string{"user:user_u", "role:user_r", "type:user_t", "level:s0:c1,c15"} + plabel, mlabel, err = InitLabels(testUser) + if err != nil { + t.Log("InitLabels User Failed") + t.Fatal(err) + } + if plabel != "user_u:user_r:user_t:s0:c1,c15" || mlabel != "user_u:object_r:svirt_sandbox_file_t:s0:c1,c15" { + t.Log("InitLabels User Failed") + t.Log(plabel, mlabel) + t.Fatal(err) + } + + testBadData := []string{"user", "role:user_r", "type:user_t", "level:s0:c1,c15"} + plabel, mlabel, err = InitLabels(testBadData) + if err == nil { + t.Log("InitLabels Bad Failed") + t.Fatal(err) + } + } +} diff --git a/vendor/src/github.com/docker/libcontainer/namespaces/init.go b/vendor/src/github.com/docker/libcontainer/namespaces/init.go index e43db3965c..0e678b67ab 100644 --- a/vendor/src/github.com/docker/libcontainer/namespaces/init.go +++ b/vendor/src/github.com/docker/libcontainer/namespaces/init.go @@ -9,7 +9,6 @@ import ( "strings" "syscall" - "github.com/docker/docker/pkg/user" "github.com/docker/libcontainer" "github.com/docker/libcontainer/apparmor" "github.com/docker/libcontainer/console" @@ -21,6 +20,7 @@ import ( "github.com/docker/libcontainer/security/restrict" "github.com/docker/libcontainer/syncpipe" "github.com/docker/libcontainer/system" + "github.com/docker/libcontainer/user" "github.com/docker/libcontainer/utils" ) @@ -119,7 +119,7 @@ func Init(container *libcontainer.Config, uncleanRootfs, consolePath string, syn return fmt.Errorf("restore parent death signal %s", err) } - return system.Execv(args[0], args[0:], container.Env) + return system.Execv(args[0], args[0:], os.Environ()) } // RestoreParentDeathSignal sets the parent death signal to old. @@ -152,7 +152,7 @@ func RestoreParentDeathSignal(old int) error { // SetupUser changes the groups, gid, and uid for the user inside the container func SetupUser(u string) error { - uid, gid, suppGids, err := user.GetUserGroupSupplementary(u, syscall.Getuid(), syscall.Getgid()) + uid, gid, suppGids, home, err := user.GetUserGroupSupplementaryHome(u, syscall.Getuid(), syscall.Getgid(), "/") if err != nil { return fmt.Errorf("get supplementary groups %s", err) } @@ -169,6 +169,13 @@ func SetupUser(u string) error { return fmt.Errorf("setuid %s", err) } + // if we didn't get HOME already, set it based on the user's HOME + if envHome := os.Getenv("HOME"); envHome == "" { + if err := os.Setenv("HOME", home); err != nil { + return fmt.Errorf("set HOME %s", err) + } + } + return nil } diff --git a/vendor/src/github.com/docker/libcontainer/namespaces/nsenter.go b/vendor/src/github.com/docker/libcontainer/namespaces/nsenter.go index cddfa44253..bf05628ce4 100644 --- a/vendor/src/github.com/docker/libcontainer/namespaces/nsenter.go +++ b/vendor/src/github.com/docker/libcontainer/namespaces/nsenter.go @@ -3,7 +3,6 @@ package namespaces /* -#include #include #include #include @@ -12,7 +11,6 @@ package namespaces #include #include #include -#include #include #include #include @@ -145,36 +143,31 @@ void nsenter() { char ns_dir[PATH_MAX]; memset(ns_dir, 0, PATH_MAX); snprintf(ns_dir, PATH_MAX - 1, "/proc/%d/ns/", init_pid); - struct dirent *dent; - DIR *dir = opendir(ns_dir); - if (dir == NULL) { - fprintf(stderr, "nsenter: Failed to open directory \"%s\" with error: \"%s\"\n", ns_dir, strerror(errno)); - exit(1); - } - while((dent = readdir(dir)) != NULL) { - if(strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0 || strcmp(dent->d_name, "user") == 0) { - continue; - } - - // Get and open the namespace for the init we are joining.. + char* namespaces[] = {"ipc", "uts", "net", "pid", "mnt"}; + const int num = sizeof(namespaces) / sizeof(char*); + int i; + for (i = 0; i < num; i++) { char buf[PATH_MAX]; memset(buf, 0, PATH_MAX); - snprintf(buf, PATH_MAX - 1, "%s%s", ns_dir, dent->d_name); + snprintf(buf, PATH_MAX - 1, "%s%s", ns_dir, namespaces[i]); int fd = open(buf, O_RDONLY); if (fd == -1) { - fprintf(stderr, "nsenter: Failed to open ns file \"%s\" for ns \"%s\" with error: \"%s\"\n", buf, dent->d_name, strerror(errno)); + // Ignore nonexistent namespaces. + if (errno == ENOENT) + continue; + + fprintf(stderr, "nsenter: Failed to open ns file \"%s\" for ns \"%s\" with error: \"%s\"\n", buf, namespaces[i], strerror(errno)); exit(1); } // Set the namespace. if (setns(fd, 0) == -1) { - fprintf(stderr, "nsenter: Failed to setns for \"%s\" with error: \"%s\"\n", dent->d_name, strerror(errno)); + fprintf(stderr, "nsenter: Failed to setns for \"%s\" with error: \"%s\"\n", namespaces[i], strerror(errno)); exit(1); } close(fd); } - closedir(dir); // We must fork to actually enter the PID namespace. int child = fork(); diff --git a/vendor/src/github.com/docker/libcontainer/system/sysconfig.go b/vendor/src/github.com/docker/libcontainer/system/sysconfig.go index 3e2f43b1e9..5efddefa79 100644 --- a/vendor/src/github.com/docker/libcontainer/system/sysconfig.go +++ b/vendor/src/github.com/docker/libcontainer/system/sysconfig.go @@ -1,4 +1,4 @@ -// +build linux,cgo +// +build cgo package system diff --git a/vendor/src/github.com/docker/libcontainer/system/sysconfig_notcgo.go b/vendor/src/github.com/docker/libcontainer/system/sysconfig_notcgo.go index 4bbb69896f..663db82bce 100644 --- a/vendor/src/github.com/docker/libcontainer/system/sysconfig_notcgo.go +++ b/vendor/src/github.com/docker/libcontainer/system/sysconfig_notcgo.go @@ -1,4 +1,4 @@ -// +build linux,!cgo +// +build !cgo package system diff --git a/pkg/user/MAINTAINERS b/vendor/src/github.com/docker/libcontainer/user/MAINTAINERS similarity index 100% rename from pkg/user/MAINTAINERS rename to vendor/src/github.com/docker/libcontainer/user/MAINTAINERS diff --git a/pkg/user/user.go b/vendor/src/github.com/docker/libcontainer/user/user.go similarity index 87% rename from pkg/user/user.go rename to vendor/src/github.com/docker/libcontainer/user/user.go index df47101221..493dd86f20 100644 --- a/pkg/user/user.go +++ b/vendor/src/github.com/docker/libcontainer/user/user.go @@ -165,12 +165,13 @@ func parseGroupFile(r io.Reader, filter func(*Group) bool) ([]*Group, error) { return out, nil } -// Given a string like "user", "1000", "user:group", "1000:1000", returns the uid, gid, and list of supplementary group IDs, if possible. -func GetUserGroupSupplementary(userSpec string, defaultUid int, defaultGid int) (int, int, []int, error) { +// Given a string like "user", "1000", "user:group", "1000:1000", returns the uid, gid, list of supplementary group IDs, and home directory, if available and/or applicable. +func GetUserGroupSupplementaryHome(userSpec string, defaultUid, defaultGid int, defaultHome string) (int, int, []int, string, error) { var ( uid = defaultUid gid = defaultGid suppGids = []int{} + home = defaultHome userArg, groupArg string ) @@ -188,7 +189,7 @@ func GetUserGroupSupplementary(userSpec string, defaultUid int, defaultGid int) if userArg == "" { userArg = strconv.Itoa(uid) } - return 0, 0, nil, fmt.Errorf("Unable to find user %v: %v", userArg, err) + return 0, 0, nil, "", fmt.Errorf("Unable to find user %v: %v", userArg, err) } haveUser := users != nil && len(users) > 0 @@ -196,15 +197,16 @@ func GetUserGroupSupplementary(userSpec string, defaultUid int, defaultGid int) // if we found any user entries that matched our filter, let's take the first one as "correct" uid = users[0].Uid gid = users[0].Gid + home = users[0].Home } else if userArg != "" { // we asked for a user but didn't find them... let's check to see if we wanted a numeric user uid, err = strconv.Atoi(userArg) if err != nil { // not numeric - we have to bail - return 0, 0, nil, fmt.Errorf("Unable to find user %v", userArg) + return 0, 0, nil, "", fmt.Errorf("Unable to find user %v", userArg) } if uid < minId || uid > maxId { - return 0, 0, nil, ErrRange + return 0, 0, nil, "", ErrRange } // if userArg couldn't be found in /etc/passwd but is numeric, just roll with it - this is legit @@ -223,7 +225,7 @@ func GetUserGroupSupplementary(userSpec string, defaultUid int, defaultGid int) return false }) if err != nil && !os.IsNotExist(err) { - return 0, 0, nil, fmt.Errorf("Unable to find groups for user %v: %v", users[0].Name, err) + return 0, 0, nil, "", fmt.Errorf("Unable to find groups for user %v: %v", users[0].Name, err) } haveGroup := groups != nil && len(groups) > 0 @@ -236,10 +238,10 @@ func GetUserGroupSupplementary(userSpec string, defaultUid int, defaultGid int) gid, err = strconv.Atoi(groupArg) if err != nil { // not numeric - we have to bail - return 0, 0, nil, fmt.Errorf("Unable to find group %v", groupArg) + return 0, 0, nil, "", fmt.Errorf("Unable to find group %v", groupArg) } if gid < minId || gid > maxId { - return 0, 0, nil, ErrRange + return 0, 0, nil, "", ErrRange } // if groupArg couldn't be found in /etc/group but is numeric, just roll with it - this is legit @@ -252,5 +254,5 @@ func GetUserGroupSupplementary(userSpec string, defaultUid int, defaultGid int) } } - return uid, gid, suppGids, nil + return uid, gid, suppGids, home, nil } diff --git a/pkg/user/user_test.go b/vendor/src/github.com/docker/libcontainer/user/user_test.go similarity index 100% rename from pkg/user/user_test.go rename to vendor/src/github.com/docker/libcontainer/user/user_test.go