summaryrefslogtreecommitdiffhomepage
path: root/runsc/specutils/specutils.go
diff options
context:
space:
mode:
authorFabricio Voznika <fvoznika@google.com>2019-03-18 12:29:43 -0700
committerShentubot <shentubot@google.com>2019-03-18 12:30:43 -0700
commite420cc3e5d2066674d32d16ad885bee6b30da210 (patch)
tree991b119af7c8816a539318560338b3e5f065a2f8 /runsc/specutils/specutils.go
parenteb69542807a87491fd4e6405bdab1c0f64db536d (diff)
Add support for mount propagation
Properly handle propagation options for root and mounts. Now usage of mount options shared, rshared, and noexec cause error to start. shared/ rshared breaks sandbox=>host isolation. slave however can be supported because changes propagate from host to sandbox. Root FS setup moved inside the gofer. Apart from simplifying the code, it keeps all mounts inside the namespace. And they are torn down when the namespace is destroyed (DestroyFS is no longer needed). PiperOrigin-RevId: 239037661 Change-Id: I8b5ee4d50da33c042ea34fa68e56514ebe20e6e0
Diffstat (limited to 'runsc/specutils/specutils.go')
-rw-r--r--runsc/specutils/specutils.go52
1 files changed, 25 insertions, 27 deletions
diff --git a/runsc/specutils/specutils.go b/runsc/specutils/specutils.go
index 4e7893ab4..cbf099c64 100644
--- a/runsc/specutils/specutils.go
+++ b/runsc/specutils/specutils.go
@@ -92,9 +92,14 @@ func ValidateSpec(spec *specs.Spec) error {
log.Warningf("Seccomp spec is being ignored")
}
- for i, m := range spec.Mounts {
- if !path.IsAbs(m.Destination) {
- return fmt.Errorf("Spec.Mounts[%d] Mount.Destination must be an absolute path: %v", i, m)
+ if spec.Linux != nil && spec.Linux.RootfsPropagation != "" {
+ if err := validateRootfsPropagation(spec.Linux.RootfsPropagation); err != nil {
+ return err
+ }
+ }
+ for _, m := range spec.Mounts {
+ if err := validateMount(&m); err != nil {
+ return err
}
}
@@ -129,15 +134,19 @@ func absPath(base, rel string) string {
return filepath.Join(base, rel)
}
+// OpenSpec opens an OCI runtime spec from the given bundle directory.
+func OpenSpec(bundleDir string) (*os.File, error) {
+ // The spec file must be named "config.json" inside the bundle directory.
+ return os.Open(filepath.Join(bundleDir, "config.json"))
+}
+
// ReadSpec reads an OCI runtime spec from the given bundle directory.
// ReadSpec also normalizes all potential relative paths into absolute
// path, e.g. spec.Root.Path, mount.Source.
func ReadSpec(bundleDir string) (*specs.Spec, error) {
- // The spec file must be in "config.json" inside the bundle directory.
- specPath := filepath.Join(bundleDir, "config.json")
- specFile, err := os.Open(specPath)
+ specFile, err := OpenSpec(bundleDir)
if err != nil {
- return nil, fmt.Errorf("error opening spec file %q: %v", specPath, err)
+ return nil, fmt.Errorf("error opening spec file %q: %v", specFile.Name(), err)
}
defer specFile.Close()
return ReadSpecFromFile(bundleDir, specFile)
@@ -171,27 +180,17 @@ func ReadSpecFromFile(bundleDir string, specFile *os.File) (*specs.Spec, error)
return &spec, nil
}
-// OpenCleanSpec opens spec file that has destination mount paths resolved to
-// their absolute location.
-func OpenCleanSpec(bundleDir string) (*os.File, error) {
- f, err := os.Open(filepath.Join(bundleDir, "config.clean.json"))
+// ReadMounts reads mount list from a file.
+func ReadMounts(f *os.File) ([]specs.Mount, error) {
+ bytes, err := ioutil.ReadAll(f)
if err != nil {
- return nil, err
+ return nil, fmt.Errorf("error reading mounts: %v", err)
}
- if _, err := f.Seek(0, os.SEEK_SET); err != nil {
- f.Close()
- return nil, fmt.Errorf("error seeking to beginning of file %q: %v", f.Name(), err)
- }
- return f, nil
-}
-
-// WriteCleanSpec writes a spec file that has destination mount paths resolved.
-func WriteCleanSpec(bundleDir string, spec *specs.Spec) error {
- bytes, err := json.Marshal(spec)
- if err != nil {
- return err
+ var mounts []specs.Mount
+ if err := json.Unmarshal(bytes, &mounts); err != nil {
+ return nil, fmt.Errorf("error unmarshaling mounts: %v\n %s", err, string(bytes))
}
- return ioutil.WriteFile(filepath.Join(bundleDir, "config.clean.json"), bytes, 0755)
+ return mounts, nil
}
// Capabilities takes in spec and returns a TaskCapabilities corresponding to
@@ -407,8 +406,7 @@ func Mount(src, dst, typ string, flags uint32) error {
// source (file or directory).
var isDir bool
if typ == "proc" {
- // Special case, as there is no source directory for proc
- // mounts.
+ // Special case, as there is no source directory for proc mounts.
isDir = true
} else if fi, err := os.Stat(src); err != nil {
return fmt.Errorf("Stat(%q) failed: %v", src, err)