Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-pages.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Thomas <nick@gitlab.com>2018-04-25 00:42:56 +0300
committerNick Thomas <nick@gitlab.com>2018-04-27 19:13:46 +0300
commit7667febecf3bb627d3e0912a59fa1d8918519280 (patch)
treeb7037c5429cdb3eb4e7b205a8c4f8c0aaf1e010a /internal/jail
parent05c03d65f64021f4a3ead9b627b7293e7b63ca07 (diff)
Restore the old in-place chroot behaviour as a command-line option
Diffstat (limited to 'internal/jail')
-rw-r--r--internal/jail/jail.go55
-rw-r--r--internal/jail/jail_test.go43
2 files changed, 76 insertions, 22 deletions
diff --git a/internal/jail/jail.go b/internal/jail/jail.go
index d2b04be0..22f22eac 100644
--- a/internal/jail/jail.go
+++ b/internal/jail/jail.go
@@ -21,30 +21,45 @@ type pathAndMode struct {
// Jail is a Chroot jail builder
type Jail struct {
+ root string
+ deleteRoot bool
directories []pathAndMode
files map[string]pathAndMode
bindMounts map[string]string
}
-// New returns a Jail for path
-func New(path string, perm os.FileMode) *Jail {
+// Into returns a Jail on path, assuming it already exists on disk. On disposal,
+// the jail *will not* remove the path
+func Into(path string) *Jail {
return &Jail{
- directories: []pathAndMode{pathAndMode{path: path, mode: perm}},
- files: make(map[string]pathAndMode),
- bindMounts: make(map[string]string),
+ root: path,
+ deleteRoot: false,
+ files: make(map[string]pathAndMode),
+ bindMounts: make(map[string]string),
}
}
-// TimestampedJail return a Jail with Path composed by prefix and current timestamp
-func TimestampedJail(prefix string, perm os.FileMode) *Jail {
+// Create returns a Jail on path, creating the directory if needed. On disposal,
+// the jail will remove the path
+func Create(path string, perm os.FileMode) *Jail {
+ jail := Into(path)
+ jail.deleteRoot = true
+ jail.directories = append(jail.directories, pathAndMode{path: path, mode: perm})
+
+ return jail
+}
+
+// CreateTimestamped returns a Jail on a path composed by prefix and current
+// timestamp, creating the directory. On disposal, the jail will remove the path
+func CreateTimestamped(prefix string, perm os.FileMode) *Jail {
jailPath := path.Join(os.TempDir(), fmt.Sprintf("%s-%d", prefix, time.Now().UnixNano()))
- return New(jailPath, perm)
+ return Create(jailPath, perm)
}
// Path returns the path of the jail
func (j *Jail) Path() string {
- return j.directories[0].path
+ return j.root
}
// Build creates the jail, making directories and copying files. If an error
@@ -87,7 +102,27 @@ func (j *Jail) Build() error {
}
func (j *Jail) removeAll() error {
- return os.RemoveAll(j.Path())
+ // Deleting the root will remove all child directories, so there's no need
+ // to traverse files and directories
+ if j.deleteRoot {
+ if err := os.RemoveAll(j.Path()); err != nil {
+ return fmt.Errorf("Can't delete jail %q. %s", j.Path(), err)
+ }
+ } else {
+ for path := range j.files {
+ if err := os.Remove(path); err != nil {
+ return fmt.Errorf("Can't delete file in jail %q: %s", path, err)
+ }
+ }
+
+ for _, dest := range j.directories {
+ if err := os.Remove(dest.path); err != nil {
+ return fmt.Errorf("Can't delete directory in jail %q: %s", dest.path, err)
+ }
+ }
+ }
+
+ return nil
}
// Dispose erases everything inside the jail
diff --git a/internal/jail/jail_test.go b/internal/jail/jail_test.go
index 04a00a74..cb242b35 100644
--- a/internal/jail/jail_test.go
+++ b/internal/jail/jail_test.go
@@ -26,8 +26,8 @@ func TestTimestampedJails(t *testing.T) {
prefix := "jail"
var mode os.FileMode = 0755
- j1 := jail.TimestampedJail(prefix, mode)
- j2 := jail.TimestampedJail(prefix, mode)
+ j1 := jail.CreateTimestamped(prefix, mode)
+ j2 := jail.CreateTimestamped(prefix, mode)
assert.NotEqual(j1.Path, j2.Path())
}
@@ -36,7 +36,7 @@ func TestJailPath(t *testing.T) {
assert := assert.New(t)
jailPath := tmpJailPath()
- cage := jail.New(jailPath, 0755)
+ cage := jail.Create(jailPath, 0755)
assert.Equal(jailPath, cage.Path())
}
@@ -45,7 +45,7 @@ func TestJailBuild(t *testing.T) {
assert := assert.New(t)
jailPath := tmpJailPath()
- cage := jail.New(jailPath, 0755)
+ cage := jail.Create(jailPath, 0755)
_, err := os.Stat(cage.Path())
assert.Error(err, "Jail path should not exist before Jail.Build()")
@@ -60,7 +60,7 @@ func TestJailBuild(t *testing.T) {
func TestJailOnlySupportsOneBindMount(t *testing.T) {
jailPath := tmpJailPath()
- cage := jail.New(jailPath, 0755)
+ cage := jail.Create(jailPath, 0755)
cage.Bind("/bin", "/bin")
cage.Bind("/lib", "/lib")
@@ -75,7 +75,7 @@ func TestJailOnlySupportsOneBindMount(t *testing.T) {
func TestJailBuildCleansUpWhenMountFails(t *testing.T) {
jailPath := tmpJailPath()
- cage := jail.New(jailPath, 0755)
+ cage := jail.Create(jailPath, 0755)
cage.Bind("/foo", "/this/path/does/not/exist/so/mount/will/fail")
err := cage.Build()
@@ -89,7 +89,7 @@ func TestJailDispose(t *testing.T) {
assert := assert.New(t)
jailPath := tmpJailPath()
- cage := jail.New(jailPath, 0755)
+ cage := jail.Create(jailPath, 0755)
err := cage.Build()
require.NoError(t, err)
@@ -105,7 +105,7 @@ func TestJailDisposeDoNotFailOnMissingPath(t *testing.T) {
assert := assert.New(t)
jailPath := tmpJailPath()
- cage := jail.New(jailPath, 0755)
+ cage := jail.Create(jailPath, 0755)
_, err := os.Stat(cage.Path())
assert.Error(err, "Jail path should not exist")
@@ -132,7 +132,7 @@ func TestJailWithCharacterDevice(t *testing.T) {
expectedRdev := sys.Rdev
jailPath := tmpJailPath()
- cage := jail.New(jailPath, 0755)
+ cage := jail.Create(jailPath, 0755)
cage.MkDir("/dev", 0755)
require.NoError(t, cage.CharDev("/dev/urandom"))
@@ -182,7 +182,7 @@ func TestJailWithFiles(t *testing.T) {
t.Run(test.name, func(t *testing.T) {
assert := assert.New(t)
- cage := jail.TimestampedJail("jail-mkdir", 0755)
+ cage := jail.CreateTimestamped("jail-mkdir", 0755)
for _, dir := range test.directories {
cage.MkDir(dir, 0755)
}
@@ -219,7 +219,7 @@ func TestJailCopyTo(t *testing.T) {
content := "hello"
- cage := jail.TimestampedJail("check-file-copy", 0755)
+ cage := jail.CreateTimestamped("check-file-copy", 0755)
tmpFile, err := ioutil.TempFile("", "dummy-file")
if err != nil {
@@ -269,7 +269,7 @@ func TestJailLazyUnbind(t *testing.T) {
tmpFile.Close()
jailPath := tmpJailPath()
- cage := jail.New(jailPath, 0755)
+ cage := jail.Create(jailPath, 0755)
cage.MkDir("/my-bind", 0755)
cage.Bind("/my-bind", toBind)
@@ -298,3 +298,22 @@ func TestJailLazyUnbind(t *testing.T) {
_, err = os.Stat(tmpFilePath)
require.NoError(t, err, "disposing a jail should not delete files under binded directories")
}
+
+func TestJailIntoOnlyCleansSubpaths(t *testing.T) {
+ jailPath := tmpJailPath()
+ require.NoError(t, os.MkdirAll(jailPath, 0755))
+ defer os.RemoveAll(jailPath)
+
+ chroot := jail.Into(jailPath)
+ chroot.MkDir("/etc", 0755)
+ chroot.Copy("/etc/resolv.conf")
+ require.NoError(t, chroot.Build())
+ require.NoError(t, chroot.Dispose())
+
+ _, err := os.Stat(path.Join(jailPath, "/etc/resolv.conf"))
+ require.True(t, os.IsNotExist(err), "/etc/resolv.conf in jail was not removed")
+ _, err = os.Stat(path.Join(jailPath, "/etc"))
+ require.True(t, os.IsNotExist(err), "/etc in jail was not removed")
+ _, err = os.Stat(jailPath)
+ require.NoError(t, err, "/ in jail (corresponding to external directory) was removed")
+}