diff options
author | Alessio Caiazza <acaiazza@gitlab.com> | 2018-03-21 20:29:55 +0300 |
---|---|---|
committer | Nick Thomas <nick@gitlab.com> | 2018-03-21 20:29:55 +0300 |
commit | 51f0df18e3d8dd5f1e0faeea3b2a41e6ff73f551 (patch) | |
tree | 8c222620310e6bb5a967f099314e40428e920c73 /daemon.go | |
parent | fe1561978ed164220e471129c9b2fa6b89d07992 (diff) |
Add /etc/resolv.conf and /etc/ssl/certs to pages chroot
Diffstat (limited to 'daemon.go')
-rw-r--r-- | daemon.go | 113 |
1 files changed, 48 insertions, 65 deletions
@@ -1,21 +1,23 @@ package main import ( - "crypto/rand" "encoding/json" - "fmt" - "io" "os" "os/exec" "os/signal" - "path/filepath" "syscall" "github.com/kardianos/osext" log "github.com/sirupsen/logrus" + + "gitlab.com/gitlab-org/gitlab-pages/internal/jail" ) -const daemonRunProgram = "gitlab-pages-unprivileged" +const ( + daemonRunProgram = "gitlab-pages-unprivileged" + + pagesRootInChroot = "/pages" +) func daemonMain() { if os.Args[0] != daemonRunProgram { @@ -100,77 +102,55 @@ func passSignals(cmd *exec.Cmd) { }() } -func copyFile(dest, src string, perm os.FileMode) (err error) { - srcFile, err := os.Open(src) - if err != nil { - return - } - defer srcFile.Close() - - destFile, err := os.OpenFile(dest, os.O_RDWR|os.O_CREATE|os.O_EXCL, perm) - if err != nil { - return - } - defer destFile.Close() +func daemonChroot(cmd *exec.Cmd) (*jail.Jail, error) { + cage := jail.TimestampedJail("gitlab-pages", 0755) - _, err = io.Copy(destFile, srcFile) - return -} - -func daemonCreateExecutable(name string, perm os.FileMode) (file *os.File, err error) { - // We assume that crypto random generates true random, non-colliding hash - b := make([]byte, 16) - _, err = rand.Read(b) + wd, err := os.Getwd() if err != nil { - return + return nil, err } - path := fmt.Sprintf("%s.%x", name, b) - file, err = os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_EXCL, perm) + // Add gitlab-pages inside the jail + err = cage.CopyTo("/gitlab-pages", cmd.Path) if err != nil { - return + return nil, err } - return -} -func daemonChroot(cmd *exec.Cmd) (path string, err error) { - wd, err := os.Getwd() + // Add /etc/resolv.conf inside the jail + cage.MkDir("/etc", 0755) + err = cage.Copy("/etc/resolv.conf") if err != nil { - return + return nil, err } - // Generate temporary file - temporaryExecutable, err := daemonCreateExecutable(".daemon", 0755) - if err != nil { - return - } - defer temporaryExecutable.Close() - defer func() { - // Remove the temporary file in case of failure + // Copy SSL_CERT_FILE inside the jail + sslCertFile := os.Getenv("SSL_CERT_FILE") + if sslCertFile != "" { + cage.MkDir("/etc/ssl", 0755) + err = cage.CopyTo("/etc/ssl/ca-bundle.pem", sslCertFile) if err != nil { - os.Remove(temporaryExecutable.Name()) + return nil, err } - }() - - // Open current executable - executableFile, err := os.Open(cmd.Path) - if err != nil { - return + cmd.Env = append(os.Environ(), "SSL_CERT_FILE=/etc/ssl/ca-bundle.pem") + } else { + log.Print("Missing SSL_CERT_FILE environment variable. HTTPS requests will fail") } - defer executableFile.Close() - // Copy the executable content - _, err = io.Copy(temporaryExecutable, executableFile) + // Bind mount shared folder + cage.MkDir(pagesRootInChroot, 0755) + cage.Bind(pagesRootInChroot, wd) + + // Update command to use chroot + cmd.SysProcAttr.Chroot = cage.Path() + cmd.Path = "/gitlab-pages" + cmd.Dir = pagesRootInChroot + + err = cage.Build() if err != nil { - return + return nil, err } - // Update command to use chroot - cmd.SysProcAttr.Chroot = wd - cmd.Path = temporaryExecutable.Name() - cmd.Dir = "/" - path = filepath.Join(wd, temporaryExecutable.Name()) - return + return cage, nil } func daemonize(config appConfig, uid, gid uint) { @@ -193,12 +173,12 @@ func daemonize(config appConfig, uid, gid uint) { defer killProcess(cmd) // Run daemon in chroot environment - temporaryExecutable, err := daemonChroot(cmd) + chroot, err := daemonChroot(cmd) if err != nil { - log.WithError(err).Error("chroot failed") + log.WithError(err).Print("chroot failed") return } - defer os.Remove(temporaryExecutable) + defer chroot.Dispose() // Create a pipe to pass the configuration configReader, configWriter, err := os.Pipe() @@ -222,15 +202,18 @@ func daemonize(config appConfig, uid, gid uint) { return } + //detach binded mountpoints + if err = chroot.LazyUnbind(); err != nil { + log.WithError(err).Print("chroot lazy umount failed") + return + } + // Write the configuration if err = json.NewEncoder(configWriter).Encode(config); err != nil { return } configWriter.Close() - // Remove executable - os.Remove(temporaryExecutable) - // Pass through signals passSignals(cmd) |