github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/client/allocdir/fs_unix.go (about)

     1  //go:build unix
     2  
     3  package allocdir
     4  
     5  import (
     6  	"fmt"
     7  	"os"
     8  	"os/user"
     9  	"path/filepath"
    10  	"strconv"
    11  	"syscall"
    12  
    13  	"github.com/hashicorp/nomad/helper/users"
    14  	"golang.org/x/sys/unix"
    15  )
    16  
    17  var (
    18  	// SharedAllocContainerPath is the path inside container for mounted
    19  	// directory shared across tasks in a task group.
    20  	SharedAllocContainerPath = filepath.Join("/", SharedAllocName)
    21  
    22  	// TaskLocalContainerPath is the path inside a container for mounted directory
    23  	// for local storage.
    24  	TaskLocalContainerPath = filepath.Join("/", TaskLocal)
    25  
    26  	// TaskSecretsContainerPath is the path inside a container for mounted
    27  	// secrets directory
    28  	TaskSecretsContainerPath = filepath.Join("/", TaskSecrets)
    29  )
    30  
    31  // dropDirPermissions gives full access to a directory to all users and sets
    32  // the owner to nobody.
    33  func dropDirPermissions(path string, desired os.FileMode) error {
    34  	if err := os.Chmod(path, desired|0777); err != nil {
    35  		return fmt.Errorf("Chmod(%v) failed: %v", path, err)
    36  	}
    37  
    38  	// Can't change owner if not root.
    39  	if unix.Geteuid() != 0 {
    40  		return nil
    41  	}
    42  
    43  	nobody := users.Nobody()
    44  
    45  	uid, err := getUid(&nobody)
    46  	if err != nil {
    47  		return err
    48  	}
    49  
    50  	gid, err := getGid(&nobody)
    51  	if err != nil {
    52  		return err
    53  	}
    54  
    55  	if err := os.Chown(path, uid, gid); err != nil {
    56  		return fmt.Errorf("Couldn't change owner/group of %v to (uid: %v, gid: %v): %v", path, uid, gid, err)
    57  	}
    58  
    59  	return nil
    60  }
    61  
    62  // getUid for a user
    63  func getUid(u *user.User) (int, error) {
    64  	uid, err := strconv.Atoi(u.Uid)
    65  	if err != nil {
    66  		return 0, fmt.Errorf("Unable to convert Uid to an int: %v", err)
    67  	}
    68  
    69  	return uid, nil
    70  }
    71  
    72  // getGid for a user
    73  func getGid(u *user.User) (int, error) {
    74  	gid, err := strconv.Atoi(u.Gid)
    75  	if err != nil {
    76  		return 0, fmt.Errorf("Unable to convert Gid to an int: %v", err)
    77  	}
    78  
    79  	return gid, nil
    80  }
    81  
    82  // linkOrCopy attempts to hardlink dst to src and fallsback to copying if the
    83  // hardlink fails.
    84  func linkOrCopy(src, dst string, uid, gid int, perm os.FileMode) error {
    85  	// Avoid link/copy if the file already exists in the chroot
    86  	// TODO 0.6 clean this up. This was needed because chroot creation fails
    87  	// when a process restarts.
    88  	if fileInfo, _ := os.Stat(dst); fileInfo != nil {
    89  		return nil
    90  	}
    91  	// Attempt to hardlink.
    92  	if err := os.Link(src, dst); err == nil {
    93  		return nil
    94  	}
    95  
    96  	return fileCopy(src, dst, uid, gid, perm)
    97  }
    98  
    99  func getOwner(fi os.FileInfo) (int, int) {
   100  	stat, ok := fi.Sys().(*syscall.Stat_t)
   101  	if !ok {
   102  		return -1, -1
   103  	}
   104  	return int(stat.Uid), int(stat.Gid)
   105  }