在读取/proc/pid/smaps文件时出现权限被拒绝的错误(使用golang)。

huangapple go评论109阅读模式
英文:

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

问题

使用os/exec包,我想在*nix操作系统上以另一个用户而不是root用户身份运行外部命令(主进程在root用户下运行)。

外部命令由go应用程序运行。但是我的应用程序无法读取/proc/pid/smaps文件,出现以下错误:

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

以下是我的代码:

// 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}, // 由于安全原因,外部命令期望以`nobody`而不是`root`用户身份运行
	}

	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{}) {
	// 重用读取器,这样我们就不必一直关闭和重新打开它
	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)
		}
	}
}

我很累了。有人可以帮忙吗?谢谢。

英文:

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 (
	&quot;fmt&quot;
	&quot;os&quot;
	&quot;os/exec&quot;
	&quot;syscall&quot;
	&quot;time&quot;
)

func main() {
	cmd := exec.Command(&quot;sleep&quot;, &quot;3&quot;)

	cmd.SysProcAttr = &amp;syscall.SysProcAttr{
		Setpgid:    true,
		Credential: &amp;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 &lt;-chan struct{}) {
	// Reuse the reader so we don&#39;t have to close and reopen it all the time
	smaps, err := os.Open(fmt.Sprintf(&quot;/proc/%d/smaps&quot;, cmd.Process.Pid))
	if err != nil {
		panic(err)
	}
	defer smaps.Close()

	for {
		select {
		case &lt;-done:
			return
		default:
			fmt.Println(&quot;running&quot;)
			time.Sleep(10 * time.Millisecond)
		}
	}
}

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

答案1

得分: 1

我在一个没有SYS_PTRACE能力的Docker容器中测试我的代码。这就是为什么会出现错误。当我为该容器添加了SYS_PTRACE能力后,错误就消失了。

英文:

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.

huangapple
  • 本文由 发表于 2022年3月4日 17:10:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/71349024.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定