Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save crosbymichael/e12c9d12b6cfecd0f843 to your computer and use it in GitHub Desktop.
Save crosbymichael/e12c9d12b6cfecd0f843 to your computer and use it in GitHub Desktop.
From 9e959f559e4aa9891da9fc628a9946bd1615d412 Mon Sep 17 00:00:00 2001
From: Michael Crosby <michael@docker.com>
Date: Fri, 25 Jul 2014 15:28:05 -0700
Subject: [PATCH] Changes to uid gid mappings
---
src/pkg/syscall/exec_linux.go | 29 ++++++++++++++--------
src/pkg/syscall/exec_unix.go | 58 ++++++++++++++++++++++++++++++++++++++++---
2 files changed, 73 insertions(+), 14 deletions(-)
diff --git a/src/pkg/syscall/exec_linux.go b/src/pkg/syscall/exec_linux.go
index f27950f..8a20da0 100644
--- a/src/pkg/syscall/exec_linux.go
+++ b/src/pkg/syscall/exec_linux.go
@@ -6,9 +6,7 @@
package syscall
-import (
- "unsafe"
-)
+import "unsafe"
type SysProcAttr struct {
Chroot string // Chroot.
@@ -36,7 +34,7 @@ func runtime_AfterFork()
// For the same reason compiler does not race instrument it.
// The calls to RawSyscall are okay because they are assembly
// functions that do not grow the stack.
-func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err Errno) {
+func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, sys *SysProcAttr, child, parent int) (pid int, err Errno) {
// Declare all variables at top in case any
// declarations require heap allocation (e.g., err1).
var (
@@ -44,6 +42,7 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
err1 Errno
nextfd int
i int
+ lzero uintptr
)
// Guard against side effects of shuffling fds below.
@@ -75,6 +74,16 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
}
// Fork succeeded, now in child.
+ if _, _, err1 = RawSyscall(SYS_CLOSE, uintptr(child), 0, 0); err != 0 {
+ goto childerror
+ }
+
+ if sys.Credential != nil && (sys.Credential.UidMapping != "" || sys.Credential.GidMapping != "") {
+ _, _, err1 = RawSyscall(SYS_READ, uintptr(parent), uintptr(unsafe.Pointer(&lzero)), uintptr(1))
+ if err1 != 0 {
+ goto childerror
+ }
+ }
// Parent death signal
if sys.Pdeathsig != 0 {
@@ -159,13 +168,13 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
// Pass 1: look for fd[i] < i and move those up above len(fd)
// so that pass 2 won't stomp on an fd it needs later.
- if pipe < nextfd {
- _, _, err1 = RawSyscall(SYS_DUP2, uintptr(pipe), uintptr(nextfd), 0)
+ if child < nextfd {
+ _, _, err1 = RawSyscall(SYS_DUP2, uintptr(child), uintptr(nextfd), 0)
if err1 != 0 {
goto childerror
}
RawSyscall(SYS_FCNTL, uintptr(nextfd), F_SETFD, FD_CLOEXEC)
- pipe = nextfd
+ child = nextfd
nextfd++
}
for i = 0; i < len(fd); i++ {
@@ -177,7 +186,7 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
RawSyscall(SYS_FCNTL, uintptr(nextfd), F_SETFD, FD_CLOEXEC)
fd[i] = nextfd
nextfd++
- if nextfd == pipe { // don't stomp on pipe
+ if nextfd == child { // don't stomp on child
nextfd++
}
}
@@ -237,8 +246,8 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
uintptr(unsafe.Pointer(&envv[0])))
childerror:
- // send error code on pipe
- RawSyscall(SYS_WRITE, uintptr(pipe), uintptr(unsafe.Pointer(&err1)), unsafe.Sizeof(err1))
+ // send error code on child
+ RawSyscall(SYS_WRITE, uintptr(child), uintptr(unsafe.Pointer(&err1)), unsafe.Sizeof(err1))
for {
RawSyscall(SYS_EXIT, 253, 0, 0)
}
diff --git a/src/pkg/syscall/exec_unix.go b/src/pkg/syscall/exec_unix.go
index 890bfdc..301999e 100644
--- a/src/pkg/syscall/exec_unix.go
+++ b/src/pkg/syscall/exec_unix.go
@@ -110,9 +110,11 @@ func SetNonblock(fd int, nonblocking bool) (err error) {
// Credential holds user and group identities to be assumed
// by a child process started by StartProcess.
type Credential struct {
- Uid uint32 // User ID.
- Gid uint32 // Group ID.
- Groups []uint32 // Supplementary group IDs.
+ Uid uint32 // User ID.
+ Gid uint32 // Group ID.
+ Groups []uint32 // Supplementary group IDs.
+ UidMapping string
+ GidMapping string
}
// ProcAttr holds attributes that will be applied to a new process started
@@ -188,17 +190,24 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error)
}
// Kick off child.
- pid, err1 = forkAndExecInChild(argv0p, argvp, envvp, chroot, dir, attr, sys, p[1])
+ pid, err1 = forkAndExecInChild(argv0p, argvp, envvp, chroot, dir, attr, sys, p[1], p[0])
if err1 != 0 {
err = Errno(err1)
goto error
}
ForkLock.Unlock()
+ if sys.Credential != nil {
+ if err = writeUidGidMappings(pid, sys.Credential); err != nil {
+ goto error
+ }
+ }
+
// Read child error status from pipe.
Close(p[1])
n, err = readlen(p[0], (*byte)(unsafe.Pointer(&err1)), int(unsafe.Sizeof(err1)))
Close(p[0])
+
if err != nil || n != 0 {
if n == int(unsafe.Sizeof(err1)) {
err = Errno(err1)
@@ -259,3 +268,44 @@ func Exec(argv0 string, argv []string, envv []string) (err error) {
uintptr(unsafe.Pointer(&envvp[0])))
return Errno(err1)
}
+
+func writeUidGidMappings(pid int, cred *Credential) error {
+ var (
+ uidf = "/proc/" + itoa(pid) + "/uid_map"
+ gidf = "/proc/" + itoa(pid) + "/gid_map"
+ )
+
+ if cred.UidMapping != "" {
+ fd, err := Open(uidf, O_RDWR, 0)
+ if err != nil {
+ return err
+ }
+
+ data := StringByteSlice(cred.UidMapping)
+ if _, err := Write(fd, data); err != nil {
+ Close(fd)
+
+ return err
+ }
+
+ Close(fd)
+ }
+
+ if cred.GidMapping != "" {
+ fd, err := Open(gidf, O_RDWR, 0)
+ if err != nil {
+ return err
+ }
+
+ data := StringByteSlice(cred.GidMapping)
+ if _, err := Write(fd, data); err != nil {
+ Close(fd)
+
+ return err
+ }
+
+ Close(fd)
+ }
+
+ return nil
+}
--
1.9.3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment