namespaces_unix.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. // +build linux freebsd
  2. package configs
  3. import (
  4. "fmt"
  5. "os"
  6. "sync"
  7. )
  8. const (
  9. NEWNET NamespaceType = "NEWNET"
  10. NEWPID NamespaceType = "NEWPID"
  11. NEWNS NamespaceType = "NEWNS"
  12. NEWUTS NamespaceType = "NEWUTS"
  13. NEWIPC NamespaceType = "NEWIPC"
  14. NEWUSER NamespaceType = "NEWUSER"
  15. )
  16. var (
  17. nsLock sync.Mutex
  18. supportedNamespaces = make(map[NamespaceType]bool)
  19. )
  20. // nsToFile converts the namespace type to its filename
  21. func nsToFile(ns NamespaceType) string {
  22. switch ns {
  23. case NEWNET:
  24. return "net"
  25. case NEWNS:
  26. return "mnt"
  27. case NEWPID:
  28. return "pid"
  29. case NEWIPC:
  30. return "ipc"
  31. case NEWUSER:
  32. return "user"
  33. case NEWUTS:
  34. return "uts"
  35. }
  36. return ""
  37. }
  38. // IsNamespaceSupported returns whether a namespace is available or
  39. // not
  40. func IsNamespaceSupported(ns NamespaceType) bool {
  41. nsLock.Lock()
  42. defer nsLock.Unlock()
  43. supported, ok := supportedNamespaces[ns]
  44. if ok {
  45. return supported
  46. }
  47. nsFile := nsToFile(ns)
  48. // if the namespace type is unknown, just return false
  49. if nsFile == "" {
  50. return false
  51. }
  52. _, err := os.Stat(fmt.Sprintf("/proc/self/ns/%s", nsFile))
  53. // a namespace is supported if it exists and we have permissions to read it
  54. supported = err == nil
  55. supportedNamespaces[ns] = supported
  56. return supported
  57. }
  58. func NamespaceTypes() []NamespaceType {
  59. return []NamespaceType{
  60. NEWNET,
  61. NEWPID,
  62. NEWNS,
  63. NEWUTS,
  64. NEWIPC,
  65. NEWUSER,
  66. }
  67. }
  68. // Namespace defines configuration for each namespace. It specifies an
  69. // alternate path that is able to be joined via setns.
  70. type Namespace struct {
  71. Type NamespaceType `json:"type"`
  72. Path string `json:"path"`
  73. }
  74. func (n *Namespace) GetPath(pid int) string {
  75. if n.Path != "" {
  76. return n.Path
  77. }
  78. return fmt.Sprintf("/proc/%d/ns/%s", pid, nsToFile(n.Type))
  79. }
  80. func (n *Namespaces) Remove(t NamespaceType) bool {
  81. i := n.index(t)
  82. if i == -1 {
  83. return false
  84. }
  85. *n = append((*n)[:i], (*n)[i+1:]...)
  86. return true
  87. }
  88. func (n *Namespaces) Add(t NamespaceType, path string) {
  89. i := n.index(t)
  90. if i == -1 {
  91. *n = append(*n, Namespace{Type: t, Path: path})
  92. return
  93. }
  94. (*n)[i].Path = path
  95. }
  96. func (n *Namespaces) index(t NamespaceType) int {
  97. for i, ns := range *n {
  98. if ns.Type == t {
  99. return i
  100. }
  101. }
  102. return -1
  103. }
  104. func (n *Namespaces) Contains(t NamespaceType) bool {
  105. return n.index(t) != -1
  106. }
  107. func (n *Namespaces) PathOf(t NamespaceType) string {
  108. i := n.index(t)
  109. if i == -1 {
  110. return ""
  111. }
  112. return (*n)[i].Path
  113. }