Created
July 25, 2014 22:29
-
-
Save crosbymichael/e12c9d12b6cfecd0f843 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 9e959f559e4aa9891da9fc628a9946bd1615d412 Mon Sep 17 00:00:00 2001 | |
From: Michael Crosby <[email protected]> | |
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