Skip to content

Commit

Permalink
Chown files when copying into chroot
Browse files Browse the repository at this point in the history
Fixes #2552

Not needed when hardlinking. Only adds Linux support but other OS's may
be easy.
  • Loading branch information
schmichael committed Apr 12, 2017
1 parent c005d29 commit e854ee6
Show file tree
Hide file tree
Showing 8 changed files with 49 additions and 11 deletions.
12 changes: 10 additions & 2 deletions client/allocdir/alloc_dir.go
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,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 {
Expand All @@ -400,7 +402,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 >= 0 && gid >= 0 {
if err := dstFile.Chown(uid, gid); err != nil {
return fmt.Errorf("Couldn't copy %q to %q: %v", src, dst, err)
}
}

return nil
Expand Down
5 changes: 5 additions & 0 deletions client/allocdir/fs_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,8 @@ func createSecretDir(dir string) error {
func removeSecretDir(dir string) error {
return os.RemoveAll(dir)
}

// getOwner isn't implemented for Darwin
func getOwner(os.FileInfo) (int, int) {
return -1, -1
}
5 changes: 5 additions & 0 deletions client/allocdir/fs_freebsd.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,8 @@ func createSecretDir(dir string) error {
func removeSecretDir(dir string) error {
return os.RemoveAll(dir)
}

// getOwner isn't implemented for FreeBSD
func getOwner(os.FileInfo) (int, int) {
return -1, -1
}
8 changes: 8 additions & 0 deletions client/allocdir/fs_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,11 @@ func removeSecretDir(dir string) error {
}
return os.RemoveAll(dir)
}

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)
}
5 changes: 5 additions & 0 deletions client/allocdir/fs_solaris.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,8 @@ func createSecretDir(dir string) error {
func removeSecretDir(dir string) error {
return os.RemoveAll(dir)
}

// getOwner isn't implemented for Solaris
func getOwner(os.FileInfo) (int, int) {
return -1, -1
}
10 changes: 5 additions & 5 deletions client/allocdir/fs_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,17 +82,17 @@ 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.
if fileInfo, _ := os.Stat(dst); fileInfo != nil {
return nil
}
// Attempt to hardlink.
if err := os.Link(src, dst); err == nil {
return nil
}
//if err := os.Link(src, dst); err == nil {
// return nil
//}

return fileCopy(src, dst, perm)
return fileCopy(src, dst, uid, gid, perm)
}
9 changes: 7 additions & 2 deletions client/allocdir/fs_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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 -1, -1
}
6 changes: 4 additions & 2 deletions client/allocdir/task_dir.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down Expand Up @@ -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
}
}
Expand Down

0 comments on commit e854ee6

Please sign in to comment.