Replace mount fork hack with CLONE_FS
This change spins up a new goroutine, locks it to a thread, then unshares CLONE_FS which allows us to `Chdir` from inside the thread without affecting the rest of the program. The thread is no longer usable after unshare so it leaves the thread locked to prevent go from returning the thread to the thread pool. Signed-off-by: Brian Goff <cpuguy83@gmail.com>
This commit is contained in:
@@ -21,6 +21,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -363,24 +364,29 @@ func mountAt(chdir string, source, target, fstype string, flags uintptr, data st
|
||||
return unix.Mount(source, target, fstype, flags, data)
|
||||
}
|
||||
|
||||
f, err := os.Open(chdir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to mountat: %w", err)
|
||||
}
|
||||
defer f.Close()
|
||||
ch := make(chan error, 1)
|
||||
go func() {
|
||||
runtime.LockOSThread()
|
||||
|
||||
fs, err := f.Stat()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to mountat: %w", err)
|
||||
}
|
||||
// Do not unlock this thread.
|
||||
// If the thread is unlocked go will try to use it for other goroutines.
|
||||
// However it is not possible to restore the thread state after CLONE_FS.
|
||||
//
|
||||
// Once the goroutine exits the thread should eventually be terminated by go.
|
||||
|
||||
if !fs.IsDir() {
|
||||
return fmt.Errorf("failed to mountat: %s is not dir", chdir)
|
||||
}
|
||||
if err := fMountat(f.Fd(), source, target, fstype, flags, data); err != nil {
|
||||
return fmt.Errorf("failed to mountat: %w", err)
|
||||
}
|
||||
return nil
|
||||
if err := unix.Unshare(unix.CLONE_FS); err != nil {
|
||||
ch <- err
|
||||
return
|
||||
}
|
||||
|
||||
if err := unix.Chdir(chdir); err != nil {
|
||||
ch <- err
|
||||
return
|
||||
}
|
||||
|
||||
ch <- unix.Mount(source, target, fstype, flags, data)
|
||||
}()
|
||||
return <-ch
|
||||
}
|
||||
|
||||
func (m *Mount) mountWithHelper(helperBinary, typePrefix, target string) error {
|
||||
|
||||
Reference in New Issue
Block a user