Maison > développement back-end > Golang > le corps du texte

Comment résoudre l'erreur \'EINVAL\' lors de la saisie de l'espace de noms de montage dans Go ?

Susan Sarandon
Libérer: 2024-11-02 08:54:02
original
602 Les gens l'ont consulté

How to resolve the

Entrée dans l'espace de noms Mount dans Go

Problème :

Dans Go, l'appel setns renvoie EINVAL (argument invalide) lorsque vous tentez d'entrer l'espace de noms de montage pour un conteneur.

Explication :

Pour entrer un espace de noms à l'aide de setns, l'appel doit être effectué à partir d'un contexte à thread unique avant les threads d'exécution Go démarrent.

Solution :

Il existe deux approches pour résoudre ce problème :

1. Utilisation de l'astuce du constructeur :

  • Ajoutez la macro __attribute__((constructor)) à une fonction C qui appelle setns avant le démarrage de Go.
  • Code Go modifié :
<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>
Copier après la connexion

2. Utilisation de syscall.RawSyscall :

  • Assurez-vous que l'appel setns est effectué dans le thread principal avant de démarrer les threads d'exécution Go.
  • Utilisez runtime.LockOSThread pour verrouiller le thread principal si nécessaire.
<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>
Copier après la connexion

Remarque :

  • Assurez-vous que votre noyau prend en charge plusieurs espaces de noms en vérifiant /proc/sys/kernel/namespaces_allowed.
  • Le correctif du noyau cité dans la documentation précise que le processus doit avoir CAP_SYS_ADMIN dans l'espace de noms de montage cible. Assurez-vous que ces conditions sont remplies avant de tenter d'appeler setns.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!