restrict.go 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445
  1. // +build linux
  2. package restrict
  3. import (
  4. "fmt"
  5. "os"
  6. "syscall"
  7. "github.com/dotcloud/docker/pkg/system"
  8. )
  9. const defaultMountFlags = syscall.MS_NOEXEC | syscall.MS_NOSUID | syscall.MS_NODEV
  10. func mountReadonly(path string) error {
  11. if err := system.Mount("", path, "", syscall.MS_REMOUNT|syscall.MS_RDONLY, ""); err != nil {
  12. if err == syscall.EINVAL {
  13. // Probably not a mountpoint, use bind-mount
  14. if err := system.Mount(path, path, "", syscall.MS_BIND, ""); err != nil {
  15. return err
  16. }
  17. if err := system.Mount(path, path, "", syscall.MS_BIND|syscall.MS_REMOUNT|syscall.MS_RDONLY|syscall.MS_REC|defaultMountFlags, ""); err != nil {
  18. return err
  19. }
  20. } else {
  21. return err
  22. }
  23. }
  24. return nil
  25. }
  26. // This has to be called while the container still has CAP_SYS_ADMIN (to be able to perform mounts).
  27. // However, afterwards, CAP_SYS_ADMIN should be dropped (otherwise the user will be able to revert those changes).
  28. func Restrict(mounts ...string) error {
  29. // remount proc and sys as readonly
  30. for _, dest := range mounts {
  31. if err := mountReadonly(dest); err != nil {
  32. return fmt.Errorf("unable to remount %s readonly: %s", dest, err)
  33. }
  34. }
  35. if err := system.Mount("/dev/null", "/proc/kcore", "", syscall.MS_BIND, ""); err != nil && !os.IsNotExist(err) {
  36. return fmt.Errorf("unable to bind-mount /dev/null over /proc/kcore: %s", err)
  37. }
  38. return nil
  39. }