From 4a496073b0bec3f07330fd1a0c1697d845b53016 Mon Sep 17 00:00:00 2001 From: Alfonso Acosta Date: Wed, 30 Mar 2016 23:57:31 +0000 Subject: [PATCH] More robust obtention of host shell command --- probe/host/controls.go | 2 +- probe/host/controls_darwin.go | 4 +++- probe/host/controls_linux.go | 26 ++++++++++++++++++-------- probe/host/reporter.go | 18 ++++++++++-------- 4 files changed, 32 insertions(+), 18 deletions(-) diff --git a/probe/host/controls.go b/probe/host/controls.go index 0ecad9f59..3f666c66c 100644 --- a/probe/host/controls.go +++ b/probe/host/controls.go @@ -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 { diff --git a/probe/host/controls_darwin.go b/probe/host/controls_darwin.go index 418293025..cae9c363e 100644 --- a/probe/host/controls_darwin.go +++ b/probe/host/controls_darwin.go @@ -1,3 +1,5 @@ package host -var hostShellCmd = []string{"/bin/bash"} +func getHostShellCmd() []string { + return []string{"/bin/bash"} +} diff --git a/probe/host/controls_linux.go b/probe/host/controls_linux.go index 2a4ef4459..f4870c33d 100644 --- a/probe/host/controls_linux.go +++ b/probe/host/controls_linux.go @@ -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 } diff --git a/probe/host/reporter.go b/probe/host/reporter.go index 23b7c48e4..04019d376 100644 --- a/probe/host/reporter.go +++ b/probe/host/reporter.go @@ -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