create.go 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. // +build linux,cgo
  2. package native
  3. import (
  4. "errors"
  5. "fmt"
  6. "net"
  7. "strings"
  8. "syscall"
  9. "github.com/docker/docker/daemon/execdriver"
  10. "github.com/opencontainers/runc/libcontainer/apparmor"
  11. "github.com/opencontainers/runc/libcontainer/configs"
  12. "github.com/opencontainers/runc/libcontainer/devices"
  13. "github.com/opencontainers/runc/libcontainer/utils"
  14. )
  15. // createContainer populates and configures the container type with the
  16. // data provided by the execdriver.Command
  17. func (d *Driver) createContainer(c *execdriver.Command) (*configs.Config, error) {
  18. container := execdriver.InitContainer(c)
  19. if err := d.createIpc(container, c); err != nil {
  20. return nil, err
  21. }
  22. if err := d.createPid(container, c); err != nil {
  23. return nil, err
  24. }
  25. if err := d.createUTS(container, c); err != nil {
  26. return nil, err
  27. }
  28. if err := d.createNetwork(container, c); err != nil {
  29. return nil, err
  30. }
  31. if c.ProcessConfig.Privileged {
  32. if !container.Readonlyfs {
  33. // clear readonly for /sys
  34. for i := range container.Mounts {
  35. if container.Mounts[i].Destination == "/sys" {
  36. container.Mounts[i].Flags &= ^syscall.MS_RDONLY
  37. }
  38. }
  39. container.ReadonlyPaths = nil
  40. }
  41. // clear readonly for cgroup
  42. for i := range container.Mounts {
  43. if container.Mounts[i].Device == "cgroup" {
  44. container.Mounts[i].Flags &= ^syscall.MS_RDONLY
  45. }
  46. }
  47. container.MaskPaths = nil
  48. if err := d.setPrivileged(container); err != nil {
  49. return nil, err
  50. }
  51. } else {
  52. if err := d.setCapabilities(container, c); err != nil {
  53. return nil, err
  54. }
  55. }
  56. container.AdditionalGroups = c.GroupAdd
  57. if c.AppArmorProfile != "" {
  58. container.AppArmorProfile = c.AppArmorProfile
  59. }
  60. if err := execdriver.SetupCgroups(container, c); err != nil {
  61. return nil, err
  62. }
  63. if container.Readonlyfs {
  64. for i := range container.Mounts {
  65. switch container.Mounts[i].Destination {
  66. case "/proc", "/dev", "/dev/pts":
  67. continue
  68. }
  69. container.Mounts[i].Flags |= syscall.MS_RDONLY
  70. }
  71. /* These paths must be remounted as r/o */
  72. container.ReadonlyPaths = append(container.ReadonlyPaths, "/proc", "/dev")
  73. }
  74. if err := d.setupMounts(container, c); err != nil {
  75. return nil, err
  76. }
  77. d.setupLabels(container, c)
  78. d.setupRlimits(container, c)
  79. return container, nil
  80. }
  81. func generateIfaceName() (string, error) {
  82. for i := 0; i < 10; i++ {
  83. name, err := utils.GenerateRandomName("veth", 7)
  84. if err != nil {
  85. continue
  86. }
  87. if _, err := net.InterfaceByName(name); err != nil {
  88. if strings.Contains(err.Error(), "no such") {
  89. return name, nil
  90. }
  91. return "", err
  92. }
  93. }
  94. return "", errors.New("Failed to find name for new interface")
  95. }
  96. func (d *Driver) createNetwork(container *configs.Config, c *execdriver.Command) error {
  97. if c.Network == nil {
  98. return nil
  99. }
  100. if c.Network.ContainerID != "" {
  101. d.Lock()
  102. active := d.activeContainers[c.Network.ContainerID]
  103. d.Unlock()
  104. if active == nil {
  105. return fmt.Errorf("%s is not a valid running container to join", c.Network.ContainerID)
  106. }
  107. state, err := active.State()
  108. if err != nil {
  109. return err
  110. }
  111. container.Namespaces.Add(configs.NEWNET, state.NamespacePaths[configs.NEWNET])
  112. return nil
  113. }
  114. if c.Network.NamespacePath == "" {
  115. return fmt.Errorf("network namespace path is empty")
  116. }
  117. container.Namespaces.Add(configs.NEWNET, c.Network.NamespacePath)
  118. return nil
  119. }
  120. func (d *Driver) createIpc(container *configs.Config, c *execdriver.Command) error {
  121. if c.Ipc.HostIpc {
  122. container.Namespaces.Remove(configs.NEWIPC)
  123. return nil
  124. }
  125. if c.Ipc.ContainerID != "" {
  126. d.Lock()
  127. active := d.activeContainers[c.Ipc.ContainerID]
  128. d.Unlock()
  129. if active == nil {
  130. return fmt.Errorf("%s is not a valid running container to join", c.Ipc.ContainerID)
  131. }
  132. state, err := active.State()
  133. if err != nil {
  134. return err
  135. }
  136. container.Namespaces.Add(configs.NEWIPC, state.NamespacePaths[configs.NEWIPC])
  137. }
  138. return nil
  139. }
  140. func (d *Driver) createPid(container *configs.Config, c *execdriver.Command) error {
  141. if c.Pid.HostPid {
  142. container.Namespaces.Remove(configs.NEWPID)
  143. return nil
  144. }
  145. return nil
  146. }
  147. func (d *Driver) createUTS(container *configs.Config, c *execdriver.Command) error {
  148. if c.UTS.HostUTS {
  149. container.Namespaces.Remove(configs.NEWUTS)
  150. container.Hostname = ""
  151. return nil
  152. }
  153. return nil
  154. }
  155. func (d *Driver) setPrivileged(container *configs.Config) (err error) {
  156. container.Capabilities = execdriver.GetAllCapabilities()
  157. container.Cgroups.AllowAllDevices = true
  158. hostDevices, err := devices.HostDevices()
  159. if err != nil {
  160. return err
  161. }
  162. container.Devices = hostDevices
  163. if apparmor.IsEnabled() {
  164. container.AppArmorProfile = "docker-unconfined"
  165. }
  166. return nil
  167. }
  168. func (d *Driver) setCapabilities(container *configs.Config, c *execdriver.Command) (err error) {
  169. container.Capabilities, err = execdriver.TweakCapabilities(container.Capabilities, c.CapAdd, c.CapDrop)
  170. return err
  171. }
  172. func (d *Driver) setupRlimits(container *configs.Config, c *execdriver.Command) {
  173. if c.Resources == nil {
  174. return
  175. }
  176. for _, rlimit := range c.Resources.Rlimits {
  177. container.Rlimits = append(container.Rlimits, configs.Rlimit{
  178. Type: rlimit.Type,
  179. Hard: rlimit.Hard,
  180. Soft: rlimit.Soft,
  181. })
  182. }
  183. }
  184. func (d *Driver) setupMounts(container *configs.Config, c *execdriver.Command) error {
  185. userMounts := make(map[string]struct{})
  186. for _, m := range c.Mounts {
  187. userMounts[m.Destination] = struct{}{}
  188. }
  189. // Filter out mounts that are overriden by user supplied mounts
  190. var defaultMounts []*configs.Mount
  191. _, mountDev := userMounts["/dev"]
  192. for _, m := range container.Mounts {
  193. if _, ok := userMounts[m.Destination]; !ok {
  194. if mountDev && strings.HasPrefix(m.Destination, "/dev/") {
  195. continue
  196. }
  197. defaultMounts = append(defaultMounts, m)
  198. }
  199. }
  200. container.Mounts = defaultMounts
  201. for _, m := range c.Mounts {
  202. flags := syscall.MS_BIND | syscall.MS_REC
  203. if !m.Writable {
  204. flags |= syscall.MS_RDONLY
  205. }
  206. if m.Slave {
  207. flags |= syscall.MS_SLAVE
  208. }
  209. container.Mounts = append(container.Mounts, &configs.Mount{
  210. Source: m.Source,
  211. Destination: m.Destination,
  212. Device: "bind",
  213. Flags: flags,
  214. })
  215. }
  216. return nil
  217. }
  218. func (d *Driver) setupLabels(container *configs.Config, c *execdriver.Command) {
  219. container.ProcessLabel = c.ProcessLabel
  220. container.MountLabel = c.MountLabel
  221. }