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:
authorKamil Trzcinski <ayufan@ayufan.eu>2016-02-16 17:25:59 +0300
committerKamil Trzcinski <ayufan@ayufan.eu>2016-02-16 17:25:59 +0300
commit7f12dcc6036f3935688e3fc4be61e8b1596cbc1d (patch)
tree7778d66b3adea6d781042f98d581b25f16879719
parentecfc0c55d22cc8d76c88dce750996256856827a8 (diff)
Execute in chroot
-rw-r--r--app.go1
-rw-r--r--daemon.go87
2 files changed, 88 insertions, 0 deletions
diff --git a/app.go b/app.go
index 4ab6a3e7..9157b8f2 100644
--- a/app.go
+++ b/app.go
@@ -26,6 +26,7 @@ func (a *theApp) domain(host string) *domain {
return domain
}
+
func (a *theApp) ServeTLS(ch *tls.ClientHelloInfo) (*tls.Certificate, error) {
if ch.ServerName == "" {
return nil, nil
diff --git a/daemon.go b/daemon.go
index f47b9703..2f8aee9d 100644
--- a/daemon.go
+++ b/daemon.go
@@ -1,16 +1,20 @@
package main
import (
+ "crypto/rand"
"encoding/json"
+ "fmt"
"log"
"os"
"os/exec"
"os/signal"
"os/user"
+ "path/filepath"
"strconv"
"syscall"
"github.com/kardianos/osext"
+ "io"
)
const daemonRunProgram = "gitlab-pages-unprivileged"
@@ -105,6 +109,79 @@ 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()
+
+ _, 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)
+ if err != nil {
+ return
+ }
+
+ path := fmt.Sprintf("%s.%x", name, b)
+ file, err = os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_EXCL, perm)
+ if err != nil {
+ return
+ }
+ return
+}
+
+func daemonChroot(cmd *exec.Cmd) (path string, err error) {
+ wd, err := os.Getwd()
+ if err != nil {
+ return
+ }
+
+ // 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
+ if err != nil {
+ os.Remove(temporaryExecutable.Name())
+ }
+ }()
+
+ // Open current executable
+ executableFile, err := os.Open(cmd.Path)
+ if err != nil {
+ return
+ }
+ defer executableFile.Close()
+
+ // Copy the executable content
+ _, err = io.Copy(temporaryExecutable, executableFile)
+ if err != nil {
+ return
+ }
+
+ // Update command to use chroot
+ cmd.SysProcAttr.Chroot = wd
+ cmd.Path = "/" + temporaryExecutable.Name()
+ cmd.Dir = "/"
+ path = filepath.Join(wd, temporaryExecutable.Name())
+ return
+}
+
func daemonize(config appConfig, cmdUser string) {
var err error
defer func() {
@@ -120,6 +197,13 @@ func daemonize(config appConfig, cmdUser string) {
}
defer killProcess(cmd)
+ // Run daemon in chroot environment
+ temporaryExecutable, err := daemonChroot(cmd)
+ if err != nil {
+ return
+ }
+ defer os.Remove(temporaryExecutable)
+
// Create a pipe to pass the configuration
configReader, configWriter, err := os.Pipe()
if err != nil {
@@ -144,6 +228,9 @@ func daemonize(config appConfig, cmdUser string) {
}
configWriter.Close()
+ // Remove executable
+ os.Remove(temporaryExecutable)
+
// Pass through signals
passSignals(cmd)