docker_cli_cp_test.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. package main
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. "os"
  6. "path/filepath"
  7. "testing"
  8. )
  9. const (
  10. cpTestPathParent = "/some"
  11. cpTestPath = "/some/path"
  12. cpTestName = "test"
  13. cpFullPath = "/some/path/test"
  14. cpContainerContents = "holla, i am the container"
  15. cpHostContents = "hello, i am the host"
  16. )
  17. // Test for #5656
  18. // Check that garbage paths don't escape the container's rootfs
  19. func TestCpGarbagePath(t *testing.T) {
  20. out, exitCode, err := cmd(t, "run", "-d", "busybox", "/bin/sh", "-c", "mkdir -p '"+cpTestPath+"' && echo -n '"+cpContainerContents+"' > "+cpFullPath)
  21. if err != nil || exitCode != 0 {
  22. t.Fatal("failed to create a container", out, err)
  23. }
  24. cleanedContainerID := stripTrailingCharacters(out)
  25. defer deleteContainer(cleanedContainerID)
  26. out, _, err = cmd(t, "wait", cleanedContainerID)
  27. if err != nil || stripTrailingCharacters(out) != "0" {
  28. t.Fatal("failed to set up container", out, err)
  29. }
  30. if err := os.MkdirAll(cpTestPath, os.ModeDir); err != nil {
  31. t.Fatal(err)
  32. }
  33. hostFile, err := os.Create(cpFullPath)
  34. if err != nil {
  35. t.Fatal(err)
  36. }
  37. defer hostFile.Close()
  38. defer os.RemoveAll(cpTestPathParent)
  39. fmt.Fprintf(hostFile, "%s", cpHostContents)
  40. tmpdir, err := ioutil.TempDir("", "docker-integration")
  41. if err != nil {
  42. t.Fatal(err)
  43. }
  44. tmpname := filepath.Join(tmpdir, cpTestName)
  45. defer os.RemoveAll(tmpdir)
  46. path := filepath.Join("../../../../../../../../../../../../", cpFullPath)
  47. _, _, err = cmd(t, "cp", cleanedContainerID+":"+path, tmpdir)
  48. if err != nil {
  49. t.Fatalf("couldn't copy from garbage path: %s:%s %s", cleanedContainerID, path, err)
  50. }
  51. file, _ := os.Open(tmpname)
  52. defer file.Close()
  53. test, err := ioutil.ReadAll(file)
  54. if err != nil {
  55. t.Fatal(err)
  56. }
  57. if string(test) == cpHostContents {
  58. t.Errorf("output matched host file -- garbage path can escape container rootfs")
  59. }
  60. if string(test) != cpContainerContents {
  61. t.Errorf("output doesn't match the input for garbage path")
  62. }
  63. logDone("cp - garbage paths relative to container's rootfs")
  64. }
  65. // Check that relative paths are relative to the container's rootfs
  66. func TestCpRelativePath(t *testing.T) {
  67. out, exitCode, err := cmd(t, "run", "-d", "busybox", "/bin/sh", "-c", "mkdir -p '"+cpTestPath+"' && echo -n '"+cpContainerContents+"' > "+cpFullPath)
  68. if err != nil || exitCode != 0 {
  69. t.Fatal("failed to create a container", out, err)
  70. }
  71. cleanedContainerID := stripTrailingCharacters(out)
  72. defer deleteContainer(cleanedContainerID)
  73. out, _, err = cmd(t, "wait", cleanedContainerID)
  74. if err != nil || stripTrailingCharacters(out) != "0" {
  75. t.Fatal("failed to set up container", out, err)
  76. }
  77. if err := os.MkdirAll(cpTestPath, os.ModeDir); err != nil {
  78. t.Fatal(err)
  79. }
  80. hostFile, err := os.Create(cpFullPath)
  81. if err != nil {
  82. t.Fatal(err)
  83. }
  84. defer hostFile.Close()
  85. defer os.RemoveAll(cpTestPathParent)
  86. fmt.Fprintf(hostFile, "%s", cpHostContents)
  87. tmpdir, err := ioutil.TempDir("", "docker-integration")
  88. if err != nil {
  89. t.Fatal(err)
  90. }
  91. tmpname := filepath.Join(tmpdir, cpTestName)
  92. defer os.RemoveAll(tmpdir)
  93. path, _ := filepath.Rel("/", cpFullPath)
  94. _, _, err = cmd(t, "cp", cleanedContainerID+":"+path, tmpdir)
  95. if err != nil {
  96. t.Fatalf("couldn't copy from relative path: %s:%s %s", cleanedContainerID, path, err)
  97. }
  98. file, _ := os.Open(tmpname)
  99. defer file.Close()
  100. test, err := ioutil.ReadAll(file)
  101. if err != nil {
  102. t.Fatal(err)
  103. }
  104. if string(test) == cpHostContents {
  105. t.Errorf("output matched host file -- relative path can escape container rootfs")
  106. }
  107. if string(test) != cpContainerContents {
  108. t.Errorf("output doesn't match the input for relative path")
  109. }
  110. logDone("cp - relative paths relative to container's rootfs")
  111. }
  112. // Check that absolute paths are relative to the container's rootfs
  113. func TestCpAbsolutePath(t *testing.T) {
  114. out, exitCode, err := cmd(t, "run", "-d", "busybox", "/bin/sh", "-c", "mkdir -p '"+cpTestPath+"' && echo -n '"+cpContainerContents+"' > "+cpFullPath)
  115. if err != nil || exitCode != 0 {
  116. t.Fatal("failed to create a container", out, err)
  117. }
  118. cleanedContainerID := stripTrailingCharacters(out)
  119. defer deleteContainer(cleanedContainerID)
  120. out, _, err = cmd(t, "wait", cleanedContainerID)
  121. if err != nil || stripTrailingCharacters(out) != "0" {
  122. t.Fatal("failed to set up container", out, err)
  123. }
  124. if err := os.MkdirAll(cpTestPath, os.ModeDir); err != nil {
  125. t.Fatal(err)
  126. }
  127. hostFile, err := os.Create(cpFullPath)
  128. if err != nil {
  129. t.Fatal(err)
  130. }
  131. defer hostFile.Close()
  132. defer os.RemoveAll(cpTestPathParent)
  133. fmt.Fprintf(hostFile, "%s", cpHostContents)
  134. tmpdir, err := ioutil.TempDir("", "docker-integration")
  135. if err != nil {
  136. t.Fatal(err)
  137. }
  138. tmpname := filepath.Join(tmpdir, cpTestName)
  139. defer os.RemoveAll(tmpdir)
  140. path := cpFullPath
  141. _, _, err = cmd(t, "cp", cleanedContainerID+":"+path, tmpdir)
  142. if err != nil {
  143. t.Fatalf("couldn't copy from absolute path: %s:%s %s", cleanedContainerID, path, err)
  144. }
  145. file, _ := os.Open(tmpname)
  146. defer file.Close()
  147. test, err := ioutil.ReadAll(file)
  148. if err != nil {
  149. t.Fatal(err)
  150. }
  151. if string(test) == cpHostContents {
  152. t.Errorf("output matched host file -- absolute path can escape container rootfs")
  153. }
  154. if string(test) != cpContainerContents {
  155. t.Errorf("output doesn't match the input for absolute path")
  156. }
  157. logDone("cp - absolute paths relative to container's rootfs")
  158. }