xianlubird / mydocker

<<自己动手写docker>> 源码
Apache License 2.0
1.98k stars 560 forks source link

Code-4.1 syscall.PivotRoot error: invalid argument #62

Open Ssx5 opened 4 years ago

Ssx5 commented 4 years ago

root@Ss-PC:/home/song12300560/gopath/src/github.com/xianlubird/mydocker# ./mydocker run -ti sh {"level":"info","msg":"command all is sh","time":"2019-11-14T19:29:59+08:00"} {"level":"info","msg":"init come on","time":"2019-11-14T19:29:59+08:00"} {"level":"info","msg":"Current location is /root/busybox","time":"2019-11-14T19:29:59+08:00"} {"level":"info","msg":"syscall.PivotRoot(/root/busybox, /root/busybox/.pivot_root)","time":"2019-11-14T19:29:59+08:00"} {"level":"fatal","msg":"pivotRoot error: pivot_root invalid argument","time":"2019-11-14T19:29:59+08:00"} root@Ss-PC:/home/song12300560/gopath/src/github.com/xianlubird/mydocker# 输出如上面所示,源码code-4.1

pibigstar commented 4 years ago

pivotRoot 方法前面添加 下面代码

// systemd 加入linux之后, mount namespace 就变成 shared by default, 所以你必须显示
//声明你要这个新的mount namespace独立。
err = syscall.Mount("", "/", "", syscall.MS_PRIVATE|syscall.MS_REC, "")
Joey777210 commented 4 years ago

同样是pivot_root这里,我加入了这个方法之后,在busybox中,所有的mount点和PID都没有了 控制台 time="2020-02-23T23:02:56-08:00" level=info msg="args: [/tmp/___go_build_Socker run -ti sh]" {"level":"info","msg":"command init write is sh","time":"2020-02-23T23:02:56-08:00"} {"level":"info","msg":"socker: exit container","time":"2020-02-23T23:02:56-08:00"} {"level":"info","msg":"init come on","time":"2020-02-23T23:02:56-08:00"} {"level":"info","msg":"command in init is [sh]","time":"2020-02-23T23:02:56-08:00"} {"level":"info","msg":"Current location is /home/joey/go/busybox","time":"2020-02-23T23:02:56-08:00"} {"level":"error","msg":"mount2 error : operation not permitted","time":"2020-02-23T23:02:56-08:00"} time="2020-02-23T23:02:56-08:00" level=info msg="args: [/proc/self/exe init]"

报错的代码是这里: defaultMountFlags := syscall.MS_NOEXEC | syscall.MS_NOSUID | syscall.MS_NODEV err2 := syscall.Mount("proc", "/proc", "proc", uintptr(defaultMountFlags), "") if err2 != nil { log.Errorf("mount2 error : %v", err2) }

Joey777210 commented 4 years ago

同时,如果我在进入busybox容器中后,使用命令 mount -t proc proc /proc 进行手动mount,会提示我没有权限

CaiJinKen commented 4 years ago

@Joey777210 是的,我也同样遇到这个问题了,请问你最后解决了没有?我一直就卡在这了

hxia043 commented 1 year ago
func pivotRoot(root string) error {
    if err := syscall.Mount("", "/", "", syscall.MS_PRIVATE|syscall.MS_REC, ""); err != nil {
        return err
    }

    // Mount the new root as a new filesystem
    if err := syscall.Mount(root, root, "", syscall.MS_BIND|syscall.MS_PRIVATE, ""); err != nil {
        return fmt.Errorf("mount rootfs to itself failed: %v", err)
    }

    // Create a new directory for the old root
    pivotDir := filepath.Join(root, ".pivot_root")
    if err := os.Mkdir(pivotDir, 0700); err != nil {
        return err
    }

    // Pivot the root directory
    if err := syscall.PivotRoot(root, pivotDir); err != nil {
        return fmt.Errorf("pivot_root %v", err)
    }

    // Change the current working directory to "/"
    if err := syscall.Chdir("/"); err != nil {
        return fmt.Errorf("chdir %v", err)
    }

    // Unmount the old root
    pivotDir = filepath.Join("/", ".pivot_root")
    if err := syscall.Unmount(pivotDir, syscall.MNT_DETACH); err != nil {
        return fmt.Errorf("umount pivot_root dir %v", err)
    }

    return os.Remove(pivotDir)
}
lin-coco commented 8 months ago

@hxia043 syscall.Mount(root, root, "", syscall.MS_BIND|syscall.MS_PRIVATE, "") 这行代码是不是可以省略了,我自己试了一下,加不加效果都一样