forked from TrueCloudLab/restic
11fbaaae9a
The restic security model includes full trust of the local machine, so this should not fix any actual security problems, but it's better to be safe than sorry. Fixes #2192.
76 lines
1.4 KiB
Go
76 lines
1.4 KiB
Go
// +build !solaris
|
|
// +build !windows
|
|
|
|
package backend
|
|
|
|
import (
|
|
"os"
|
|
"os/exec"
|
|
"os/signal"
|
|
"syscall"
|
|
"unsafe"
|
|
|
|
"github.com/restic/restic/internal/debug"
|
|
"github.com/restic/restic/internal/errors"
|
|
)
|
|
|
|
func tcsetpgrp(fd int, pid int) error {
|
|
_, _, errno := syscall.RawSyscall(syscall.SYS_IOCTL, uintptr(fd),
|
|
uintptr(syscall.TIOCSPGRP), uintptr(unsafe.Pointer(&pid)))
|
|
if errno == 0 {
|
|
return nil
|
|
}
|
|
|
|
return errno
|
|
}
|
|
|
|
func startForeground(cmd *exec.Cmd) (bg func() error, err error) {
|
|
// open the TTY, we need the file descriptor
|
|
tty, err := os.OpenFile("/dev/tty", os.O_RDWR, 0)
|
|
if err != nil {
|
|
debug.Log("unable to open tty: %v", err)
|
|
bg = func() error {
|
|
return nil
|
|
}
|
|
return bg, cmd.Start()
|
|
}
|
|
|
|
signal.Ignore(syscall.SIGTTIN)
|
|
signal.Ignore(syscall.SIGTTOU)
|
|
|
|
// run the command in its own process group
|
|
cmd.SysProcAttr = &syscall.SysProcAttr{
|
|
Setpgid: true,
|
|
}
|
|
|
|
// start the process
|
|
err = cmd.Start()
|
|
if err != nil {
|
|
_ = tty.Close()
|
|
return nil, errors.Wrap(err, "cmd.Start")
|
|
}
|
|
|
|
// move the command's process group into the foreground
|
|
prev := syscall.Getpgrp()
|
|
err = tcsetpgrp(int(tty.Fd()), cmd.Process.Pid)
|
|
if err != nil {
|
|
_ = tty.Close()
|
|
return nil, err
|
|
}
|
|
|
|
bg = func() error {
|
|
signal.Reset(syscall.SIGTTIN)
|
|
signal.Reset(syscall.SIGTTOU)
|
|
|
|
// reset the foreground process group
|
|
err = tcsetpgrp(int(tty.Fd()), prev)
|
|
if err != nil {
|
|
_ = tty.Close()
|
|
return err
|
|
}
|
|
|
|
return tty.Close()
|
|
}
|
|
|
|
return bg, nil
|
|
}
|