daemon_unix.go 49 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346
  1. // +build linux freebsd
  2. package daemon
  3. import (
  4. "bufio"
  5. "bytes"
  6. "fmt"
  7. "io/ioutil"
  8. "net"
  9. "os"
  10. "path/filepath"
  11. "runtime"
  12. "runtime/debug"
  13. "strconv"
  14. "strings"
  15. "time"
  16. "github.com/docker/docker/api/types"
  17. "github.com/docker/docker/api/types/blkiodev"
  18. pblkiodev "github.com/docker/docker/api/types/blkiodev"
  19. containertypes "github.com/docker/docker/api/types/container"
  20. "github.com/docker/docker/container"
  21. "github.com/docker/docker/daemon/config"
  22. "github.com/docker/docker/image"
  23. "github.com/docker/docker/opts"
  24. "github.com/docker/docker/pkg/idtools"
  25. "github.com/docker/docker/pkg/parsers"
  26. "github.com/docker/docker/pkg/parsers/kernel"
  27. "github.com/docker/docker/pkg/sysinfo"
  28. "github.com/docker/docker/runconfig"
  29. "github.com/docker/docker/volume"
  30. "github.com/docker/libnetwork"
  31. nwconfig "github.com/docker/libnetwork/config"
  32. "github.com/docker/libnetwork/drivers/bridge"
  33. "github.com/docker/libnetwork/netlabel"
  34. "github.com/docker/libnetwork/netutils"
  35. "github.com/docker/libnetwork/options"
  36. lntypes "github.com/docker/libnetwork/types"
  37. "github.com/golang/protobuf/ptypes"
  38. "github.com/opencontainers/runc/libcontainer/cgroups"
  39. rsystem "github.com/opencontainers/runc/libcontainer/system"
  40. specs "github.com/opencontainers/runtime-spec/specs-go"
  41. "github.com/opencontainers/selinux/go-selinux/label"
  42. "github.com/pkg/errors"
  43. "github.com/sirupsen/logrus"
  44. "github.com/vishvananda/netlink"
  45. "golang.org/x/sys/unix"
  46. )
  47. const (
  48. // See https://git.kernel.org/cgit/linux/kernel/git/tip/tip.git/tree/kernel/sched/sched.h?id=8cd9234c64c584432f6992fe944ca9e46ca8ea76#n269
  49. linuxMinCPUShares = 2
  50. linuxMaxCPUShares = 262144
  51. platformSupported = true
  52. // It's not kernel limit, we want this 4M limit to supply a reasonable functional container
  53. linuxMinMemory = 4194304
  54. // constants for remapped root settings
  55. defaultIDSpecifier string = "default"
  56. defaultRemappedID string = "dockremap"
  57. // constant for cgroup drivers
  58. cgroupFsDriver = "cgroupfs"
  59. cgroupSystemdDriver = "systemd"
  60. )
  61. func getMemoryResources(config containertypes.Resources) *specs.LinuxMemory {
  62. memory := specs.LinuxMemory{}
  63. if config.Memory > 0 {
  64. limit := uint64(config.Memory)
  65. memory.Limit = &limit
  66. }
  67. if config.MemoryReservation > 0 {
  68. reservation := uint64(config.MemoryReservation)
  69. memory.Reservation = &reservation
  70. }
  71. if config.MemorySwap > 0 {
  72. swap := uint64(config.MemorySwap)
  73. memory.Swap = &swap
  74. }
  75. if config.MemorySwappiness != nil {
  76. swappiness := uint64(*config.MemorySwappiness)
  77. memory.Swappiness = &swappiness
  78. }
  79. if config.KernelMemory != 0 {
  80. kernelMemory := uint64(config.KernelMemory)
  81. memory.Kernel = &kernelMemory
  82. }
  83. return &memory
  84. }
  85. func getCPUResources(config containertypes.Resources) (*specs.LinuxCPU, error) {
  86. cpu := specs.LinuxCPU{}
  87. if config.CPUShares < 0 {
  88. return nil, fmt.Errorf("shares: invalid argument")
  89. }
  90. if config.CPUShares >= 0 {
  91. shares := uint64(config.CPUShares)
  92. cpu.Shares = &shares
  93. }
  94. if config.CpusetCpus != "" {
  95. cpu.Cpus = config.CpusetCpus
  96. }
  97. if config.CpusetMems != "" {
  98. cpu.Mems = config.CpusetMems
  99. }
  100. if config.NanoCPUs > 0 {
  101. // https://www.kernel.org/doc/Documentation/scheduler/sched-bwc.txt
  102. period := uint64(100 * time.Millisecond / time.Microsecond)
  103. quota := config.NanoCPUs * int64(period) / 1e9
  104. cpu.Period = &period
  105. cpu.Quota = &quota
  106. }
  107. if config.CPUPeriod != 0 {
  108. period := uint64(config.CPUPeriod)
  109. cpu.Period = &period
  110. }
  111. if config.CPUQuota != 0 {
  112. q := config.CPUQuota
  113. cpu.Quota = &q
  114. }
  115. if config.CPURealtimePeriod != 0 {
  116. period := uint64(config.CPURealtimePeriod)
  117. cpu.RealtimePeriod = &period
  118. }
  119. if config.CPURealtimeRuntime != 0 {
  120. c := config.CPURealtimeRuntime
  121. cpu.RealtimeRuntime = &c
  122. }
  123. return &cpu, nil
  124. }
  125. func getBlkioWeightDevices(config containertypes.Resources) ([]specs.LinuxWeightDevice, error) {
  126. var stat unix.Stat_t
  127. var blkioWeightDevices []specs.LinuxWeightDevice
  128. for _, weightDevice := range config.BlkioWeightDevice {
  129. if err := unix.Stat(weightDevice.Path, &stat); err != nil {
  130. return nil, err
  131. }
  132. weight := weightDevice.Weight
  133. d := specs.LinuxWeightDevice{Weight: &weight}
  134. d.Major = int64(stat.Rdev / 256)
  135. d.Minor = int64(stat.Rdev % 256)
  136. blkioWeightDevices = append(blkioWeightDevices, d)
  137. }
  138. return blkioWeightDevices, nil
  139. }
  140. func (daemon *Daemon) parseSecurityOpt(container *container.Container, hostConfig *containertypes.HostConfig) error {
  141. container.NoNewPrivileges = daemon.configStore.NoNewPrivileges
  142. return parseSecurityOpt(container, hostConfig)
  143. }
  144. func parseSecurityOpt(container *container.Container, config *containertypes.HostConfig) error {
  145. var (
  146. labelOpts []string
  147. err error
  148. )
  149. for _, opt := range config.SecurityOpt {
  150. if opt == "no-new-privileges" {
  151. container.NoNewPrivileges = true
  152. continue
  153. }
  154. if opt == "disable" {
  155. labelOpts = append(labelOpts, "disable")
  156. continue
  157. }
  158. var con []string
  159. if strings.Contains(opt, "=") {
  160. con = strings.SplitN(opt, "=", 2)
  161. } else if strings.Contains(opt, ":") {
  162. con = strings.SplitN(opt, ":", 2)
  163. logrus.Warn("Security options with `:` as a separator are deprecated and will be completely unsupported in 17.04, use `=` instead.")
  164. }
  165. if len(con) != 2 {
  166. return fmt.Errorf("invalid --security-opt 1: %q", opt)
  167. }
  168. switch con[0] {
  169. case "label":
  170. labelOpts = append(labelOpts, con[1])
  171. case "apparmor":
  172. container.AppArmorProfile = con[1]
  173. case "seccomp":
  174. container.SeccompProfile = con[1]
  175. case "no-new-privileges":
  176. noNewPrivileges, err := strconv.ParseBool(con[1])
  177. if err != nil {
  178. return fmt.Errorf("invalid --security-opt 2: %q", opt)
  179. }
  180. container.NoNewPrivileges = noNewPrivileges
  181. default:
  182. return fmt.Errorf("invalid --security-opt 2: %q", opt)
  183. }
  184. }
  185. container.ProcessLabel, container.MountLabel, err = label.InitLabels(labelOpts)
  186. return err
  187. }
  188. func getBlkioThrottleDevices(devs []*blkiodev.ThrottleDevice) ([]specs.LinuxThrottleDevice, error) {
  189. var throttleDevices []specs.LinuxThrottleDevice
  190. var stat unix.Stat_t
  191. for _, d := range devs {
  192. if err := unix.Stat(d.Path, &stat); err != nil {
  193. return nil, err
  194. }
  195. d := specs.LinuxThrottleDevice{Rate: d.Rate}
  196. d.Major = int64(stat.Rdev / 256)
  197. d.Minor = int64(stat.Rdev % 256)
  198. throttleDevices = append(throttleDevices, d)
  199. }
  200. return throttleDevices, nil
  201. }
  202. func checkKernel() error {
  203. // Check for unsupported kernel versions
  204. // FIXME: it would be cleaner to not test for specific versions, but rather
  205. // test for specific functionalities.
  206. // Unfortunately we can't test for the feature "does not cause a kernel panic"
  207. // without actually causing a kernel panic, so we need this workaround until
  208. // the circumstances of pre-3.10 crashes are clearer.
  209. // For details see https://github.com/docker/docker/issues/407
  210. // Docker 1.11 and above doesn't actually run on kernels older than 3.4,
  211. // due to containerd-shim usage of PR_SET_CHILD_SUBREAPER (introduced in 3.4).
  212. if !kernel.CheckKernelVersion(3, 10, 0) {
  213. v, _ := kernel.GetKernelVersion()
  214. if os.Getenv("DOCKER_NOWARN_KERNEL_VERSION") == "" {
  215. logrus.Fatalf("Your Linux kernel version %s is not supported for running docker. Please upgrade your kernel to 3.10.0 or newer.", v.String())
  216. }
  217. }
  218. return nil
  219. }
  220. // adaptContainerSettings is called during container creation to modify any
  221. // settings necessary in the HostConfig structure.
  222. func (daemon *Daemon) adaptContainerSettings(hostConfig *containertypes.HostConfig, adjustCPUShares bool) error {
  223. if adjustCPUShares && hostConfig.CPUShares > 0 {
  224. // Handle unsupported CPUShares
  225. if hostConfig.CPUShares < linuxMinCPUShares {
  226. logrus.Warnf("Changing requested CPUShares of %d to minimum allowed of %d", hostConfig.CPUShares, linuxMinCPUShares)
  227. hostConfig.CPUShares = linuxMinCPUShares
  228. } else if hostConfig.CPUShares > linuxMaxCPUShares {
  229. logrus.Warnf("Changing requested CPUShares of %d to maximum allowed of %d", hostConfig.CPUShares, linuxMaxCPUShares)
  230. hostConfig.CPUShares = linuxMaxCPUShares
  231. }
  232. }
  233. if hostConfig.Memory > 0 && hostConfig.MemorySwap == 0 {
  234. // By default, MemorySwap is set to twice the size of Memory.
  235. hostConfig.MemorySwap = hostConfig.Memory * 2
  236. }
  237. if hostConfig.ShmSize == 0 {
  238. hostConfig.ShmSize = config.DefaultShmSize
  239. if daemon.configStore != nil {
  240. hostConfig.ShmSize = int64(daemon.configStore.ShmSize)
  241. }
  242. }
  243. // Set default IPC mode, if unset for container
  244. if hostConfig.IpcMode.IsEmpty() {
  245. m := config.DefaultIpcMode
  246. if daemon.configStore != nil {
  247. m = daemon.configStore.IpcMode
  248. }
  249. hostConfig.IpcMode = containertypes.IpcMode(m)
  250. }
  251. var err error
  252. opts, err := daemon.generateSecurityOpt(hostConfig)
  253. if err != nil {
  254. return err
  255. }
  256. hostConfig.SecurityOpt = append(hostConfig.SecurityOpt, opts...)
  257. if hostConfig.OomKillDisable == nil {
  258. defaultOomKillDisable := false
  259. hostConfig.OomKillDisable = &defaultOomKillDisable
  260. }
  261. return nil
  262. }
  263. func verifyContainerResources(resources *containertypes.Resources, sysInfo *sysinfo.SysInfo, update bool) ([]string, error) {
  264. warnings := []string{}
  265. fixMemorySwappiness(resources)
  266. // memory subsystem checks and adjustments
  267. if resources.Memory != 0 && resources.Memory < linuxMinMemory {
  268. return warnings, fmt.Errorf("Minimum memory limit allowed is 4MB")
  269. }
  270. if resources.Memory > 0 && !sysInfo.MemoryLimit {
  271. warnings = append(warnings, "Your kernel does not support memory limit capabilities or the cgroup is not mounted. Limitation discarded.")
  272. logrus.Warn("Your kernel does not support memory limit capabilities or the cgroup is not mounted. Limitation discarded.")
  273. resources.Memory = 0
  274. resources.MemorySwap = -1
  275. }
  276. if resources.Memory > 0 && resources.MemorySwap != -1 && !sysInfo.SwapLimit {
  277. warnings = append(warnings, "Your kernel does not support swap limit capabilities or the cgroup is not mounted. Memory limited without swap.")
  278. logrus.Warn("Your kernel does not support swap limit capabilities,or the cgroup is not mounted. Memory limited without swap.")
  279. resources.MemorySwap = -1
  280. }
  281. if resources.Memory > 0 && resources.MemorySwap > 0 && resources.MemorySwap < resources.Memory {
  282. return warnings, fmt.Errorf("Minimum memoryswap limit should be larger than memory limit, see usage")
  283. }
  284. if resources.Memory == 0 && resources.MemorySwap > 0 && !update {
  285. return warnings, fmt.Errorf("You should always set the Memory limit when using Memoryswap limit, see usage")
  286. }
  287. if resources.MemorySwappiness != nil && !sysInfo.MemorySwappiness {
  288. warnings = append(warnings, "Your kernel does not support memory swappiness capabilities or the cgroup is not mounted. Memory swappiness discarded.")
  289. logrus.Warn("Your kernel does not support memory swappiness capabilities, or the cgroup is not mounted. Memory swappiness discarded.")
  290. resources.MemorySwappiness = nil
  291. }
  292. if resources.MemorySwappiness != nil {
  293. swappiness := *resources.MemorySwappiness
  294. if swappiness < 0 || swappiness > 100 {
  295. return warnings, fmt.Errorf("Invalid value: %v, valid memory swappiness range is 0-100", swappiness)
  296. }
  297. }
  298. if resources.MemoryReservation > 0 && !sysInfo.MemoryReservation {
  299. warnings = append(warnings, "Your kernel does not support memory soft limit capabilities or the cgroup is not mounted. Limitation discarded.")
  300. logrus.Warn("Your kernel does not support memory soft limit capabilities or the cgroup is not mounted. Limitation discarded.")
  301. resources.MemoryReservation = 0
  302. }
  303. if resources.MemoryReservation > 0 && resources.MemoryReservation < linuxMinMemory {
  304. return warnings, fmt.Errorf("Minimum memory reservation allowed is 4MB")
  305. }
  306. if resources.Memory > 0 && resources.MemoryReservation > 0 && resources.Memory < resources.MemoryReservation {
  307. return warnings, fmt.Errorf("Minimum memory limit can not be less than memory reservation limit, see usage")
  308. }
  309. if resources.KernelMemory > 0 && !sysInfo.KernelMemory {
  310. warnings = append(warnings, "Your kernel does not support kernel memory limit capabilities or the cgroup is not mounted. Limitation discarded.")
  311. logrus.Warn("Your kernel does not support kernel memory limit capabilities or the cgroup is not mounted. Limitation discarded.")
  312. resources.KernelMemory = 0
  313. }
  314. if resources.KernelMemory > 0 && resources.KernelMemory < linuxMinMemory {
  315. return warnings, fmt.Errorf("Minimum kernel memory limit allowed is 4MB")
  316. }
  317. if resources.KernelMemory > 0 && !kernel.CheckKernelVersion(4, 0, 0) {
  318. warnings = append(warnings, "You specified a kernel memory limit on a kernel older than 4.0. Kernel memory limits are experimental on older kernels, it won't work as expected and can cause your system to be unstable.")
  319. logrus.Warn("You specified a kernel memory limit on a kernel older than 4.0. Kernel memory limits are experimental on older kernels, it won't work as expected and can cause your system to be unstable.")
  320. }
  321. if resources.OomKillDisable != nil && !sysInfo.OomKillDisable {
  322. // only produce warnings if the setting wasn't to *disable* the OOM Kill; no point
  323. // warning the caller if they already wanted the feature to be off
  324. if *resources.OomKillDisable {
  325. warnings = append(warnings, "Your kernel does not support OomKillDisable. OomKillDisable discarded.")
  326. logrus.Warn("Your kernel does not support OomKillDisable. OomKillDisable discarded.")
  327. }
  328. resources.OomKillDisable = nil
  329. }
  330. if resources.PidsLimit != 0 && !sysInfo.PidsLimit {
  331. warnings = append(warnings, "Your kernel does not support pids limit capabilities or the cgroup is not mounted. PIDs limit discarded.")
  332. logrus.Warn("Your kernel does not support pids limit capabilities or the cgroup is not mounted. PIDs limit discarded.")
  333. resources.PidsLimit = 0
  334. }
  335. // cpu subsystem checks and adjustments
  336. if resources.NanoCPUs > 0 && resources.CPUPeriod > 0 {
  337. return warnings, fmt.Errorf("Conflicting options: Nano CPUs and CPU Period cannot both be set")
  338. }
  339. if resources.NanoCPUs > 0 && resources.CPUQuota > 0 {
  340. return warnings, fmt.Errorf("Conflicting options: Nano CPUs and CPU Quota cannot both be set")
  341. }
  342. if resources.NanoCPUs > 0 && (!sysInfo.CPUCfsPeriod || !sysInfo.CPUCfsQuota) {
  343. return warnings, fmt.Errorf("NanoCPUs can not be set, as your kernel does not support CPU cfs period/quota or the cgroup is not mounted")
  344. }
  345. // The highest precision we could get on Linux is 0.001, by setting
  346. // cpu.cfs_period_us=1000ms
  347. // cpu.cfs_quota=1ms
  348. // See the following link for details:
  349. // https://www.kernel.org/doc/Documentation/scheduler/sched-bwc.txt
  350. // Here we don't set the lower limit and it is up to the underlying platform (e.g., Linux) to return an error.
  351. // The error message is 0.01 so that this is consistent with Windows
  352. if resources.NanoCPUs < 0 || resources.NanoCPUs > int64(sysinfo.NumCPU())*1e9 {
  353. return warnings, fmt.Errorf("Range of CPUs is from 0.01 to %d.00, as there are only %d CPUs available", sysinfo.NumCPU(), sysinfo.NumCPU())
  354. }
  355. if resources.CPUShares > 0 && !sysInfo.CPUShares {
  356. warnings = append(warnings, "Your kernel does not support CPU shares or the cgroup is not mounted. Shares discarded.")
  357. logrus.Warn("Your kernel does not support CPU shares or the cgroup is not mounted. Shares discarded.")
  358. resources.CPUShares = 0
  359. }
  360. if resources.CPUPeriod > 0 && !sysInfo.CPUCfsPeriod {
  361. warnings = append(warnings, "Your kernel does not support CPU cfs period or the cgroup is not mounted. Period discarded.")
  362. logrus.Warn("Your kernel does not support CPU cfs period or the cgroup is not mounted. Period discarded.")
  363. resources.CPUPeriod = 0
  364. }
  365. if resources.CPUPeriod != 0 && (resources.CPUPeriod < 1000 || resources.CPUPeriod > 1000000) {
  366. return warnings, fmt.Errorf("CPU cfs period can not be less than 1ms (i.e. 1000) or larger than 1s (i.e. 1000000)")
  367. }
  368. if resources.CPUQuota > 0 && !sysInfo.CPUCfsQuota {
  369. warnings = append(warnings, "Your kernel does not support CPU cfs quota or the cgroup is not mounted. Quota discarded.")
  370. logrus.Warn("Your kernel does not support CPU cfs quota or the cgroup is not mounted. Quota discarded.")
  371. resources.CPUQuota = 0
  372. }
  373. if resources.CPUQuota > 0 && resources.CPUQuota < 1000 {
  374. return warnings, fmt.Errorf("CPU cfs quota can not be less than 1ms (i.e. 1000)")
  375. }
  376. if resources.CPUPercent > 0 {
  377. warnings = append(warnings, fmt.Sprintf("%s does not support CPU percent. Percent discarded.", runtime.GOOS))
  378. logrus.Warnf("%s does not support CPU percent. Percent discarded.", runtime.GOOS)
  379. resources.CPUPercent = 0
  380. }
  381. // cpuset subsystem checks and adjustments
  382. if (resources.CpusetCpus != "" || resources.CpusetMems != "") && !sysInfo.Cpuset {
  383. warnings = append(warnings, "Your kernel does not support cpuset or the cgroup is not mounted. Cpuset discarded.")
  384. logrus.Warn("Your kernel does not support cpuset or the cgroup is not mounted. Cpuset discarded.")
  385. resources.CpusetCpus = ""
  386. resources.CpusetMems = ""
  387. }
  388. cpusAvailable, err := sysInfo.IsCpusetCpusAvailable(resources.CpusetCpus)
  389. if err != nil {
  390. return warnings, fmt.Errorf("Invalid value %s for cpuset cpus", resources.CpusetCpus)
  391. }
  392. if !cpusAvailable {
  393. return warnings, fmt.Errorf("Requested CPUs are not available - requested %s, available: %s", resources.CpusetCpus, sysInfo.Cpus)
  394. }
  395. memsAvailable, err := sysInfo.IsCpusetMemsAvailable(resources.CpusetMems)
  396. if err != nil {
  397. return warnings, fmt.Errorf("Invalid value %s for cpuset mems", resources.CpusetMems)
  398. }
  399. if !memsAvailable {
  400. return warnings, fmt.Errorf("Requested memory nodes are not available - requested %s, available: %s", resources.CpusetMems, sysInfo.Mems)
  401. }
  402. // blkio subsystem checks and adjustments
  403. if resources.BlkioWeight > 0 && !sysInfo.BlkioWeight {
  404. warnings = append(warnings, "Your kernel does not support Block I/O weight or the cgroup is not mounted. Weight discarded.")
  405. logrus.Warn("Your kernel does not support Block I/O weight or the cgroup is not mounted. Weight discarded.")
  406. resources.BlkioWeight = 0
  407. }
  408. if resources.BlkioWeight > 0 && (resources.BlkioWeight < 10 || resources.BlkioWeight > 1000) {
  409. return warnings, fmt.Errorf("Range of blkio weight is from 10 to 1000")
  410. }
  411. if resources.IOMaximumBandwidth != 0 || resources.IOMaximumIOps != 0 {
  412. return warnings, fmt.Errorf("Invalid QoS settings: %s does not support Maximum IO Bandwidth or Maximum IO IOps", runtime.GOOS)
  413. }
  414. if len(resources.BlkioWeightDevice) > 0 && !sysInfo.BlkioWeightDevice {
  415. warnings = append(warnings, "Your kernel does not support Block I/O weight_device or the cgroup is not mounted. Weight-device discarded.")
  416. logrus.Warn("Your kernel does not support Block I/O weight_device or the cgroup is not mounted. Weight-device discarded.")
  417. resources.BlkioWeightDevice = []*pblkiodev.WeightDevice{}
  418. }
  419. if len(resources.BlkioDeviceReadBps) > 0 && !sysInfo.BlkioReadBpsDevice {
  420. warnings = append(warnings, "Your kernel does not support BPS Block I/O read limit or the cgroup is not mounted. Block I/O BPS read limit discarded.")
  421. logrus.Warn("Your kernel does not support BPS Block I/O read limit or the cgroup is not mounted. Block I/O BPS read limit discarded")
  422. resources.BlkioDeviceReadBps = []*pblkiodev.ThrottleDevice{}
  423. }
  424. if len(resources.BlkioDeviceWriteBps) > 0 && !sysInfo.BlkioWriteBpsDevice {
  425. warnings = append(warnings, "Your kernel does not support BPS Block I/O write limit or the cgroup is not mounted. Block I/O BPS write limit discarded.")
  426. logrus.Warn("Your kernel does not support BPS Block I/O write limit or the cgroup is not mounted. Block I/O BPS write limit discarded.")
  427. resources.BlkioDeviceWriteBps = []*pblkiodev.ThrottleDevice{}
  428. }
  429. if len(resources.BlkioDeviceReadIOps) > 0 && !sysInfo.BlkioReadIOpsDevice {
  430. warnings = append(warnings, "Your kernel does not support IOPS Block read limit or the cgroup is not mounted. Block I/O IOPS read limit discarded.")
  431. logrus.Warn("Your kernel does not support IOPS Block I/O read limit in IO or the cgroup is not mounted. Block I/O IOPS read limit discarded.")
  432. resources.BlkioDeviceReadIOps = []*pblkiodev.ThrottleDevice{}
  433. }
  434. if len(resources.BlkioDeviceWriteIOps) > 0 && !sysInfo.BlkioWriteIOpsDevice {
  435. warnings = append(warnings, "Your kernel does not support IOPS Block write limit or the cgroup is not mounted. Block I/O IOPS write limit discarded.")
  436. logrus.Warn("Your kernel does not support IOPS Block I/O write limit or the cgroup is not mounted. Block I/O IOPS write limit discarded.")
  437. resources.BlkioDeviceWriteIOps = []*pblkiodev.ThrottleDevice{}
  438. }
  439. return warnings, nil
  440. }
  441. func (daemon *Daemon) getCgroupDriver() string {
  442. cgroupDriver := cgroupFsDriver
  443. if UsingSystemd(daemon.configStore) {
  444. cgroupDriver = cgroupSystemdDriver
  445. }
  446. return cgroupDriver
  447. }
  448. // getCD gets the raw value of the native.cgroupdriver option, if set.
  449. func getCD(config *config.Config) string {
  450. for _, option := range config.ExecOptions {
  451. key, val, err := parsers.ParseKeyValueOpt(option)
  452. if err != nil || !strings.EqualFold(key, "native.cgroupdriver") {
  453. continue
  454. }
  455. return val
  456. }
  457. return ""
  458. }
  459. // VerifyCgroupDriver validates native.cgroupdriver
  460. func VerifyCgroupDriver(config *config.Config) error {
  461. cd := getCD(config)
  462. if cd == "" || cd == cgroupFsDriver || cd == cgroupSystemdDriver {
  463. return nil
  464. }
  465. return fmt.Errorf("native.cgroupdriver option %s not supported", cd)
  466. }
  467. // UsingSystemd returns true if cli option includes native.cgroupdriver=systemd
  468. func UsingSystemd(config *config.Config) bool {
  469. return getCD(config) == cgroupSystemdDriver
  470. }
  471. // verifyPlatformContainerSettings performs platform-specific validation of the
  472. // hostconfig and config structures.
  473. func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes.HostConfig, config *containertypes.Config, update bool) ([]string, error) {
  474. var warnings []string
  475. sysInfo := sysinfo.New(true)
  476. warnings, err := daemon.verifyExperimentalContainerSettings(hostConfig, config)
  477. if err != nil {
  478. return warnings, err
  479. }
  480. w, err := verifyContainerResources(&hostConfig.Resources, sysInfo, update)
  481. // no matter err is nil or not, w could have data in itself.
  482. warnings = append(warnings, w...)
  483. if err != nil {
  484. return warnings, err
  485. }
  486. if hostConfig.ShmSize < 0 {
  487. return warnings, fmt.Errorf("SHM size can not be less than 0")
  488. }
  489. if hostConfig.OomScoreAdj < -1000 || hostConfig.OomScoreAdj > 1000 {
  490. return warnings, fmt.Errorf("Invalid value %d, range for oom score adj is [-1000, 1000]", hostConfig.OomScoreAdj)
  491. }
  492. // ip-forwarding does not affect container with '--net=host' (or '--net=none')
  493. if sysInfo.IPv4ForwardingDisabled && !(hostConfig.NetworkMode.IsHost() || hostConfig.NetworkMode.IsNone()) {
  494. warnings = append(warnings, "IPv4 forwarding is disabled. Networking will not work.")
  495. logrus.Warn("IPv4 forwarding is disabled. Networking will not work")
  496. }
  497. // check for various conflicting options with user namespaces
  498. if daemon.configStore.RemappedRoot != "" && hostConfig.UsernsMode.IsPrivate() {
  499. if hostConfig.Privileged {
  500. return warnings, fmt.Errorf("privileged mode is incompatible with user namespaces. You must run the container in the host namespace when running privileged mode")
  501. }
  502. if hostConfig.NetworkMode.IsHost() && !hostConfig.UsernsMode.IsHost() {
  503. return warnings, fmt.Errorf("cannot share the host's network namespace when user namespaces are enabled")
  504. }
  505. if hostConfig.PidMode.IsHost() && !hostConfig.UsernsMode.IsHost() {
  506. return warnings, fmt.Errorf("cannot share the host PID namespace when user namespaces are enabled")
  507. }
  508. }
  509. if hostConfig.CgroupParent != "" && UsingSystemd(daemon.configStore) {
  510. // CgroupParent for systemd cgroup should be named as "xxx.slice"
  511. if len(hostConfig.CgroupParent) <= 6 || !strings.HasSuffix(hostConfig.CgroupParent, ".slice") {
  512. return warnings, fmt.Errorf("cgroup-parent for systemd cgroup should be a valid slice named as \"xxx.slice\"")
  513. }
  514. }
  515. if hostConfig.Runtime == "" {
  516. hostConfig.Runtime = daemon.configStore.GetDefaultRuntimeName()
  517. }
  518. if rt := daemon.configStore.GetRuntime(hostConfig.Runtime); rt == nil {
  519. return warnings, fmt.Errorf("Unknown runtime specified %s", hostConfig.Runtime)
  520. }
  521. for dest := range hostConfig.Tmpfs {
  522. if err := volume.ValidateTmpfsMountDestination(dest); err != nil {
  523. return warnings, err
  524. }
  525. }
  526. return warnings, nil
  527. }
  528. // reloadPlatform updates configuration with platform specific options
  529. // and updates the passed attributes
  530. func (daemon *Daemon) reloadPlatform(conf *config.Config, attributes map[string]string) error {
  531. if err := conf.ValidatePlatformConfig(); err != nil {
  532. return err
  533. }
  534. if conf.IsValueSet("runtimes") {
  535. daemon.configStore.Runtimes = conf.Runtimes
  536. // Always set the default one
  537. daemon.configStore.Runtimes[config.StockRuntimeName] = types.Runtime{Path: DefaultRuntimeBinary}
  538. }
  539. if conf.DefaultRuntime != "" {
  540. daemon.configStore.DefaultRuntime = conf.DefaultRuntime
  541. }
  542. if conf.IsValueSet("default-shm-size") {
  543. daemon.configStore.ShmSize = conf.ShmSize
  544. }
  545. if conf.IpcMode != "" {
  546. daemon.configStore.IpcMode = conf.IpcMode
  547. }
  548. // Update attributes
  549. var runtimeList bytes.Buffer
  550. for name, rt := range daemon.configStore.Runtimes {
  551. if runtimeList.Len() > 0 {
  552. runtimeList.WriteRune(' ')
  553. }
  554. runtimeList.WriteString(fmt.Sprintf("%s:%s", name, rt))
  555. }
  556. attributes["runtimes"] = runtimeList.String()
  557. attributes["default-runtime"] = daemon.configStore.DefaultRuntime
  558. attributes["default-shm-size"] = fmt.Sprintf("%d", daemon.configStore.ShmSize)
  559. attributes["default-ipc-mode"] = daemon.configStore.IpcMode
  560. return nil
  561. }
  562. // verifyDaemonSettings performs validation of daemon config struct
  563. func verifyDaemonSettings(conf *config.Config) error {
  564. // Check for mutually incompatible config options
  565. if conf.BridgeConfig.Iface != "" && conf.BridgeConfig.IP != "" {
  566. return fmt.Errorf("You specified -b & --bip, mutually exclusive options. Please specify only one")
  567. }
  568. if !conf.BridgeConfig.EnableIPTables && !conf.BridgeConfig.InterContainerCommunication {
  569. return fmt.Errorf("You specified --iptables=false with --icc=false. ICC=false uses iptables to function. Please set --icc or --iptables to true")
  570. }
  571. if !conf.BridgeConfig.EnableIPTables && conf.BridgeConfig.EnableIPMasq {
  572. conf.BridgeConfig.EnableIPMasq = false
  573. }
  574. if err := VerifyCgroupDriver(conf); err != nil {
  575. return err
  576. }
  577. if conf.CgroupParent != "" && UsingSystemd(conf) {
  578. if len(conf.CgroupParent) <= 6 || !strings.HasSuffix(conf.CgroupParent, ".slice") {
  579. return fmt.Errorf("cgroup-parent for systemd cgroup should be a valid slice named as \"xxx.slice\"")
  580. }
  581. }
  582. if conf.DefaultRuntime == "" {
  583. conf.DefaultRuntime = config.StockRuntimeName
  584. }
  585. if conf.Runtimes == nil {
  586. conf.Runtimes = make(map[string]types.Runtime)
  587. }
  588. conf.Runtimes[config.StockRuntimeName] = types.Runtime{Path: DefaultRuntimeBinary}
  589. return nil
  590. }
  591. // checkSystem validates platform-specific requirements
  592. func checkSystem() error {
  593. if os.Geteuid() != 0 {
  594. return fmt.Errorf("The Docker daemon needs to be run as root")
  595. }
  596. return checkKernel()
  597. }
  598. // configureMaxThreads sets the Go runtime max threads threshold
  599. // which is 90% of the kernel setting from /proc/sys/kernel/threads-max
  600. func configureMaxThreads(config *config.Config) error {
  601. mt, err := ioutil.ReadFile("/proc/sys/kernel/threads-max")
  602. if err != nil {
  603. return err
  604. }
  605. mtint, err := strconv.Atoi(strings.TrimSpace(string(mt)))
  606. if err != nil {
  607. return err
  608. }
  609. maxThreads := (mtint / 100) * 90
  610. debug.SetMaxThreads(maxThreads)
  611. logrus.Debugf("Golang's threads limit set to %d", maxThreads)
  612. return nil
  613. }
  614. func overlaySupportsSelinux() (bool, error) {
  615. f, err := os.Open("/proc/kallsyms")
  616. if err != nil {
  617. if os.IsNotExist(err) {
  618. return false, nil
  619. }
  620. return false, err
  621. }
  622. defer f.Close()
  623. var symAddr, symType, symName, text string
  624. s := bufio.NewScanner(f)
  625. for s.Scan() {
  626. if err := s.Err(); err != nil {
  627. return false, err
  628. }
  629. text = s.Text()
  630. if _, err := fmt.Sscanf(text, "%s %s %s", &symAddr, &symType, &symName); err != nil {
  631. return false, fmt.Errorf("Scanning '%s' failed: %s", text, err)
  632. }
  633. // Check for presence of symbol security_inode_copy_up.
  634. if symName == "security_inode_copy_up" {
  635. return true, nil
  636. }
  637. }
  638. return false, nil
  639. }
  640. // configureKernelSecuritySupport configures and validates security support for the kernel
  641. func configureKernelSecuritySupport(config *config.Config, driverNames []string) error {
  642. if config.EnableSelinuxSupport {
  643. if !selinuxEnabled() {
  644. logrus.Warn("Docker could not enable SELinux on the host system")
  645. return nil
  646. }
  647. overlayFound := false
  648. for _, d := range driverNames {
  649. if d == "overlay" || d == "overlay2" {
  650. overlayFound = true
  651. break
  652. }
  653. }
  654. if overlayFound {
  655. // If driver is overlay or overlay2, make sure kernel
  656. // supports selinux with overlay.
  657. supported, err := overlaySupportsSelinux()
  658. if err != nil {
  659. return err
  660. }
  661. if !supported {
  662. logrus.Warnf("SELinux is not supported with the %v graph driver on this kernel", driverNames)
  663. }
  664. }
  665. } else {
  666. selinuxSetDisabled()
  667. }
  668. return nil
  669. }
  670. func (daemon *Daemon) initNetworkController(config *config.Config, activeSandboxes map[string]interface{}) (libnetwork.NetworkController, error) {
  671. netOptions, err := daemon.networkOptions(config, daemon.PluginStore, activeSandboxes)
  672. if err != nil {
  673. return nil, err
  674. }
  675. controller, err := libnetwork.New(netOptions...)
  676. if err != nil {
  677. return nil, fmt.Errorf("error obtaining controller instance: %v", err)
  678. }
  679. if len(activeSandboxes) > 0 {
  680. logrus.Info("There are old running containers, the network config will not take affect")
  681. return controller, nil
  682. }
  683. // Initialize default network on "null"
  684. if n, _ := controller.NetworkByName("none"); n == nil {
  685. if _, err := controller.NewNetwork("null", "none", "", libnetwork.NetworkOptionPersist(true)); err != nil {
  686. return nil, fmt.Errorf("Error creating default \"null\" network: %v", err)
  687. }
  688. }
  689. // Initialize default network on "host"
  690. if n, _ := controller.NetworkByName("host"); n == nil {
  691. if _, err := controller.NewNetwork("host", "host", "", libnetwork.NetworkOptionPersist(true)); err != nil {
  692. return nil, fmt.Errorf("Error creating default \"host\" network: %v", err)
  693. }
  694. }
  695. // Clear stale bridge network
  696. if n, err := controller.NetworkByName("bridge"); err == nil {
  697. if err = n.Delete(); err != nil {
  698. return nil, fmt.Errorf("could not delete the default bridge network: %v", err)
  699. }
  700. }
  701. if !config.DisableBridge {
  702. // Initialize default driver "bridge"
  703. if err := initBridgeDriver(controller, config); err != nil {
  704. return nil, err
  705. }
  706. } else {
  707. removeDefaultBridgeInterface()
  708. }
  709. return controller, nil
  710. }
  711. func driverOptions(config *config.Config) []nwconfig.Option {
  712. bridgeConfig := options.Generic{
  713. "EnableIPForwarding": config.BridgeConfig.EnableIPForward,
  714. "EnableIPTables": config.BridgeConfig.EnableIPTables,
  715. "EnableUserlandProxy": config.BridgeConfig.EnableUserlandProxy,
  716. "UserlandProxyPath": config.BridgeConfig.UserlandProxyPath}
  717. bridgeOption := options.Generic{netlabel.GenericData: bridgeConfig}
  718. dOptions := []nwconfig.Option{}
  719. dOptions = append(dOptions, nwconfig.OptionDriverConfig("bridge", bridgeOption))
  720. return dOptions
  721. }
  722. func initBridgeDriver(controller libnetwork.NetworkController, config *config.Config) error {
  723. bridgeName := bridge.DefaultBridgeName
  724. if config.BridgeConfig.Iface != "" {
  725. bridgeName = config.BridgeConfig.Iface
  726. }
  727. netOption := map[string]string{
  728. bridge.BridgeName: bridgeName,
  729. bridge.DefaultBridge: strconv.FormatBool(true),
  730. netlabel.DriverMTU: strconv.Itoa(config.Mtu),
  731. bridge.EnableIPMasquerade: strconv.FormatBool(config.BridgeConfig.EnableIPMasq),
  732. bridge.EnableICC: strconv.FormatBool(config.BridgeConfig.InterContainerCommunication),
  733. }
  734. // --ip processing
  735. if config.BridgeConfig.DefaultIP != nil {
  736. netOption[bridge.DefaultBindingIP] = config.BridgeConfig.DefaultIP.String()
  737. }
  738. var (
  739. ipamV4Conf *libnetwork.IpamConf
  740. ipamV6Conf *libnetwork.IpamConf
  741. )
  742. ipamV4Conf = &libnetwork.IpamConf{AuxAddresses: make(map[string]string)}
  743. nwList, nw6List, err := netutils.ElectInterfaceAddresses(bridgeName)
  744. if err != nil {
  745. return errors.Wrap(err, "list bridge addresses failed")
  746. }
  747. nw := nwList[0]
  748. if len(nwList) > 1 && config.BridgeConfig.FixedCIDR != "" {
  749. _, fCIDR, err := net.ParseCIDR(config.BridgeConfig.FixedCIDR)
  750. if err != nil {
  751. return errors.Wrap(err, "parse CIDR failed")
  752. }
  753. // Iterate through in case there are multiple addresses for the bridge
  754. for _, entry := range nwList {
  755. if fCIDR.Contains(entry.IP) {
  756. nw = entry
  757. break
  758. }
  759. }
  760. }
  761. ipamV4Conf.PreferredPool = lntypes.GetIPNetCanonical(nw).String()
  762. hip, _ := lntypes.GetHostPartIP(nw.IP, nw.Mask)
  763. if hip.IsGlobalUnicast() {
  764. ipamV4Conf.Gateway = nw.IP.String()
  765. }
  766. if config.BridgeConfig.IP != "" {
  767. ipamV4Conf.PreferredPool = config.BridgeConfig.IP
  768. ip, _, err := net.ParseCIDR(config.BridgeConfig.IP)
  769. if err != nil {
  770. return err
  771. }
  772. ipamV4Conf.Gateway = ip.String()
  773. } else if bridgeName == bridge.DefaultBridgeName && ipamV4Conf.PreferredPool != "" {
  774. logrus.Infof("Default bridge (%s) is assigned with an IP address %s. Daemon option --bip can be used to set a preferred IP address", bridgeName, ipamV4Conf.PreferredPool)
  775. }
  776. if config.BridgeConfig.FixedCIDR != "" {
  777. _, fCIDR, err := net.ParseCIDR(config.BridgeConfig.FixedCIDR)
  778. if err != nil {
  779. return err
  780. }
  781. ipamV4Conf.SubPool = fCIDR.String()
  782. }
  783. if config.BridgeConfig.DefaultGatewayIPv4 != nil {
  784. ipamV4Conf.AuxAddresses["DefaultGatewayIPv4"] = config.BridgeConfig.DefaultGatewayIPv4.String()
  785. }
  786. var deferIPv6Alloc bool
  787. if config.BridgeConfig.FixedCIDRv6 != "" {
  788. _, fCIDRv6, err := net.ParseCIDR(config.BridgeConfig.FixedCIDRv6)
  789. if err != nil {
  790. return err
  791. }
  792. // In case user has specified the daemon flag --fixed-cidr-v6 and the passed network has
  793. // at least 48 host bits, we need to guarantee the current behavior where the containers'
  794. // IPv6 addresses will be constructed based on the containers' interface MAC address.
  795. // We do so by telling libnetwork to defer the IPv6 address allocation for the endpoints
  796. // on this network until after the driver has created the endpoint and returned the
  797. // constructed address. Libnetwork will then reserve this address with the ipam driver.
  798. ones, _ := fCIDRv6.Mask.Size()
  799. deferIPv6Alloc = ones <= 80
  800. if ipamV6Conf == nil {
  801. ipamV6Conf = &libnetwork.IpamConf{AuxAddresses: make(map[string]string)}
  802. }
  803. ipamV6Conf.PreferredPool = fCIDRv6.String()
  804. // In case the --fixed-cidr-v6 is specified and the current docker0 bridge IPv6
  805. // address belongs to the same network, we need to inform libnetwork about it, so
  806. // that it can be reserved with IPAM and it will not be given away to somebody else
  807. for _, nw6 := range nw6List {
  808. if fCIDRv6.Contains(nw6.IP) {
  809. ipamV6Conf.Gateway = nw6.IP.String()
  810. break
  811. }
  812. }
  813. }
  814. if config.BridgeConfig.DefaultGatewayIPv6 != nil {
  815. if ipamV6Conf == nil {
  816. ipamV6Conf = &libnetwork.IpamConf{AuxAddresses: make(map[string]string)}
  817. }
  818. ipamV6Conf.AuxAddresses["DefaultGatewayIPv6"] = config.BridgeConfig.DefaultGatewayIPv6.String()
  819. }
  820. v4Conf := []*libnetwork.IpamConf{ipamV4Conf}
  821. v6Conf := []*libnetwork.IpamConf{}
  822. if ipamV6Conf != nil {
  823. v6Conf = append(v6Conf, ipamV6Conf)
  824. }
  825. // Initialize default network on "bridge" with the same name
  826. _, err = controller.NewNetwork("bridge", "bridge", "",
  827. libnetwork.NetworkOptionEnableIPv6(config.BridgeConfig.EnableIPv6),
  828. libnetwork.NetworkOptionDriverOpts(netOption),
  829. libnetwork.NetworkOptionIpam("default", "", v4Conf, v6Conf, nil),
  830. libnetwork.NetworkOptionDeferIPv6Alloc(deferIPv6Alloc))
  831. if err != nil {
  832. return fmt.Errorf("Error creating default \"bridge\" network: %v", err)
  833. }
  834. return nil
  835. }
  836. // Remove default bridge interface if present (--bridge=none use case)
  837. func removeDefaultBridgeInterface() {
  838. if lnk, err := netlink.LinkByName(bridge.DefaultBridgeName); err == nil {
  839. if err := netlink.LinkDel(lnk); err != nil {
  840. logrus.Warnf("Failed to remove bridge interface (%s): %v", bridge.DefaultBridgeName, err)
  841. }
  842. }
  843. }
  844. func (daemon *Daemon) getLayerInit() func(string) error {
  845. return daemon.setupInitLayer
  846. }
  847. // Parse the remapped root (user namespace) option, which can be one of:
  848. // username - valid username from /etc/passwd
  849. // username:groupname - valid username; valid groupname from /etc/group
  850. // uid - 32-bit unsigned int valid Linux UID value
  851. // uid:gid - uid value; 32-bit unsigned int Linux GID value
  852. //
  853. // If no groupname is specified, and a username is specified, an attempt
  854. // will be made to lookup a gid for that username as a groupname
  855. //
  856. // If names are used, they are verified to exist in passwd/group
  857. func parseRemappedRoot(usergrp string) (string, string, error) {
  858. var (
  859. userID, groupID int
  860. username, groupname string
  861. )
  862. idparts := strings.Split(usergrp, ":")
  863. if len(idparts) > 2 {
  864. return "", "", fmt.Errorf("Invalid user/group specification in --userns-remap: %q", usergrp)
  865. }
  866. if uid, err := strconv.ParseInt(idparts[0], 10, 32); err == nil {
  867. // must be a uid; take it as valid
  868. userID = int(uid)
  869. luser, err := idtools.LookupUID(userID)
  870. if err != nil {
  871. return "", "", fmt.Errorf("Uid %d has no entry in /etc/passwd: %v", userID, err)
  872. }
  873. username = luser.Name
  874. if len(idparts) == 1 {
  875. // if the uid was numeric and no gid was specified, take the uid as the gid
  876. groupID = userID
  877. lgrp, err := idtools.LookupGID(groupID)
  878. if err != nil {
  879. return "", "", fmt.Errorf("Gid %d has no entry in /etc/group: %v", groupID, err)
  880. }
  881. groupname = lgrp.Name
  882. }
  883. } else {
  884. lookupName := idparts[0]
  885. // special case: if the user specified "default", they want Docker to create or
  886. // use (after creation) the "dockremap" user/group for root remapping
  887. if lookupName == defaultIDSpecifier {
  888. lookupName = defaultRemappedID
  889. }
  890. luser, err := idtools.LookupUser(lookupName)
  891. if err != nil && idparts[0] != defaultIDSpecifier {
  892. // error if the name requested isn't the special "dockremap" ID
  893. return "", "", fmt.Errorf("Error during uid lookup for %q: %v", lookupName, err)
  894. } else if err != nil {
  895. // special case-- if the username == "default", then we have been asked
  896. // to create a new entry pair in /etc/{passwd,group} for which the /etc/sub{uid,gid}
  897. // ranges will be used for the user and group mappings in user namespaced containers
  898. _, _, err := idtools.AddNamespaceRangesUser(defaultRemappedID)
  899. if err == nil {
  900. return defaultRemappedID, defaultRemappedID, nil
  901. }
  902. return "", "", fmt.Errorf("Error during %q user creation: %v", defaultRemappedID, err)
  903. }
  904. username = luser.Name
  905. if len(idparts) == 1 {
  906. // we only have a string username, and no group specified; look up gid from username as group
  907. group, err := idtools.LookupGroup(lookupName)
  908. if err != nil {
  909. return "", "", fmt.Errorf("Error during gid lookup for %q: %v", lookupName, err)
  910. }
  911. groupname = group.Name
  912. }
  913. }
  914. if len(idparts) == 2 {
  915. // groupname or gid is separately specified and must be resolved
  916. // to an unsigned 32-bit gid
  917. if gid, err := strconv.ParseInt(idparts[1], 10, 32); err == nil {
  918. // must be a gid, take it as valid
  919. groupID = int(gid)
  920. lgrp, err := idtools.LookupGID(groupID)
  921. if err != nil {
  922. return "", "", fmt.Errorf("Gid %d has no entry in /etc/passwd: %v", groupID, err)
  923. }
  924. groupname = lgrp.Name
  925. } else {
  926. // not a number; attempt a lookup
  927. if _, err := idtools.LookupGroup(idparts[1]); err != nil {
  928. return "", "", fmt.Errorf("Error during groupname lookup for %q: %v", idparts[1], err)
  929. }
  930. groupname = idparts[1]
  931. }
  932. }
  933. return username, groupname, nil
  934. }
  935. func setupRemappedRoot(config *config.Config) (*idtools.IDMappings, error) {
  936. if runtime.GOOS != "linux" && config.RemappedRoot != "" {
  937. return nil, fmt.Errorf("User namespaces are only supported on Linux")
  938. }
  939. // if the daemon was started with remapped root option, parse
  940. // the config option to the int uid,gid values
  941. if config.RemappedRoot != "" {
  942. username, groupname, err := parseRemappedRoot(config.RemappedRoot)
  943. if err != nil {
  944. return nil, err
  945. }
  946. if username == "root" {
  947. // Cannot setup user namespaces with a 1-to-1 mapping; "--root=0:0" is a no-op
  948. // effectively
  949. logrus.Warn("User namespaces: root cannot be remapped with itself; user namespaces are OFF")
  950. return &idtools.IDMappings{}, nil
  951. }
  952. logrus.Infof("User namespaces: ID ranges will be mapped to subuid/subgid ranges of: %s:%s", username, groupname)
  953. // update remapped root setting now that we have resolved them to actual names
  954. config.RemappedRoot = fmt.Sprintf("%s:%s", username, groupname)
  955. mappings, err := idtools.NewIDMappings(username, groupname)
  956. if err != nil {
  957. return nil, errors.Wrapf(err, "Can't create ID mappings: %v")
  958. }
  959. return mappings, nil
  960. }
  961. return &idtools.IDMappings{}, nil
  962. }
  963. func setupDaemonRoot(config *config.Config, rootDir string, rootIDs idtools.IDPair) error {
  964. config.Root = rootDir
  965. // the docker root metadata directory needs to have execute permissions for all users (g+x,o+x)
  966. // so that syscalls executing as non-root, operating on subdirectories of the graph root
  967. // (e.g. mounted layers of a container) can traverse this path.
  968. // The user namespace support will create subdirectories for the remapped root host uid:gid
  969. // pair owned by that same uid:gid pair for proper write access to those needed metadata and
  970. // layer content subtrees.
  971. if _, err := os.Stat(rootDir); err == nil {
  972. // root current exists; verify the access bits are correct by setting them
  973. if err = os.Chmod(rootDir, 0711); err != nil {
  974. return err
  975. }
  976. } else if os.IsNotExist(err) {
  977. // no root exists yet, create it 0711 with root:root ownership
  978. if err := os.MkdirAll(rootDir, 0711); err != nil {
  979. return err
  980. }
  981. }
  982. // if user namespaces are enabled we will create a subtree underneath the specified root
  983. // with any/all specified remapped root uid/gid options on the daemon creating
  984. // a new subdirectory with ownership set to the remapped uid/gid (so as to allow
  985. // `chdir()` to work for containers namespaced to that uid/gid)
  986. if config.RemappedRoot != "" {
  987. config.Root = filepath.Join(rootDir, fmt.Sprintf("%d.%d", rootIDs.UID, rootIDs.GID))
  988. logrus.Debugf("Creating user namespaced daemon root: %s", config.Root)
  989. // Create the root directory if it doesn't exist
  990. if err := idtools.MkdirAllAndChown(config.Root, 0700, rootIDs); err != nil {
  991. return fmt.Errorf("Cannot create daemon root: %s: %v", config.Root, err)
  992. }
  993. // we also need to verify that any pre-existing directories in the path to
  994. // the graphroot won't block access to remapped root--if any pre-existing directory
  995. // has strict permissions that don't allow "x", container start will fail, so
  996. // better to warn and fail now
  997. dirPath := config.Root
  998. for {
  999. dirPath = filepath.Dir(dirPath)
  1000. if dirPath == "/" {
  1001. break
  1002. }
  1003. if !idtools.CanAccess(dirPath, rootIDs) {
  1004. return fmt.Errorf("a subdirectory in your graphroot path (%s) restricts access to the remapped root uid/gid; please fix by allowing 'o+x' permissions on existing directories", config.Root)
  1005. }
  1006. }
  1007. }
  1008. return nil
  1009. }
  1010. // registerLinks writes the links to a file.
  1011. func (daemon *Daemon) registerLinks(container *container.Container, hostConfig *containertypes.HostConfig) error {
  1012. if hostConfig == nil || hostConfig.NetworkMode.IsUserDefined() {
  1013. return nil
  1014. }
  1015. for _, l := range hostConfig.Links {
  1016. name, alias, err := opts.ParseLink(l)
  1017. if err != nil {
  1018. return err
  1019. }
  1020. child, err := daemon.GetContainer(name)
  1021. if err != nil {
  1022. return errors.Wrapf(err, "could not get container for %s", name)
  1023. }
  1024. for child.HostConfig.NetworkMode.IsContainer() {
  1025. parts := strings.SplitN(string(child.HostConfig.NetworkMode), ":", 2)
  1026. child, err = daemon.GetContainer(parts[1])
  1027. if err != nil {
  1028. return errors.Wrapf(err, "Could not get container for %s", parts[1])
  1029. }
  1030. }
  1031. if child.HostConfig.NetworkMode.IsHost() {
  1032. return runconfig.ErrConflictHostNetworkAndLinks
  1033. }
  1034. if err := daemon.registerLink(container, child, alias); err != nil {
  1035. return err
  1036. }
  1037. }
  1038. // After we load all the links into the daemon
  1039. // set them to nil on the hostconfig
  1040. _, err := container.WriteHostConfig()
  1041. return err
  1042. }
  1043. // conditionalMountOnStart is a platform specific helper function during the
  1044. // container start to call mount.
  1045. func (daemon *Daemon) conditionalMountOnStart(container *container.Container) error {
  1046. return daemon.Mount(container)
  1047. }
  1048. // conditionalUnmountOnCleanup is a platform specific helper function called
  1049. // during the cleanup of a container to unmount.
  1050. func (daemon *Daemon) conditionalUnmountOnCleanup(container *container.Container) error {
  1051. return daemon.Unmount(container)
  1052. }
  1053. func (daemon *Daemon) stats(c *container.Container) (*types.StatsJSON, error) {
  1054. if !c.IsRunning() {
  1055. return nil, errNotRunning(c.ID)
  1056. }
  1057. stats, err := daemon.containerd.Stats(c.ID)
  1058. if err != nil {
  1059. if strings.Contains(err.Error(), "container not found") {
  1060. return nil, containerNotFound(c.ID)
  1061. }
  1062. return nil, err
  1063. }
  1064. s := &types.StatsJSON{}
  1065. cgs := stats.CgroupStats
  1066. if cgs != nil {
  1067. s.BlkioStats = types.BlkioStats{
  1068. IoServiceBytesRecursive: copyBlkioEntry(cgs.BlkioStats.IoServiceBytesRecursive),
  1069. IoServicedRecursive: copyBlkioEntry(cgs.BlkioStats.IoServicedRecursive),
  1070. IoQueuedRecursive: copyBlkioEntry(cgs.BlkioStats.IoQueuedRecursive),
  1071. IoServiceTimeRecursive: copyBlkioEntry(cgs.BlkioStats.IoServiceTimeRecursive),
  1072. IoWaitTimeRecursive: copyBlkioEntry(cgs.BlkioStats.IoWaitTimeRecursive),
  1073. IoMergedRecursive: copyBlkioEntry(cgs.BlkioStats.IoMergedRecursive),
  1074. IoTimeRecursive: copyBlkioEntry(cgs.BlkioStats.IoTimeRecursive),
  1075. SectorsRecursive: copyBlkioEntry(cgs.BlkioStats.SectorsRecursive),
  1076. }
  1077. cpu := cgs.CpuStats
  1078. s.CPUStats = types.CPUStats{
  1079. CPUUsage: types.CPUUsage{
  1080. TotalUsage: cpu.CpuUsage.TotalUsage,
  1081. PercpuUsage: cpu.CpuUsage.PercpuUsage,
  1082. UsageInKernelmode: cpu.CpuUsage.UsageInKernelmode,
  1083. UsageInUsermode: cpu.CpuUsage.UsageInUsermode,
  1084. },
  1085. ThrottlingData: types.ThrottlingData{
  1086. Periods: cpu.ThrottlingData.Periods,
  1087. ThrottledPeriods: cpu.ThrottlingData.ThrottledPeriods,
  1088. ThrottledTime: cpu.ThrottlingData.ThrottledTime,
  1089. },
  1090. }
  1091. mem := cgs.MemoryStats.Usage
  1092. s.MemoryStats = types.MemoryStats{
  1093. Usage: mem.Usage,
  1094. MaxUsage: mem.MaxUsage,
  1095. Stats: cgs.MemoryStats.Stats,
  1096. Failcnt: mem.Failcnt,
  1097. Limit: mem.Limit,
  1098. }
  1099. // if the container does not set memory limit, use the machineMemory
  1100. if mem.Limit > daemon.machineMemory && daemon.machineMemory > 0 {
  1101. s.MemoryStats.Limit = daemon.machineMemory
  1102. }
  1103. if cgs.PidsStats != nil {
  1104. s.PidsStats = types.PidsStats{
  1105. Current: cgs.PidsStats.Current,
  1106. }
  1107. }
  1108. }
  1109. s.Read, err = ptypes.Timestamp(stats.Timestamp)
  1110. if err != nil {
  1111. return nil, err
  1112. }
  1113. return s, nil
  1114. }
  1115. // setDefaultIsolation determines the default isolation mode for the
  1116. // daemon to run in. This is only applicable on Windows
  1117. func (daemon *Daemon) setDefaultIsolation() error {
  1118. return nil
  1119. }
  1120. func rootFSToAPIType(rootfs *image.RootFS) types.RootFS {
  1121. var layers []string
  1122. for _, l := range rootfs.DiffIDs {
  1123. layers = append(layers, l.String())
  1124. }
  1125. return types.RootFS{
  1126. Type: rootfs.Type,
  1127. Layers: layers,
  1128. }
  1129. }
  1130. // setupDaemonProcess sets various settings for the daemon's process
  1131. func setupDaemonProcess(config *config.Config) error {
  1132. // setup the daemons oom_score_adj
  1133. return setupOOMScoreAdj(config.OOMScoreAdjust)
  1134. }
  1135. func setupOOMScoreAdj(score int) error {
  1136. f, err := os.OpenFile("/proc/self/oom_score_adj", os.O_WRONLY, 0)
  1137. if err != nil {
  1138. return err
  1139. }
  1140. defer f.Close()
  1141. stringScore := strconv.Itoa(score)
  1142. _, err = f.WriteString(stringScore)
  1143. if os.IsPermission(err) {
  1144. // Setting oom_score_adj does not work in an
  1145. // unprivileged container. Ignore the error, but log
  1146. // it if we appear not to be in that situation.
  1147. if !rsystem.RunningInUserNS() {
  1148. logrus.Debugf("Permission denied writing %q to /proc/self/oom_score_adj", stringScore)
  1149. }
  1150. return nil
  1151. }
  1152. return err
  1153. }
  1154. func (daemon *Daemon) initCgroupsPath(path string) error {
  1155. if path == "/" || path == "." {
  1156. return nil
  1157. }
  1158. if daemon.configStore.CPURealtimePeriod == 0 && daemon.configStore.CPURealtimeRuntime == 0 {
  1159. return nil
  1160. }
  1161. // Recursively create cgroup to ensure that the system and all parent cgroups have values set
  1162. // for the period and runtime as this limits what the children can be set to.
  1163. daemon.initCgroupsPath(filepath.Dir(path))
  1164. mnt, root, err := cgroups.FindCgroupMountpointAndRoot("cpu")
  1165. if err != nil {
  1166. return err
  1167. }
  1168. // When docker is run inside docker, the root is based of the host cgroup.
  1169. // Should this be handled in runc/libcontainer/cgroups ?
  1170. if strings.HasPrefix(root, "/docker/") {
  1171. root = "/"
  1172. }
  1173. path = filepath.Join(mnt, root, path)
  1174. sysinfo := sysinfo.New(true)
  1175. if err := maybeCreateCPURealTimeFile(sysinfo.CPURealtimePeriod, daemon.configStore.CPURealtimePeriod, "cpu.rt_period_us", path); err != nil {
  1176. return err
  1177. }
  1178. if err := maybeCreateCPURealTimeFile(sysinfo.CPURealtimeRuntime, daemon.configStore.CPURealtimeRuntime, "cpu.rt_runtime_us", path); err != nil {
  1179. return err
  1180. }
  1181. return nil
  1182. }
  1183. func maybeCreateCPURealTimeFile(sysinfoPresent bool, configValue int64, file string, path string) error {
  1184. if sysinfoPresent && configValue != 0 {
  1185. if err := os.MkdirAll(path, 0755); err != nil && !os.IsExist(err) {
  1186. return err
  1187. }
  1188. if err := ioutil.WriteFile(filepath.Join(path, file), []byte(strconv.FormatInt(configValue, 10)), 0700); err != nil {
  1189. return err
  1190. }
  1191. }
  1192. return nil
  1193. }
  1194. func (daemon *Daemon) setupSeccompProfile() error {
  1195. if daemon.configStore.SeccompProfile != "" {
  1196. daemon.seccompProfilePath = daemon.configStore.SeccompProfile
  1197. b, err := ioutil.ReadFile(daemon.configStore.SeccompProfile)
  1198. if err != nil {
  1199. return fmt.Errorf("opening seccomp profile (%s) failed: %v", daemon.configStore.SeccompProfile, err)
  1200. }
  1201. daemon.seccompProfile = b
  1202. }
  1203. return nil
  1204. }