Skip to content

Commit

Permalink
Merge pull request #204 from gustavosbarreto/reexec
Browse files Browse the repository at this point in the history
Reexec updatehub binary to enter in a new mount NS for isolating changes to the mount table
  • Loading branch information
otavio committed Jun 1, 2018
2 parents 73d5ab2 + a7bbde3 commit 3a66c1c
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 45 deletions.
48 changes: 36 additions & 12 deletions cmd/updatehub/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"encoding/pem"
"net/http"
"os"
"os/exec"
"path"
"path/filepath"
"syscall"
Expand Down Expand Up @@ -43,6 +44,37 @@ var (
)

func main() {
if !isReexeced() {
/* Reexec updatehub binary to enter in a new mount NS
for isolating changes to the mount table */
if err := syscall.Unshare(syscall.CLONE_NEWNS); err != nil {
log.Fatalf("failed to enter private mount NS: %s", err)
os.Exit(1)
}

cmd := exec.Command("/proc/self/exe", os.Args...)
cmd.SysProcAttr = &syscall.SysProcAttr{
Setpgid: true,
Pdeathsig: syscall.SIGTERM,
Cloneflags: syscall.CLONE_NEWNS,
}
cmd.Env = append(os.Environ(), []string{"UPDATEHUB_REEXEC=true"}...)
cmd.Stdin = os.Stdin
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout

if err := cmd.Run(); err != nil {
if exitError, ok := err.(*exec.ExitError); ok {
ws := exitError.Sys().(syscall.WaitStatus)
os.Exit(ws.ExitStatus())
}

os.Exit(1)
}

os.Exit(0)
}

log.SetLevel(logrus.InfoLevel)

cmd := &cobra.Command{
Expand Down Expand Up @@ -78,18 +110,6 @@ func main() {
log.SetLevel(logrus.DebugLevel)
}

// enter in a new mount NS for isolating changes to the mount table
if err := syscall.Unshare(syscall.CLONE_NEWNS); err != nil {
log.Fatalf("failed to enter private mount NS: %s", err)
os.Exit(1)
}

err = syscall.Mount("", "/", "updatehub", syscall.MS_REC|syscall.MS_SLAVE, "")
if err != nil {
log.Fatalf("failed to mark rootfs as rslave: %s", err)
os.Exit(1)
}

osFs := afero.NewOsFs()
settings := &updatehub.Settings{}

Expand Down Expand Up @@ -201,3 +221,7 @@ func readPublicKey(fs afero.Fs, settings *updatehub.Settings) (*rsa.PublicKey, e

return key.(*rsa.PublicKey), nil
}

func isReexeced() bool {
return os.Getenv("UPDATEHUB_REEXEC") == "true"
}
38 changes: 5 additions & 33 deletions utils/filesystem.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,11 @@

package utils

/*
#include <stdlib.h>
#include <sys/mount.h>
#include <errno.h>
#include <string.h>
static int errno_wrapper() {
return errno;
}
*/
import "C"
import (
"fmt"
"os/exec"
"strings"
"unsafe"
"syscall"

"github.com/spf13/afero"
)
Expand Down Expand Up @@ -89,33 +78,16 @@ func (fs *FileSystem) Format(targetDevice string, fsType string, formatOptions s
}

func (fs *FileSystem) Mount(targetDevice string, mountPath string, fsType string, mountOptions string) error {
cTargetDevice := C.CString(targetDevice)
defer C.free(unsafe.Pointer(cTargetDevice))

cMountPath := C.CString(mountPath)
defer C.free(unsafe.Pointer(cMountPath))

cFSType := C.CString(fsType)
defer C.free(unsafe.Pointer(cFSType))

cMountOptions := C.CString(mountOptions)
defer C.free(unsafe.Pointer(cMountOptions))

r := C.mount(cTargetDevice, cMountPath, cFSType, 0, unsafe.Pointer(cMountOptions))
if r == -1 {
return fmt.Errorf("Couldn't mount '%s': %s", targetDevice, C.GoString(C.strerror(C.errno_wrapper())))
if err := syscall.Mount(targetDevice, mountPath, fsType, 0, mountOptions); err != nil {
return fmt.Errorf("Couldn't mount '%s': %s", targetDevice, err)
}

return nil
}

func (fs *FileSystem) Umount(mountPath string) error {
cMountPath := C.CString(mountPath)
defer C.free(unsafe.Pointer(cMountPath))

r := C.umount(cMountPath)
if r == -1 {
return fmt.Errorf("Couldn't umount '%s': %s", mountPath, C.GoString(C.strerror(C.errno_wrapper())))
if err := syscall.Unmount(mountPath, 0); err != nil {
return fmt.Errorf("Couldn't umount '%s': %s", mountPath, err)
}

return nil
Expand Down

0 comments on commit 3a66c1c

Please sign in to comment.