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 Trzciński <ayufan@ayufan.eu>2020-09-01 13:18:10 +0300
committerKamil Trzciński <ayufan@ayufan.eu>2020-09-02 13:39:52 +0300
commit4e64869e248537b2bb8719c47620597595a46ea4 (patch)
treedec77058f4f41619ac53ecde0ff326ff472d0e94 /daemon.go
parent92dae330532ca47abab1b31b65a0778eeff2b53f (diff)
Unshare mount namespace to fix `getcwd`
Previously we would call `LazyUnbind` as soon as proces starts. This does break `getcwd` as it starts returning `(unreachable)` due to mountpoint being gone from `chroot`. This removes the need for `LazyUnbind` and instead `unshare` mount namespace, making the new process to have it's own mounts that are not shared with parent process. The mounts gets cleaned-up once the process exists.
Diffstat (limited to 'daemon.go')
-rw-r--r--daemon.go37
1 files changed, 22 insertions, 15 deletions
diff --git a/daemon.go b/daemon.go
index 25ed85c1..5091069b 100644
--- a/daemon.go
+++ b/daemon.go
@@ -8,6 +8,7 @@ import (
"os"
"os/exec"
"os/signal"
+ "strings"
"syscall"
"github.com/kardianos/osext"
@@ -27,9 +28,19 @@ func daemonMain() {
return
}
+ // Validate that a working directory is valid
+ // https://man7.org/linux/man-pages/man2/getcwd.2.html
+ wd, err := os.Getwd()
+ if err != nil {
+ fatal(err, "could not get current working directory")
+ } else if strings.HasPrefix(wd, "(unreachable)") {
+ fatal(os.ErrPermission, "could not get current working directory")
+ }
+
log.WithFields(log.Fields{
"uid": syscall.Getuid(),
"gid": syscall.Getgid(),
+ "wd": wd,
}).Info("starting the daemon as unprivileged user")
// read the configuration from the pipe "ExtraFiles"
@@ -132,10 +143,6 @@ func chrootDaemon(cmd *exec.Cmd) (*jail.Jail, error) {
cmd.Path = tempExecutablePath
cmd.Dir = "/"
- if err := chroot.Build(); err != nil {
- return nil, err
- }
-
return chroot, nil
}
@@ -249,11 +256,6 @@ func jailDaemon(cmd *exec.Cmd) (*jail.Jail, error) {
cmd.Path = "/gitlab-pages"
cmd.Dir = pagesRootInChroot
- err = cage.Build()
- if err != nil {
- return nil, err
- }
-
return cage, nil
}
@@ -283,6 +285,17 @@ func daemonize(config appConfig, uid, gid uint, inPlace bool) error {
}
defer wrapper.Dispose()
+ // Unshare mount namespace
+ // 1. If this fails, in a worst case changes to mounts will propagate to other processes
+ // 2. Needed for fixing `os.Getwd()` which does return `(unreachable)`:
+ // 3. https://man7.org/linux/man-pages/man2/getcwd.2.html.
+ _ = wrapper.Unshare()
+
+ if err := wrapper.Build(); err != nil {
+ log.WithError(err).Print("chroot build failed")
+ return err
+ }
+
// Create a pipe to pass the configuration
configReader, configWriter, err := os.Pipe()
if err != nil {
@@ -299,12 +312,6 @@ func daemonize(config appConfig, uid, gid uint, inPlace bool) error {
return err
}
- // Proactively detach any bind-mounts so they can't be left dangling
- if err := wrapper.LazyUnbind(); err != nil {
- log.WithError(err).Print("jail lazy umount failed")
- return err
- }
-
// Write the configuration
if err := json.NewEncoder(configWriter).Encode(config); err != nil {
return err