Bagaimana untuk menyelesaikan ralat \'EINVAL\' apabila memasuki ruang nama pelekap dalam Go?

Susan Sarandon
Lepaskan: 2024-11-02 08:54:02
asal
602 orang telah melayarinya

How to resolve the

Memasuki Ruang Nama Gunung dalam Go

Isu:

Dalam Go, panggilan setns mengembalikan EINVAL (argumen tidak sah) apabila cuba memasuki ruang nama pelekap untuk bekas.

Penjelasan:

Untuk memasukkan ruang nama menggunakan setns, panggilan mesti dibuat daripada konteks satu utas sebelum urutan masa jalan Go bermula.

Penyelesaian:

Terdapat dua pendekatan untuk 解决isu ini:

1. Menggunakan Trik Pembina:

  • Tambahkan makro __attribute__((pembina)) pada fungsi C yang memanggil setns sebelum Go bermula.
  • Kod Go yang diubah suai:
<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>
Salin selepas log masuk

2. Menggunakan syscall.RawSyscall:

  • Pastikan panggilan setns dibuat dalam utas utama sebelum memulakan urutan masa jalan Go.
  • Gunakan runtime.LockOSThread untuk mengunci utas utama jika perlu.
<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>
Salin selepas log masuk

Nota:

  • Pastikan kernel anda menyokong berbilang ruang nama dengan menyemak /proc/sys/kernel/namespaces_allowed.
  • Tampalan kernel yang dipetik dalam dokumentasi menyatakan bahawa proses mesti mempunyai CAP_SYS_ADMIN dalam ruang nama pelekap sasaran. Pastikan syarat ini dipenuhi sebelum cuba memanggil setns.

Atas ialah kandungan terperinci Bagaimana untuk menyelesaikan ralat \'EINVAL\' apabila memasuki ruang nama pelekap dalam Go?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:php.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Artikel terbaru oleh pengarang
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!