More robust obtention of host shell command

This commit is contained in:
Alfonso Acosta
2016-03-30 23:57:31 +00:00
parent 59af5d28ad
commit 4a496073b0
4 changed files with 32 additions and 18 deletions

View File

@@ -24,7 +24,7 @@ func (*Reporter) deregisterControls() {
}
func (r *Reporter) execHost(req xfer.Request) xfer.Response {
cmd := exec.Command(hostShellCmd[0], hostShellCmd[1:]...)
cmd := exec.Command(r.hostShellCmd[0], r.hostShellCmd[1:]...)
cmd.Env = []string{"TERM=xterm"}
ptyPipe, err := pty.Start(cmd)
if err != nil {

View File

@@ -1,3 +1,5 @@
package host
var hostShellCmd = []string{"/bin/bash"}
func getHostShellCmd() []string {
return []string{"/bin/bash"}
}

View File

@@ -3,14 +3,14 @@ package host
import (
"bytes"
"os/exec"
"strings"
"syscall"
log "github.com/Sirupsen/logrus"
"github.com/willdonnelly/passwd"
)
var hostShellCmd []string
func init() {
func getHostShellCmd() []string {
if isProbeContainerized() {
// Escape the container namespaces and jump into the ones from
// the host's init process.
@@ -19,17 +19,16 @@ func init() {
// but it doesn't hurt.
readPasswdCmd := []string{"/usr/bin/nsenter", "-t1", "-m", "--no-fork", "cat", "/etc/passwd"}
uid, gid, shell := getRootUserDetails(readPasswdCmd)
hostShellCmd = []string{
return []string{
"/usr/bin/nsenter", "-t1", "-m", "-i", "-n", "-p", "--no-fork",
"--setuid", uid,
"--setgid", gid,
shell,
}
return
}
_, _, shell := getRootUserDetails([]string{"cat", "/etc/passwd"})
hostShellCmd = []string{shell}
return []string{shell}
}
func getRootUserDetails(readPasswdCmd []string) (uid, gid, shell string) {
@@ -41,16 +40,23 @@ func getRootUserDetails(readPasswdCmd []string) (uid, gid, shell string) {
cmdBuffer := &bytes.Buffer{}
cmd.Stdout = cmdBuffer
if err := cmd.Run(); err != nil {
log.Warnf(
"getRootUserDetails(): error running read passwd command %q: %s",
strings.Join(readPasswdCmd, " "),
err,
)
return
}
entries, err := passwd.ParseReader(cmdBuffer)
if err != nil {
log.Warnf("getRootUserDetails(): error parsing passwd: %s", err)
return
}
entry, ok := entries["root"]
if !ok {
log.Warnf("getRootUserDetails(): no root entry in passwd")
return
}
@@ -65,12 +71,16 @@ func isProbeContainerized() bool {
// wouldn't have a way to escape the container anyhow).
var statT syscall.Stat_t
if err := syscall.Stat("/proc/self/ns/mnt", &statT); err != nil {
path := "/proc/self/ns/mnt"
if err := syscall.Stat(path, &statT); err != nil {
log.Warnf("isProbeContainerized(): stat() error on %q: %s", path, err)
return false
}
selfMountNamespaceID := statT.Ino
if err := syscall.Stat("/proc/1/ns/mnt", &statT); err != nil {
path = "/proc/1/ns/mnt"
if err := syscall.Stat(path, &statT); err != nil {
log.Warnf("isProbeContainerized(): stat() error on %q: %s", path, err)
return false
}

View File

@@ -35,20 +35,22 @@ const (
// Reporter generates Reports containing the host topology.
type Reporter struct {
hostID string
hostName string
probeID string
pipes controls.PipeClient
hostID string
hostName string
probeID string
pipes controls.PipeClient
hostShellCmd []string
}
// NewReporter returns a Reporter which produces a report containing host
// topology for this host.
func NewReporter(hostID, hostName, probeID string, pipes controls.PipeClient) *Reporter {
r := &Reporter{
hostID: hostID,
hostName: hostName,
probeID: probeID,
pipes: pipes,
hostID: hostID,
hostName: hostName,
probeID: probeID,
pipes: pipes,
hostShellCmd: getHostShellCmd(),
}
r.registerControls()
return r