首頁 >後端開發 >Golang >如何解決Go中輸入掛載命名空間時出現「EINVAL」錯誤?

如何解決Go中輸入掛載命名空間時出現「EINVAL」錯誤?

Susan Sarandon
Susan Sarandon原創
2024-11-02 08:54:02680瀏覽

How to resolve the

在Go 中輸入Mount 命名空間

問題:

在Go 中,setns 呼叫回EINVAL(無效參數)嘗試進入容器的掛載命名空間時。

說明:

要使用 setns 進入命名空間,必須先從單執行緒上下文進行呼叫Go 執行緒執行緒啟動。

解:

有兩種方法可以解決此問題:

1.使用建構子技巧:

  • 將__attribute__((constructor)) 巨集加入到在Go 啟動之前呼叫setns 的C 函數。
  • 修改的 Go 程式碼:
<code class="go">/*
#include <sched.h>
#include <stdio.h>
#include <fcntl.h>

__attribute__((constructor)) void enter_namespace(void) {
   setns(open("/proc/<PID>/ns/mnt", O_RDONLY, 0644), 0);
}
*/
import "C"</code>

2。使用syscall.RawSyscall:

  • 確保在啟動Go運行時執行緒之前在主執行緒中進行setns呼叫。
  • 使用runtime.LockOSThread鎖定主執行緒
<code class="go">package main

import (
    "fmt"
    "os"
    "path/filepath"
    "syscall"
    "runtime"
)

func main() {
    if syscall.Geteuid() != 0 {
        fmt.Println("abort: you want to run this as root")
        os.Exit(1)
    }

    if len(os.Args) != 2 {
        fmt.Println("abort: you must provide a PID as the sole argument")
        os.Exit(2)
    }

    // Lock the main thread to the OS thread
    runtime.LockOSThread()

    namespaces := []string{"ipc", "uts", "net", "pid", "mnt"}

    for i := range namespaces {
        fd, _ := syscall.Open(filepath.Join("/proc", os.Args[1], "ns", namespaces[i]), syscall.O_RDONLY, 0644)
        err, _, msg := syscall.RawSyscall(308, uintptr(fd), 0, 0) // 308 == setns

        if err != 0 {
            fmt.Println("setns on", namespaces[i], "namespace failed:", msg)
        } else {
            fmt.Println("setns on", namespaces[i], "namespace succeeded")
        }

    }
}</code>

注意:

  • 透過檢查/proc/nel/ker /namespaces_allowed 確保您的核心支援多個命名空間。
  • 文件中所引用的核心修補程式指定行程在目標掛載命名空間中必須具有 CAP_SYS_ADMIN。在嘗試呼叫 setns 之前,請確保滿足這些條件。

以上是如何解決Go中輸入掛載命名空間時出現「EINVAL」錯誤?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn