mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge pull request #7312 from tianon/update-libcontainer
Bump libcontainer dep
This commit is contained in:
commit
b1496effe3
20 changed files with 170 additions and 57 deletions
|
@ -27,10 +27,10 @@ import (
|
||||||
"github.com/docker/docker/pkg/listenbuffer"
|
"github.com/docker/docker/pkg/listenbuffer"
|
||||||
"github.com/docker/docker/pkg/parsers"
|
"github.com/docker/docker/pkg/parsers"
|
||||||
"github.com/docker/docker/pkg/systemd"
|
"github.com/docker/docker/pkg/systemd"
|
||||||
"github.com/docker/docker/pkg/user"
|
|
||||||
"github.com/docker/docker/pkg/version"
|
"github.com/docker/docker/pkg/version"
|
||||||
"github.com/docker/docker/registry"
|
"github.com/docker/docker/registry"
|
||||||
"github.com/docker/docker/utils"
|
"github.com/docker/docker/utils"
|
||||||
|
"github.com/docker/libcontainer/user"
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -121,7 +121,7 @@ func (b *buildFile) CmdFrom(name string) error {
|
||||||
b.config = image.Config
|
b.config = image.Config
|
||||||
}
|
}
|
||||||
if b.config.Env == nil || len(b.config.Env) == 0 {
|
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
|
// Process ONBUILD triggers if they exist
|
||||||
if nTriggers := len(b.config.OnBuild); nTriggers != 0 {
|
if nTriggers := len(b.config.OnBuild); nTriggers != 0 {
|
||||||
|
|
|
@ -1043,9 +1043,12 @@ func (container *Container) setupLinkedContainers() ([]string, error) {
|
||||||
func (container *Container) createDaemonEnvironment(linkedEnv []string) []string {
|
func (container *Container) createDaemonEnvironment(linkedEnv []string) []string {
|
||||||
// Setup environment
|
// Setup environment
|
||||||
env := []string{
|
env := []string{
|
||||||
"HOME=/",
|
|
||||||
"PATH=" + DefaultPathEnv,
|
"PATH=" + DefaultPathEnv,
|
||||||
"HOSTNAME=" + container.Config.Hostname,
|
"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 {
|
if container.Config.Tty {
|
||||||
env = append(env, "TERM=xterm")
|
env = append(env, "TERM=xterm")
|
||||||
|
|
|
@ -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/godbus/dbus v1
|
||||||
clone git github.com/coreos/go-systemd v2
|
clone git github.com/coreos/go-systemd v2
|
||||||
clone git github.com/docker/libcontainer e6a43c1c2b9f769deb96348a0a93417cd48a36d8
|
clone git github.com/docker/libcontainer bc06326a5e7decdc4191d1367de8439b9d83c450
|
||||||
|
|
|
@ -723,7 +723,7 @@ func TestBuildRelativeWorkdir(t *testing.T) {
|
||||||
|
|
||||||
func TestBuildEnv(t *testing.T) {
|
func TestBuildEnv(t *testing.T) {
|
||||||
name := "testbuildenv"
|
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)
|
defer deleteImages(name)
|
||||||
_, err := buildImage(name,
|
_, err := buildImage(name,
|
||||||
`FROM busybox
|
`FROM busybox
|
||||||
|
|
|
@ -657,7 +657,7 @@ func TestRunTwoConcurrentContainers(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEnvironment(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(),
|
cmd.Env = append(os.Environ(),
|
||||||
"TRUE=false",
|
"TRUE=false",
|
||||||
"TRICKY=tri\ncky\n",
|
"TRICKY=tri\ncky\n",
|
||||||
|
@ -676,13 +676,13 @@ func TestEnvironment(t *testing.T) {
|
||||||
|
|
||||||
goodEnv := []string{
|
goodEnv := []string{
|
||||||
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||||
"HOME=/",
|
|
||||||
"HOSTNAME=testing",
|
"HOSTNAME=testing",
|
||||||
"FALSE=true",
|
"FALSE=true",
|
||||||
"TRUE=false",
|
"TRUE=false",
|
||||||
"TRICKY=tri",
|
"TRICKY=tri",
|
||||||
"cky",
|
"cky",
|
||||||
"",
|
"",
|
||||||
|
"HOME=/root",
|
||||||
}
|
}
|
||||||
sort.Strings(goodEnv)
|
sort.Strings(goodEnv)
|
||||||
if len(goodEnv) != len(actualEnv) {
|
if len(goodEnv) != len(actualEnv) {
|
||||||
|
|
|
@ -21,10 +21,10 @@ install:
|
||||||
- if [ -z "$TRAVIS_GLOBAL_WTF" ]; then go env; fi
|
- if [ -z "$TRAVIS_GLOBAL_WTF" ]; then go env; fi
|
||||||
- go get -d -v ./...
|
- go get -d -v ./...
|
||||||
- if [ "$TRAVIS_GLOBAL_WTF" ]; then
|
- 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";
|
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} );
|
( cd "$DOCKER_PATH/hack/make" && wget -c 'https://raw.githubusercontent.com/docker/docker/master/hack/make/'{.validate,validate-dco,validate-gofmt} );
|
||||||
sed -i 's!dotcloud/docker!docker/libcontainer!' "$DOCKER_PATH/hack/make/.validate";
|
sed -i 's!docker/docker!docker/libcontainer!' "$DOCKER_PATH/hack/make/.validate";
|
||||||
fi
|
fi
|
||||||
|
|
||||||
script:
|
script:
|
||||||
|
|
|
@ -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:
|
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``
|
* Note: the above script expects to find your GitHub user name in ``git config --get github.user``
|
||||||
|
|
|
@ -150,6 +150,10 @@ func (raw *data) parent(subsystem string) (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (raw *data) path(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)
|
parent, err := raw.parent(subsystem)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
|
|
@ -5,6 +5,8 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/docker/libcontainer/cgroups"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -66,3 +68,20 @@ func TestGetCgroupParamsInt(t *testing.T) {
|
||||||
t.Fatal("Expecting error, got none")
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2,6 +2,13 @@
|
||||||
|
|
||||||
package label
|
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) {
|
func GenLabels(options string) (string, string, error) {
|
||||||
return "", "", nil
|
return "", "", nil
|
||||||
}
|
}
|
||||||
|
@ -22,7 +29,7 @@ func Relabel(path string, fileLabel string, relabel string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetPidCon(pid int) (string, error) {
|
func GetPidLabel(pid int) (string, error) {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,30 +9,49 @@ import (
|
||||||
"github.com/docker/libcontainer/selinux"
|
"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() {
|
if !selinux.SelinuxEnabled() {
|
||||||
return "", "", nil
|
return "", "", nil
|
||||||
}
|
}
|
||||||
var err error
|
var err error
|
||||||
processLabel, mountLabel := selinux.GetLxcContexts()
|
processLabel, mountLabel := selinux.GetLxcContexts()
|
||||||
if processLabel != "" {
|
if processLabel != "" {
|
||||||
var (
|
pcon := selinux.NewContext(processLabel)
|
||||||
s = strings.Fields(options)
|
mcon := selinux.NewContext(mountLabel)
|
||||||
l = len(s)
|
for _, opt := range options {
|
||||||
)
|
if opt == "disable" {
|
||||||
if l > 0 {
|
return "", "", nil
|
||||||
pcon := selinux.NewContext(processLabel)
|
}
|
||||||
for i := 0; i < l; i++ {
|
if i := strings.Index(opt, ":"); i == -1 {
|
||||||
o := strings.Split(s[i], "=")
|
return "", "", fmt.Errorf("Bad SELinux Option")
|
||||||
pcon[o[0]] = o[1]
|
}
|
||||||
|
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
|
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 {
|
func FormatMountLabel(src, mountLabel string) string {
|
||||||
if mountLabel != "" {
|
if mountLabel != "" {
|
||||||
switch src {
|
switch src {
|
||||||
|
@ -45,6 +64,8 @@ func FormatMountLabel(src, mountLabel string) string {
|
||||||
return src
|
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 {
|
func SetProcessLabel(processLabel string) error {
|
||||||
if selinux.SelinuxEnabled() {
|
if selinux.SelinuxEnabled() {
|
||||||
return selinux.Setexeccon(processLabel)
|
return selinux.Setexeccon(processLabel)
|
||||||
|
@ -52,6 +73,9 @@ func SetProcessLabel(processLabel string) error {
|
||||||
return nil
|
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) {
|
func GetProcessLabel() (string, error) {
|
||||||
if selinux.SelinuxEnabled() {
|
if selinux.SelinuxEnabled() {
|
||||||
return selinux.Getexeccon()
|
return selinux.Getexeccon()
|
||||||
|
@ -59,6 +83,7 @@ func GetProcessLabel() (string, error) {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetFileLabel modifies the "path" label to the specified file label
|
||||||
func SetFileLabel(path string, fileLabel string) error {
|
func SetFileLabel(path string, fileLabel string) error {
|
||||||
if selinux.SelinuxEnabled() && fileLabel != "" {
|
if selinux.SelinuxEnabled() && fileLabel != "" {
|
||||||
return selinux.Setfilecon(path, 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)
|
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() {
|
if !selinux.SelinuxEnabled() {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
return selinux.Getpidcon(pid)
|
return selinux.Getpidcon(pid)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Init initialises the labeling system
|
||||||
func Init() {
|
func Init() {
|
||||||
selinux.SelinuxEnabled()
|
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 {
|
func ReserveLabel(label string) error {
|
||||||
selinux.ReserveLabel(label)
|
selinux.ReserveLabel(label)
|
||||||
return nil
|
return nil
|
||||||
|
|
48
vendor/src/github.com/docker/libcontainer/label/label_selinux_test.go
vendored
Normal file
48
vendor/src/github.com/docker/libcontainer/label/label_selinux_test.go
vendored
Normal file
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,7 +9,6 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/docker/docker/pkg/user"
|
|
||||||
"github.com/docker/libcontainer"
|
"github.com/docker/libcontainer"
|
||||||
"github.com/docker/libcontainer/apparmor"
|
"github.com/docker/libcontainer/apparmor"
|
||||||
"github.com/docker/libcontainer/console"
|
"github.com/docker/libcontainer/console"
|
||||||
|
@ -21,6 +20,7 @@ import (
|
||||||
"github.com/docker/libcontainer/security/restrict"
|
"github.com/docker/libcontainer/security/restrict"
|
||||||
"github.com/docker/libcontainer/syncpipe"
|
"github.com/docker/libcontainer/syncpipe"
|
||||||
"github.com/docker/libcontainer/system"
|
"github.com/docker/libcontainer/system"
|
||||||
|
"github.com/docker/libcontainer/user"
|
||||||
"github.com/docker/libcontainer/utils"
|
"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 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.
|
// 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
|
// SetupUser changes the groups, gid, and uid for the user inside the container
|
||||||
func SetupUser(u string) error {
|
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 {
|
if err != nil {
|
||||||
return fmt.Errorf("get supplementary groups %s", err)
|
return fmt.Errorf("get supplementary groups %s", err)
|
||||||
}
|
}
|
||||||
|
@ -169,6 +169,13 @@ func SetupUser(u string) error {
|
||||||
return fmt.Errorf("setuid %s", err)
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
package namespaces
|
package namespaces
|
||||||
|
|
||||||
/*
|
/*
|
||||||
#include <dirent.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <linux/limits.h>
|
#include <linux/limits.h>
|
||||||
|
@ -12,7 +11,6 @@ package namespaces
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
|
@ -145,36 +143,31 @@ void nsenter() {
|
||||||
char ns_dir[PATH_MAX];
|
char ns_dir[PATH_MAX];
|
||||||
memset(ns_dir, 0, PATH_MAX);
|
memset(ns_dir, 0, PATH_MAX);
|
||||||
snprintf(ns_dir, PATH_MAX - 1, "/proc/%d/ns/", init_pid);
|
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) {
|
char* namespaces[] = {"ipc", "uts", "net", "pid", "mnt"};
|
||||||
if(strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0 || strcmp(dent->d_name, "user") == 0) {
|
const int num = sizeof(namespaces) / sizeof(char*);
|
||||||
continue;
|
int i;
|
||||||
}
|
for (i = 0; i < num; i++) {
|
||||||
|
|
||||||
// Get and open the namespace for the init we are joining..
|
|
||||||
char buf[PATH_MAX];
|
char buf[PATH_MAX];
|
||||||
memset(buf, 0, 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);
|
int fd = open(buf, O_RDONLY);
|
||||||
if (fd == -1) {
|
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);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the namespace.
|
// Set the namespace.
|
||||||
if (setns(fd, 0) == -1) {
|
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);
|
exit(1);
|
||||||
}
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
closedir(dir);
|
|
||||||
|
|
||||||
// We must fork to actually enter the PID namespace.
|
// We must fork to actually enter the PID namespace.
|
||||||
int child = fork();
|
int child = fork();
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// +build linux,cgo
|
// +build cgo
|
||||||
|
|
||||||
package system
|
package system
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// +build linux,!cgo
|
// +build !cgo
|
||||||
|
|
||||||
package system
|
package system
|
||||||
|
|
||||||
|
|
|
@ -165,12 +165,13 @@ func parseGroupFile(r io.Reader, filter func(*Group) bool) ([]*Group, error) {
|
||||||
return out, nil
|
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.
|
// 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 GetUserGroupSupplementary(userSpec string, defaultUid int, defaultGid int) (int, int, []int, error) {
|
func GetUserGroupSupplementaryHome(userSpec string, defaultUid, defaultGid int, defaultHome string) (int, int, []int, string, error) {
|
||||||
var (
|
var (
|
||||||
uid = defaultUid
|
uid = defaultUid
|
||||||
gid = defaultGid
|
gid = defaultGid
|
||||||
suppGids = []int{}
|
suppGids = []int{}
|
||||||
|
home = defaultHome
|
||||||
|
|
||||||
userArg, groupArg string
|
userArg, groupArg string
|
||||||
)
|
)
|
||||||
|
@ -188,7 +189,7 @@ func GetUserGroupSupplementary(userSpec string, defaultUid int, defaultGid int)
|
||||||
if userArg == "" {
|
if userArg == "" {
|
||||||
userArg = strconv.Itoa(uid)
|
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
|
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"
|
// if we found any user entries that matched our filter, let's take the first one as "correct"
|
||||||
uid = users[0].Uid
|
uid = users[0].Uid
|
||||||
gid = users[0].Gid
|
gid = users[0].Gid
|
||||||
|
home = users[0].Home
|
||||||
} else if userArg != "" {
|
} else if userArg != "" {
|
||||||
// we asked for a user but didn't find them... let's check to see if we wanted a numeric user
|
// 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)
|
uid, err = strconv.Atoi(userArg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// not numeric - we have to bail
|
// 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 {
|
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
|
// 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
|
return false
|
||||||
})
|
})
|
||||||
if err != nil && !os.IsNotExist(err) {
|
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
|
haveGroup := groups != nil && len(groups) > 0
|
||||||
|
@ -236,10 +238,10 @@ func GetUserGroupSupplementary(userSpec string, defaultUid int, defaultGid int)
|
||||||
gid, err = strconv.Atoi(groupArg)
|
gid, err = strconv.Atoi(groupArg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// not numeric - we have to bail
|
// 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 {
|
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
|
// 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
|
||||||
}
|
}
|
Loading…
Reference in a new issue