github.com/hhrutter/nomad@v0.6.0-rc2.0.20170723054333-80c4b03f0705/client/allocdir/fs_linux.go (about)

     1  package allocdir
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"path/filepath"
     7  	"syscall"
     8  
     9  	"golang.org/x/sys/unix"
    10  )
    11  
    12  const (
    13  	// secretDirTmpfsSize is the size of the tmpfs per task in MBs
    14  	secretDirTmpfsSize = 1
    15  
    16  	// secretMarker is the filename of the marker created so Nomad doesn't
    17  	// try to mount the secrets tmpfs more than once
    18  	secretMarker = ".nomad-mount"
    19  )
    20  
    21  // linkDir bind mounts src to dst as Linux doesn't support hardlinking
    22  // directories.
    23  func linkDir(src, dst string) error {
    24  	if err := os.MkdirAll(dst, 0777); err != nil {
    25  		return err
    26  	}
    27  
    28  	return syscall.Mount(src, dst, "", syscall.MS_BIND, "")
    29  }
    30  
    31  // unlinkDir unmounts a bind mounted directory as Linux doesn't support
    32  // hardlinking directories. If the dir is already unmounted no error is
    33  // returned.
    34  func unlinkDir(dir string) error {
    35  	if err := syscall.Unmount(dir, 0); err != nil {
    36  		if err != syscall.EINVAL {
    37  			return err
    38  		}
    39  	}
    40  	return nil
    41  }
    42  
    43  // createSecretDir creates the secrets dir folder at the given path using a
    44  // tmpfs
    45  func createSecretDir(dir string) error {
    46  	// Only mount the tmpfs if we are root
    47  	if unix.Geteuid() == 0 {
    48  		if err := os.MkdirAll(dir, 0777); err != nil {
    49  			return err
    50  		}
    51  
    52  		// Check for marker file and skip mounting if it exists
    53  		marker := filepath.Join(dir, secretMarker)
    54  		if _, err := os.Stat(marker); err == nil {
    55  			return nil
    56  		}
    57  
    58  		var flags uintptr
    59  		flags = syscall.MS_NOEXEC
    60  		options := fmt.Sprintf("size=%dm", secretDirTmpfsSize)
    61  		if err := syscall.Mount("tmpfs", dir, "tmpfs", flags, options); err != nil {
    62  			return os.NewSyscallError("mount", err)
    63  		}
    64  
    65  		// Create the marker file so we don't try to mount more than once
    66  		f, err := os.OpenFile(marker, os.O_RDWR|os.O_CREATE, 0666)
    67  		if err != nil {
    68  			// Hard fail since if this fails something is really wrong
    69  			return err
    70  		}
    71  		f.Close()
    72  		return nil
    73  	}
    74  
    75  	return os.MkdirAll(dir, 0777)
    76  }
    77  
    78  // createSecretDir removes the secrets dir folder
    79  func removeSecretDir(dir string) error {
    80  	if unix.Geteuid() == 0 {
    81  		if err := unlinkDir(dir); err != nil {
    82  			// Ignore invalid path errors
    83  			if err != syscall.ENOENT {
    84  				return os.NewSyscallError("unmount", err)
    85  			}
    86  		}
    87  
    88  	}
    89  	return os.RemoveAll(dir)
    90  }