checkProcMount checks to ensure that the mount destination is not over the top of /proc. dest is required to be an abs path and have any symlinks resolved before calling this function. If m is nil, don't stat the filesystem. This is used for restore of a checkpoint.
(rootfs, dest string, m mountEntry)
| 837 | // |
| 838 | // If m is nil, don't stat the filesystem. This is used for restore of a checkpoint. |
| 839 | func checkProcMount(rootfs, dest string, m mountEntry) error { |
| 840 | const procPath = "/proc" |
| 841 | path, err := filepath.Rel(filepath.Join(rootfs, procPath), dest) |
| 842 | if err != nil { |
| 843 | return err |
| 844 | } |
| 845 | // pass if the mount path is located outside of /proc |
| 846 | if strings.HasPrefix(path, "..") { |
| 847 | return nil |
| 848 | } |
| 849 | if path == "." { |
| 850 | // Only allow bind-mounts on top of /proc, and only if the source is a |
| 851 | // procfs mount. |
| 852 | if m.IsBind() { |
| 853 | fsSt, err := m.srcStatfs() |
| 854 | if err != nil { |
| 855 | return err |
| 856 | } |
| 857 | if fsSt.Type == unix.PROC_SUPER_MAGIC { |
| 858 | if _, uSt, err := m.srcStat(); err != nil { |
| 859 | return err |
| 860 | } else if uSt.Ino != procRootIno { |
| 861 | // We cannot error out in this case, because we've |
| 862 | // supported these kinds of mounts for a long time. |
| 863 | // However, we would expect users to bind-mount the root of |
| 864 | // a real procfs on top of /proc in the container. We might |
| 865 | // want to block this in the future. |
| 866 | logrus.Warnf("bind-mount %v (source %v) is of type procfs but is not the root of a procfs (inode %d). Future versions of runc might block this configuration -- please report an issue to <https://github.com/opencontainers/runc> if you see this warning.", dest, m.srcName(), uSt.Ino) |
| 867 | } |
| 868 | return nil |
| 869 | } |
| 870 | } else if m.Device == "proc" { |
| 871 | // Fresh procfs-type mounts are always safe to mount on top of /proc. |
| 872 | return nil |
| 873 | } |
| 874 | return fmt.Errorf("%q cannot be mounted because it is not of type proc", dest) |
| 875 | } |
| 876 | |
| 877 | // Here dest is definitely under /proc. Do not allow those, |
| 878 | // except for a few specific entries emulated by lxcfs. |
| 879 | validProcMounts := []string{ |
| 880 | "/proc/cpuinfo", |
| 881 | "/proc/diskstats", |
| 882 | "/proc/meminfo", |
| 883 | "/proc/stat", |
| 884 | "/proc/swaps", |
| 885 | "/proc/uptime", |
| 886 | "/proc/loadavg", |
| 887 | "/proc/slabinfo", |
| 888 | "/proc/sys/kernel/ns_last_pid", |
| 889 | "/proc/sys/crypto/fips_enabled", |
| 890 | } |
| 891 | for _, valid := range validProcMounts { |
| 892 | path, err := filepath.Rel(filepath.Join(rootfs, valid), dest) |
| 893 | if err != nil { |
| 894 | return err |
| 895 | } |
| 896 | if path == "." { |
searching dependent graphs…