create.go 6.3 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/docker/libcontainer/apparmor"
  11. "github.com/docker/libcontainer/configs"
  12. "github.com/docker/libcontainer/devices"
  13. "github.com/docker/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. // clear readonly for /sys
  33. for i := range container.Mounts {
  34. if container.Mounts[i].Destination == "/sys" {
  35. container.Mounts[i].Flags &= ^syscall.MS_RDONLY
  36. }
  37. }
  38. container.ReadonlyPaths = nil
  39. container.MaskPaths = nil
  40. if err := d.setPrivileged(container); err != nil {
  41. return nil, err
  42. }
  43. } else {
  44. if err := d.setCapabilities(container, c); err != nil {
  45. return nil, err
  46. }
  47. }
  48. if c.AppArmorProfile != "" {
  49. container.AppArmorProfile = c.AppArmorProfile
  50. }
  51. if err := execdriver.SetupCgroups(container, c); err != nil {
  52. return nil, err
  53. }
  54. if err := d.setupMounts(container, c); err != nil {
  55. return nil, err
  56. }
  57. d.setupLabels(container, c)
  58. d.setupRlimits(container, c)
  59. return container, nil
  60. }
  61. func generateIfaceName() (string, error) {
  62. for i := 0; i < 10; i++ {
  63. name, err := utils.GenerateRandomName("veth", 7)
  64. if err != nil {
  65. continue
  66. }
  67. if _, err := net.InterfaceByName(name); err != nil {
  68. if strings.Contains(err.Error(), "no such") {
  69. return name, nil
  70. }
  71. return "", err
  72. }
  73. }
  74. return "", errors.New("Failed to find name for new interface")
  75. }
  76. func (d *driver) createNetwork(container *configs.Config, c *execdriver.Command) error {
  77. if c.Network.HostNetworking {
  78. container.Namespaces.Remove(configs.NEWNET)
  79. return nil
  80. }
  81. container.Networks = []*configs.Network{
  82. {
  83. Type: "loopback",
  84. },
  85. }
  86. iName, err := generateIfaceName()
  87. if err != nil {
  88. return err
  89. }
  90. if c.Network.Interface != nil {
  91. vethNetwork := configs.Network{
  92. Name: "eth0",
  93. HostInterfaceName: iName,
  94. Mtu: c.Network.Mtu,
  95. Address: fmt.Sprintf("%s/%d", c.Network.Interface.IPAddress, c.Network.Interface.IPPrefixLen),
  96. MacAddress: c.Network.Interface.MacAddress,
  97. Gateway: c.Network.Interface.Gateway,
  98. Type: "veth",
  99. Bridge: c.Network.Interface.Bridge,
  100. HairpinMode: c.Network.Interface.HairpinMode,
  101. }
  102. if c.Network.Interface.GlobalIPv6Address != "" {
  103. vethNetwork.IPv6Address = fmt.Sprintf("%s/%d", c.Network.Interface.GlobalIPv6Address, c.Network.Interface.GlobalIPv6PrefixLen)
  104. vethNetwork.IPv6Gateway = c.Network.Interface.IPv6Gateway
  105. }
  106. container.Networks = append(container.Networks, &vethNetwork)
  107. }
  108. if c.Network.ContainerID != "" {
  109. d.Lock()
  110. active := d.activeContainers[c.Network.ContainerID]
  111. d.Unlock()
  112. if active == nil {
  113. return fmt.Errorf("%s is not a valid running container to join", c.Network.ContainerID)
  114. }
  115. state, err := active.State()
  116. if err != nil {
  117. return err
  118. }
  119. container.Namespaces.Add(configs.NEWNET, state.NamespacePaths[configs.NEWNET])
  120. }
  121. return nil
  122. }
  123. func (d *driver) createIpc(container *configs.Config, c *execdriver.Command) error {
  124. if c.Ipc.HostIpc {
  125. container.Namespaces.Remove(configs.NEWIPC)
  126. return nil
  127. }
  128. if c.Ipc.ContainerID != "" {
  129. d.Lock()
  130. active := d.activeContainers[c.Ipc.ContainerID]
  131. d.Unlock()
  132. if active == nil {
  133. return fmt.Errorf("%s is not a valid running container to join", c.Ipc.ContainerID)
  134. }
  135. state, err := active.State()
  136. if err != nil {
  137. return err
  138. }
  139. container.Namespaces.Add(configs.NEWIPC, state.NamespacePaths[configs.NEWIPC])
  140. }
  141. return nil
  142. }
  143. func (d *driver) createPid(container *configs.Config, c *execdriver.Command) error {
  144. if c.Pid.HostPid {
  145. container.Namespaces.Remove(configs.NEWPID)
  146. return nil
  147. }
  148. return nil
  149. }
  150. func (d *driver) createUTS(container *configs.Config, c *execdriver.Command) error {
  151. if c.UTS.HostUTS {
  152. container.Namespaces.Remove(configs.NEWUTS)
  153. container.Hostname = ""
  154. return nil
  155. }
  156. return nil
  157. }
  158. func (d *driver) setPrivileged(container *configs.Config) (err error) {
  159. container.Capabilities = execdriver.GetAllCapabilities()
  160. container.Cgroups.AllowAllDevices = true
  161. hostDevices, err := devices.HostDevices()
  162. if err != nil {
  163. return err
  164. }
  165. container.Devices = hostDevices
  166. if apparmor.IsEnabled() {
  167. container.AppArmorProfile = "unconfined"
  168. }
  169. return nil
  170. }
  171. func (d *driver) setCapabilities(container *configs.Config, c *execdriver.Command) (err error) {
  172. container.Capabilities, err = execdriver.TweakCapabilities(container.Capabilities, c.CapAdd, c.CapDrop)
  173. return err
  174. }
  175. func (d *driver) setupRlimits(container *configs.Config, c *execdriver.Command) {
  176. if c.Resources == nil {
  177. return
  178. }
  179. for _, rlimit := range c.Resources.Rlimits {
  180. container.Rlimits = append(container.Rlimits, configs.Rlimit{
  181. Type: rlimit.Type,
  182. Hard: rlimit.Hard,
  183. Soft: rlimit.Soft,
  184. })
  185. }
  186. }
  187. func (d *driver) setupMounts(container *configs.Config, c *execdriver.Command) error {
  188. userMounts := make(map[string]struct{})
  189. for _, m := range c.Mounts {
  190. userMounts[m.Destination] = struct{}{}
  191. }
  192. // Filter out mounts that are overriden by user supplied mounts
  193. var defaultMounts []*configs.Mount
  194. _, mountDev := userMounts["/dev"]
  195. for _, m := range container.Mounts {
  196. if _, ok := userMounts[m.Destination]; !ok {
  197. if mountDev && strings.HasPrefix(m.Destination, "/dev/") {
  198. continue
  199. }
  200. defaultMounts = append(defaultMounts, m)
  201. }
  202. }
  203. container.Mounts = defaultMounts
  204. for _, m := range c.Mounts {
  205. flags := syscall.MS_BIND | syscall.MS_REC
  206. if !m.Writable {
  207. flags |= syscall.MS_RDONLY
  208. }
  209. if m.Slave {
  210. flags |= syscall.MS_SLAVE
  211. }
  212. container.Mounts = append(container.Mounts, &configs.Mount{
  213. Source: m.Source,
  214. Destination: m.Destination,
  215. Device: "bind",
  216. Flags: flags,
  217. })
  218. }
  219. return nil
  220. }
  221. func (d *driver) setupLabels(container *configs.Config, c *execdriver.Command) {
  222. container.ProcessLabel = c.ProcessLabel
  223. container.MountLabel = c.MountLabel
  224. }