diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2016-01-11 17:28:34 +0100 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2016-01-11 17:28:34 +0100 |
| commit | 31d1087c3f39cc48bde5983ca43764a366cc0d2c (patch) | |
| tree | 83c9e79c2f2e7a82305b3246db065a67c1a7c343 | |
| parent | 4f3c86c9504d001347f231d8ef0f3690b1d2434d (diff) | |
ipc: umount all mounts before removing temp dirs
This is needed if unshare(CLONE_NEWNS) is not implemented.
Otherwise, os.RemoveAll fails.
| -rw-r--r-- | fileutil/fileutil.go | 14 | ||||
| -rw-r--r-- | ipc/ipc.go | 3 |
2 files changed, 17 insertions, 0 deletions
diff --git a/fileutil/fileutil.go b/fileutil/fileutil.go index a019a14ea..b84088354 100644 --- a/fileutil/fileutil.go +++ b/fileutil/fileutil.go @@ -12,6 +12,7 @@ import ( "strconv" "sync" "syscall" + "unsafe" ) var copyMu sync.Mutex @@ -103,3 +104,16 @@ func ProcessTempDir(where string) (string, int, error) { } return "", 0, fmt.Errorf("too many live instances") } + +// UmountAll recurusively unmounts all mounts in dir. +func UmountAll(dir string) { + files, _ := ioutil.ReadDir(dir) + for _, f := range files { + name := filepath.Join(dir, f.Name()) + if f.IsDir() { + UmountAll(name) + } + fn := []byte(name + "\x00") + syscall.Syscall(syscall.SYS_UMOUNT2, uintptr(unsafe.Pointer(&fn[0])), syscall.MNT_FORCE, 0) + } +} diff --git a/ipc/ipc.go b/ipc/ipc.go index 85904d2fa..95ac83b0b 100644 --- a/ipc/ipc.go +++ b/ipc/ipc.go @@ -16,6 +16,7 @@ import ( "syscall" "time" + "github.com/google/syzkaller/fileutil" "github.com/google/syzkaller/prog" ) @@ -356,6 +357,7 @@ func (c *command) close() { c.kill() c.cmd.Wait() } + fileutil.UmountAll(c.dir) os.RemoveAll(c.dir) if c.rp != nil { c.rp.Close() @@ -400,6 +402,7 @@ func (c *command) exec() (output, strace []byte, failed, hanged bool, err0 error //!!! handle c.rp overflow _, readErr := c.inrp.Read(tmp[:]) close(done) + fileutil.UmountAll(c.dir) os.RemoveAll(c.dir) if err := os.Mkdir(c.dir, 0777); err != nil { <-hang |
