ホームページ  >  記事  >  バックエンド開発  >  Go でマウント名前空間に入るときの「EINVAL」エラーを解決するにはどうすればよいですか?

Go でマウント名前空間に入るときの「EINVAL」エラーを解決するにはどうすればよいですか?

Susan Sarandon
Susan Sarandonオリジナル
2024-11-02 08:54:02587ブラウズ

How to resolve the

Go でマウント名前空間に入る

問題:

Go で setns 呼び出しが EINVAL (無効な引数) を返すコンテナのマウント名前空間に入ろうとするとき。

説明:

setns を使用して名前空間に入るには、その前にシングルスレッド コンテキストから呼び出しを行う必要があります。 Go ランタイム スレッドが開始されます。

解決策:

この問題を解決するには 2 つのアプローチがあります。

1.コンストラクター トリックの使用:

  • Go の開始前に setns を呼び出す C 関数に __attribute__((constructor)) マクロを追加します。
  • 修正された 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/sys/kernel/namespaces_allowed をチェックして、カーネルが複数の名前空間をサポートしていることを確認してください。
  • ドキュメントで引用されているカーネル パッチでは、プロセスのターゲット マウント名前空間に CAP_SYS_ADMIN が必要であると指定されています。 setns を呼び出す前に、これらの条件が満たされていることを確認してください。

以上がGo でマウント名前空間に入るときの「EINVAL」エラーを解決するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。