mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
runsc:gofer: don't mount a new proc instance
If the existing proc instance has over-mounted areas, it can be impossible to mount a new /proc instance (look at SB_I_USERNS_VISIBLE for more details). Actually, runsc-gofer needs /proc just to open /proc/self/fd and to read a few generic files, so it doesn't need a proc instance of the target pid namespace. Fixes #8205 PiperOrigin-RevId: 609634818
This commit is contained in:
@@ -42,7 +42,7 @@ import (
|
||||
func init() {
|
||||
log.SetLevel(log.Debug)
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
if err := fsgofer.OpenProcSelfFD(); err != nil {
|
||||
if err := fsgofer.OpenProcSelfFD("/proc/self/fd"); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
+28
-18
@@ -219,7 +219,11 @@ func (g *Gofer) Execute(_ context.Context, f *flag.FlagSet, args ...any) subcomm
|
||||
// modes exactly as sent by the sandbox, which will have applied its own umask.
|
||||
unix.Umask(0)
|
||||
|
||||
if err := fsgofer.OpenProcSelfFD(); err != nil {
|
||||
procFDPath := procFDBindMount
|
||||
if conf.TestOnlyAllowRunAsCurrentUserWithoutChroot {
|
||||
procFDPath = "/proc/self/fd"
|
||||
}
|
||||
if err := fsgofer.OpenProcSelfFD(procFDPath); err != nil {
|
||||
util.Fatalf("failed to open /proc/self/fd: %v", err)
|
||||
}
|
||||
|
||||
@@ -358,6 +362,10 @@ func (g *Gofer) writeMounts(mounts []specs.Mount) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Redhat distros don't allow to create bind-mounts in /proc/self directories.
|
||||
// It is protected by selinux rules.
|
||||
const procFDBindMount = "/proc/fs"
|
||||
|
||||
func (g *Gofer) setupRootFS(spec *specs.Spec, conf *config.Config) error {
|
||||
// Convert all shared mounts into slaves to be sure that nothing will be
|
||||
// propagated outside of our namespace.
|
||||
@@ -375,36 +383,38 @@ func (g *Gofer) setupRootFS(spec *specs.Spec, conf *config.Config) error {
|
||||
// We need a directory to construct a new root and we know that
|
||||
// runsc can't start without /proc, so we can use it for this.
|
||||
flags := uintptr(unix.MS_NOSUID | unix.MS_NODEV | unix.MS_NOEXEC)
|
||||
if err := specutils.SafeMount("runsc-root", "/proc", "tmpfs", flags, "", procPath); err != nil {
|
||||
if err := specutils.SafeMount("runsc-root", "/proc/fs", "tmpfs", flags, "", procPath); err != nil {
|
||||
util.Fatalf("error mounting tmpfs: %v", err)
|
||||
}
|
||||
|
||||
if err := unix.Mount("", "/proc/fs", "", unix.MS_UNBINDABLE, ""); err != nil {
|
||||
util.Fatalf("error setting MS_UNBINDABLE")
|
||||
}
|
||||
// Prepare tree structure for pivot_root(2).
|
||||
if err := os.Mkdir("/proc/proc", 0755); err != nil {
|
||||
util.Fatalf("error creating /proc/proc: %v", err)
|
||||
if err := os.Mkdir("/proc/fs/proc", 0755); err != nil {
|
||||
util.Fatalf("error creating /proc/fs/proc: %v", err)
|
||||
}
|
||||
if err := os.Mkdir("/proc/root", 0755); err != nil {
|
||||
util.Fatalf("error creating /proc/root: %v", err)
|
||||
if err := os.Mkdir("/proc/fs/root", 0755); err != nil {
|
||||
util.Fatalf("error creating /proc/fs/root: %v", err)
|
||||
}
|
||||
if err := os.Mkdir("/proc/etc", 0755); err != nil {
|
||||
util.Fatalf("error creating /proc/etc: %v", err)
|
||||
if err := os.Mkdir("/proc/fs/etc", 0755); err != nil {
|
||||
util.Fatalf("error creating /proc/fs/etc: %v", err)
|
||||
}
|
||||
// This cannot use SafeMount because there's no available procfs. But we
|
||||
// know that /proc is an empty tmpfs mount, so this is safe.
|
||||
if err := unix.Mount("runsc-proc", "/proc/proc", "proc", flags|unix.MS_RDONLY, ""); err != nil {
|
||||
util.Fatalf("error mounting proc: %v", err)
|
||||
// know that /proc/fs is an empty tmpfs mount, so this is safe.
|
||||
if err := unix.Mount("/proc", "/proc/fs/proc", "", flags|unix.MS_RDONLY|unix.MS_BIND|unix.MS_REC, ""); err != nil {
|
||||
util.Fatalf("error mounting /proc/fs/proc: %v", err)
|
||||
}
|
||||
// self/fd is bind-mounted, so that the FD return by
|
||||
// OpenProcSelfFD() does not allow escapes with walking ".." .
|
||||
if err := unix.Mount("/proc/proc/self/fd", "/proc/proc/self/fd",
|
||||
"", unix.MS_RDONLY|unix.MS_BIND|unix.MS_NOEXEC, ""); err != nil {
|
||||
if err := unix.Mount("/proc/fs/proc/self/fd", "/proc/fs/"+procFDBindMount,
|
||||
"", unix.MS_RDONLY|unix.MS_BIND|flags, ""); err != nil {
|
||||
util.Fatalf("error mounting proc/self/fd: %v", err)
|
||||
}
|
||||
if err := copyFile("/proc/etc/localtime", "/etc/localtime"); err != nil {
|
||||
if err := copyFile("/proc/fs/etc/localtime", "/etc/localtime"); err != nil {
|
||||
log.Warningf("Failed to copy /etc/localtime: %v. UTC timezone will be used.", err)
|
||||
}
|
||||
root = "/proc/root"
|
||||
procPath = "/proc/proc"
|
||||
root = "/proc/fs/root"
|
||||
procPath = "/proc/fs/proc"
|
||||
}
|
||||
|
||||
rootfsConf := g.mountConfs[0]
|
||||
@@ -461,7 +471,7 @@ func (g *Gofer) setupRootFS(spec *specs.Spec, conf *config.Config) error {
|
||||
}
|
||||
|
||||
if !conf.TestOnlyAllowRunAsCurrentUserWithoutChroot {
|
||||
if err := pivotRoot("/proc"); err != nil {
|
||||
if err := pivotRoot("/proc/fs"); err != nil {
|
||||
util.Fatalf("failed to change the root file system: %v", err)
|
||||
}
|
||||
if err := os.Chdir("/"); err != nil {
|
||||
|
||||
@@ -69,8 +69,8 @@ var procSelfFD *rwfd.FD
|
||||
|
||||
// OpenProcSelfFD opens the /proc/self/fd directory, which will be used to
|
||||
// reopen file descriptors.
|
||||
func OpenProcSelfFD() error {
|
||||
d, err := unix.Open("/proc/self/fd", unix.O_RDONLY|unix.O_DIRECTORY, 0)
|
||||
func OpenProcSelfFD(path string) error {
|
||||
d, err := unix.Open(path, unix.O_RDONLY|unix.O_DIRECTORY, 0)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error opening /proc/self/fd: %v", err)
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ import (
|
||||
|
||||
func init() {
|
||||
log.SetLevel(log.Debug)
|
||||
if err := fsgofer.OpenProcSelfFD(); err != nil {
|
||||
if err := fsgofer.OpenProcSelfFD("/proc/self/fd"); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user