Permission denied while reading /proc/pid/smaps file (golang)

Issue

Using the os/exec package, I want to run an external command on a *nix OS with another user instead of root. (The main process runs under root user).

The external command runs by go app. But my app can not read /proc/pid/smaps file, following error:

panic: open /proc/2962/smaps: permission denied

goroutine 6 [running]:
main.memwatch(0xc000094000, 0xc00007a0c0)
        /src/main.go:41 +0x298
created by main.main
        /src/main.go:25 +0x18f
exit status 2

Here is my code:

// main.go
package main

import (
    "fmt"
    "os"
    "os/exec"
    "syscall"
    "time"
)

func main() {
    cmd := exec.Command("sleep", "3")

    cmd.SysProcAttr = &syscall.SysProcAttr{
        Setpgid:    true,
        Credential: &syscall.Credential{Uid: 65534, Gid: 65534}, // External command expect run with `nobody` instead of `root` for security reason
    }

    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr

    err := cmd.Start()
    done := make(chan struct{})

    go memwatch(cmd, done)

    if err != nil {
        panic(err)
    }

    cmd.Wait()

    close(done)
}

func memwatch(cmd *exec.Cmd, done <-chan struct{}) {
    // Reuse the reader so we don't have to close and reopen it all the time
    smaps, err := os.Open(fmt.Sprintf("/proc/%d/smaps", cmd.Process.Pid))
    if err != nil {
        panic(err)
    }
    defer smaps.Close()

    for {
        select {
        case <-done:
            return
        default:
            fmt.Println("running")
            time.Sleep(10 * time.Millisecond)
        }
    }
}

I’m tired. Anyone here for help, please.

Solution

I test my code inside a docker container that doesn’t have SYS_PTRACE capability. That’s why the error shows. The error was gone when I added the SYS_PTRACE capability for that container.

Answered By – Kim Nguyen

Answer Checked By – Dawn Plyler (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.