Merge pull request #2553 from hashicorp/b-2552-chown-on-copy
Chown files when copying into chroot
This commit is contained in:
commit
291f4f0b44
|
@ -19,6 +19,7 @@ BUG FIXES:
|
|||
* client/artifact: Honor netrc [GH-2524]
|
||||
* client/artifact: Handle tars where file in directory is listed before
|
||||
directory [GH-2524]
|
||||
* driver/exec: Properly set file/dir ownership in chroots [GH-2552]
|
||||
* server: Reject non-TLS clients when TLS enabled [GH-2525]
|
||||
* server: Fix a panic in plan evaluation with partial failures and all_at_once
|
||||
set [GH-2544]
|
||||
|
|
|
@ -17,6 +17,12 @@ import (
|
|||
"github.com/hpcloud/tail/watch"
|
||||
)
|
||||
|
||||
const (
|
||||
// idUnsupported is what the uid/gid will be set to on platforms (eg
|
||||
// Windows) that don't support integer ownership identifiers.
|
||||
idUnsupported = -1
|
||||
)
|
||||
|
||||
var (
|
||||
// The name of the directory that is shared across tasks in a task group.
|
||||
SharedAllocName = "alloc"
|
||||
|
@ -385,7 +391,9 @@ func getFileWatcher(path string) watch.FileWatcher {
|
|||
return watch.NewPollingFileWatcher(path)
|
||||
}
|
||||
|
||||
func fileCopy(src, dst string, perm os.FileMode) error {
|
||||
// fileCopy from src to dst setting the permissions and owner (if uid & gid are
|
||||
// both greater than 0)
|
||||
func fileCopy(src, dst string, uid, gid int, perm os.FileMode) error {
|
||||
// Do a simple copy.
|
||||
srcFile, err := os.Open(src)
|
||||
if err != nil {
|
||||
|
@ -400,7 +408,13 @@ func fileCopy(src, dst string, perm os.FileMode) error {
|
|||
defer dstFile.Close()
|
||||
|
||||
if _, err := io.Copy(dstFile, srcFile); err != nil {
|
||||
return fmt.Errorf("Couldn't copy %v to %v: %v", src, dst, err)
|
||||
return fmt.Errorf("Couldn't copy %q to %q: %v", src, dst, err)
|
||||
}
|
||||
|
||||
if uid != idUnsupported && gid != idUnsupported {
|
||||
if err := dstFile.Chown(uid, gid); err != nil {
|
||||
return fmt.Errorf("Couldn't copy %q to %q: %v", src, dst, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -448,6 +462,12 @@ func createDir(basePath, relPath string) error {
|
|||
if err := os.MkdirAll(destDir, fi.Perm); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if fi.Uid != idUnsupported && fi.Gid != idUnsupported {
|
||||
if err := os.Chown(destDir, fi.Uid, fi.Gid); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -456,6 +476,10 @@ func createDir(basePath, relPath string) error {
|
|||
type fileInfo struct {
|
||||
Name string
|
||||
Perm os.FileMode
|
||||
|
||||
// Uid and Gid are unsupported on Windows
|
||||
Uid int
|
||||
Gid int
|
||||
}
|
||||
|
||||
// splitPath stats each subdirectory of a path. The first element of the array
|
||||
|
@ -463,17 +487,19 @@ type fileInfo struct {
|
|||
// path.
|
||||
func splitPath(path string) ([]fileInfo, error) {
|
||||
var mode os.FileMode
|
||||
i, err := os.Stat(path)
|
||||
fi, err := os.Stat(path)
|
||||
|
||||
// If the path is not present in the host then we respond with the most
|
||||
// flexible permission.
|
||||
uid, gid := idUnsupported, idUnsupported
|
||||
if err != nil {
|
||||
mode = os.ModePerm
|
||||
} else {
|
||||
mode = i.Mode()
|
||||
uid, gid = getOwner(fi)
|
||||
mode = fi.Mode()
|
||||
}
|
||||
var dirs []fileInfo
|
||||
dirs = append(dirs, fileInfo{Name: path, Perm: mode})
|
||||
dirs = append(dirs, fileInfo{Name: path, Perm: mode, Uid: uid, Gid: gid})
|
||||
currentDir := path
|
||||
for {
|
||||
dir := filepath.Dir(filepath.Clean(currentDir))
|
||||
|
@ -483,13 +509,15 @@ func splitPath(path string) ([]fileInfo, error) {
|
|||
|
||||
// We try to find the permission of the file in the host. If the path is not
|
||||
// present in the host then we respond with the most flexible permission.
|
||||
i, err = os.Stat(dir)
|
||||
uid, gid := idUnsupported, idUnsupported
|
||||
fi, err := os.Stat(dir)
|
||||
if err != nil {
|
||||
mode = os.ModePerm
|
||||
} else {
|
||||
mode = i.Mode()
|
||||
uid, gid = getOwner(fi)
|
||||
mode = fi.Mode()
|
||||
}
|
||||
dirs = append(dirs, fileInfo{Name: dir, Perm: mode})
|
||||
dirs = append(dirs, fileInfo{Name: dir, Perm: mode, Uid: uid, Gid: gid})
|
||||
currentDir = dir
|
||||
}
|
||||
return dirs, nil
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"os/user"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
@ -82,7 +83,7 @@ func getGid(u *user.User) (int, error) {
|
|||
|
||||
// linkOrCopy attempts to hardlink dst to src and fallsback to copying if the
|
||||
// hardlink fails.
|
||||
func linkOrCopy(src, dst string, perm os.FileMode) error {
|
||||
func linkOrCopy(src, dst string, uid, gid int, perm os.FileMode) error {
|
||||
// Avoid link/copy if the file already exists in the chroot
|
||||
// TODO 0.6 clean this up. This was needed because chroot creation fails
|
||||
// when a process restarts.
|
||||
|
@ -94,5 +95,13 @@ func linkOrCopy(src, dst string, perm os.FileMode) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
return fileCopy(src, dst, perm)
|
||||
return fileCopy(src, dst, uid, gid, perm)
|
||||
}
|
||||
|
||||
func getOwner(fi os.FileInfo) (int, int) {
|
||||
stat, ok := fi.Sys().(*syscall.Stat_t)
|
||||
if !ok {
|
||||
return -1, -1
|
||||
}
|
||||
return int(stat.Uid), int(stat.Gid)
|
||||
}
|
||||
|
|
|
@ -21,8 +21,8 @@ var (
|
|||
)
|
||||
|
||||
// linkOrCopy is always copies dst to src on Windows.
|
||||
func linkOrCopy(src, dst string, perm os.FileMode) error {
|
||||
return fileCopy(src, dst, perm)
|
||||
func linkOrCopy(src, dst string, uid, gid int, perm os.FileMode) error {
|
||||
return fileCopy(src, dst, uid, gid, perm)
|
||||
}
|
||||
|
||||
// The windows version does nothing currently.
|
||||
|
@ -70,3 +70,8 @@ func MountSpecialDirs(taskDir string) error {
|
|||
func unmountSpecialDirs(taskDir string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// getOwner doesn't work on Windows as Windows doesn't use int user IDs
|
||||
func getOwner(os.FileInfo) (int, int) {
|
||||
return idUnsupported, idUnsupported
|
||||
}
|
||||
|
|
|
@ -163,7 +163,8 @@ func (t *TaskDir) embedDirs(entries map[string]string) error {
|
|||
|
||||
// Copy the file.
|
||||
taskEntry := filepath.Join(t.Dir, dest)
|
||||
if err := linkOrCopy(source, taskEntry, s.Mode().Perm()); err != nil {
|
||||
uid, gid := getOwner(s)
|
||||
if err := linkOrCopy(source, taskEntry, uid, gid, s.Mode().Perm()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -217,7 +218,8 @@ func (t *TaskDir) embedDirs(entries map[string]string) error {
|
|||
continue
|
||||
}
|
||||
|
||||
if err := linkOrCopy(hostEntry, taskEntry, entry.Mode().Perm()); err != nil {
|
||||
uid, gid := getOwner(entry)
|
||||
if err := linkOrCopy(hostEntry, taskEntry, uid, gid, entry.Mode().Perm()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue