create.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. // +build linux,cgo
  2. package native
  3. import (
  4. "errors"
  5. "fmt"
  6. "net"
  7. "path/filepath"
  8. "strings"
  9. "syscall"
  10. "github.com/docker/docker/daemon/execdriver"
  11. "github.com/docker/docker/pkg/symlink"
  12. "github.com/docker/libcontainer/apparmor"
  13. "github.com/docker/libcontainer/configs"
  14. "github.com/docker/libcontainer/devices"
  15. "github.com/docker/libcontainer/utils"
  16. )
  17. // createContainer populates and configures the container type with the
  18. // data provided by the execdriver.Command
  19. func (d *driver) createContainer(c *execdriver.Command) (*configs.Config, error) {
  20. container := execdriver.InitContainer(c)
  21. if err := d.createIpc(container, c); err != nil {
  22. return nil, err
  23. }
  24. if err := d.createPid(container, c); err != nil {
  25. return nil, err
  26. }
  27. if err := d.createNetwork(container, c); err != nil {
  28. return nil, err
  29. }
  30. if c.ProcessConfig.Privileged {
  31. // clear readonly for /sys
  32. for i := range container.Mounts {
  33. if container.Mounts[i].Destination == "/sys" {
  34. container.Mounts[i].Flags &= ^syscall.MS_RDONLY
  35. }
  36. }
  37. container.ReadonlyPaths = nil
  38. if err := d.setPrivileged(container); err != nil {
  39. return nil, err
  40. }
  41. } else {
  42. if err := d.setCapabilities(container, c); err != nil {
  43. return nil, err
  44. }
  45. }
  46. if c.AppArmorProfile != "" {
  47. container.AppArmorProfile = c.AppArmorProfile
  48. }
  49. if err := execdriver.SetupCgroups(container, c); err != nil {
  50. return nil, err
  51. }
  52. if err := d.setupMounts(container, c); err != nil {
  53. return nil, err
  54. }
  55. if err := d.setupLabels(container, c); err != nil {
  56. return nil, err
  57. }
  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. }
  101. if c.Network.Interface.GlobalIPv6Address != "" {
  102. vethNetwork.IPv6Address = fmt.Sprintf("%s/%d", c.Network.Interface.GlobalIPv6Address, c.Network.Interface.GlobalIPv6PrefixLen)
  103. vethNetwork.IPv6Gateway = c.Network.Interface.IPv6Gateway
  104. }
  105. container.Networks = append(container.Networks, &vethNetwork)
  106. }
  107. if c.Network.ContainerID != "" {
  108. d.Lock()
  109. active := d.activeContainers[c.Network.ContainerID]
  110. d.Unlock()
  111. if active == nil {
  112. return fmt.Errorf("%s is not a valid running container to join", c.Network.ContainerID)
  113. }
  114. state, err := active.State()
  115. if err != nil {
  116. return err
  117. }
  118. container.Namespaces.Add(configs.NEWNET, state.NamespacePaths[configs.NEWNET])
  119. }
  120. return nil
  121. }
  122. func (d *driver) createIpc(container *configs.Config, c *execdriver.Command) error {
  123. if c.Ipc.HostIpc {
  124. container.Namespaces.Remove(configs.NEWIPC)
  125. return nil
  126. }
  127. if c.Ipc.ContainerID != "" {
  128. d.Lock()
  129. active := d.activeContainers[c.Ipc.ContainerID]
  130. d.Unlock()
  131. if active == nil {
  132. return fmt.Errorf("%s is not a valid running container to join", c.Ipc.ContainerID)
  133. }
  134. state, err := active.State()
  135. if err != nil {
  136. return err
  137. }
  138. container.Namespaces.Add(configs.NEWIPC, state.NamespacePaths[configs.NEWIPC])
  139. }
  140. return nil
  141. }
  142. func (d *driver) createPid(container *configs.Config, c *execdriver.Command) error {
  143. if c.Pid.HostPid {
  144. container.Namespaces.Remove(configs.NEWPID)
  145. return nil
  146. }
  147. return nil
  148. }
  149. func (d *driver) setPrivileged(container *configs.Config) (err error) {
  150. container.Capabilities = execdriver.GetAllCapabilities()
  151. container.Cgroups.AllowAllDevices = true
  152. hostDevices, err := devices.HostDevices()
  153. if err != nil {
  154. return err
  155. }
  156. container.Devices = hostDevices
  157. if apparmor.IsEnabled() {
  158. container.AppArmorProfile = "unconfined"
  159. }
  160. return nil
  161. }
  162. func (d *driver) setCapabilities(container *configs.Config, c *execdriver.Command) (err error) {
  163. container.Capabilities, err = execdriver.TweakCapabilities(container.Capabilities, c.CapAdd, c.CapDrop)
  164. return err
  165. }
  166. func (d *driver) setupRlimits(container *configs.Config, c *execdriver.Command) {
  167. if c.Resources == nil {
  168. return
  169. }
  170. for _, rlimit := range c.Resources.Rlimits {
  171. container.Rlimits = append(container.Rlimits, configs.Rlimit{
  172. Type: rlimit.Type,
  173. Hard: rlimit.Hard,
  174. Soft: rlimit.Soft,
  175. })
  176. }
  177. }
  178. func (d *driver) setupMounts(container *configs.Config, c *execdriver.Command) error {
  179. userMounts := make(map[string]struct{})
  180. for _, m := range c.Mounts {
  181. userMounts[m.Destination] = struct{}{}
  182. }
  183. // Filter out mounts that are overriden by user supplied mounts
  184. var defaultMounts []*configs.Mount
  185. for _, m := range container.Mounts {
  186. if _, ok := userMounts[m.Destination]; !ok {
  187. defaultMounts = append(defaultMounts, m)
  188. }
  189. }
  190. container.Mounts = defaultMounts
  191. for _, m := range c.Mounts {
  192. dest, err := symlink.FollowSymlinkInScope(filepath.Join(c.Rootfs, m.Destination), c.Rootfs)
  193. if err != nil {
  194. return err
  195. }
  196. flags := syscall.MS_BIND | syscall.MS_REC
  197. if !m.Writable {
  198. flags |= syscall.MS_RDONLY
  199. }
  200. if m.Slave {
  201. flags |= syscall.MS_SLAVE
  202. }
  203. container.Mounts = append(container.Mounts, &configs.Mount{
  204. Source: m.Source,
  205. Destination: dest,
  206. Device: "bind",
  207. Flags: flags,
  208. })
  209. }
  210. return nil
  211. }
  212. func (d *driver) setupLabels(container *configs.Config, c *execdriver.Command) error {
  213. container.ProcessLabel = c.ProcessLabel
  214. container.MountLabel = c.MountLabel
  215. return nil
  216. }