在go中更改linux名称空间

I want to change namespace in go. When I'm compiling and running code in C it works fine, but in go I got errno 22 on netns syscall. Any Idea why this could occur?

go)

$ go build main.go ; ./main
setns mnt: Invalid argument
panic: -1

goroutine 1 [running]:
runtime.panic(0x423b80, 0xffffffffffffffff)
    /usr/local/go/src/pkg/runtime/panic.c:266 +0xb6
main.main()
    main.go:81 +0x86
$

c)

$ grep ^// main.go | sed 's/\/\///' | sed 's/__main/main/' > main.c; gcc main.c -o main; ./main
$

The code below:

package main

//
// #define _GNU_SOURCE
// #include <fcntl.h>
// #include <sched.h>
// #include <sys/syscall.h>
// #include <sys/param.h>
// #include <sys/mount.h>
// #include <stdio.h>
// #include <unistd.h>
//
// #define NETNS_RUN_DIR "/run/netns"
// #define MNTNS_RUN_DIR "/run/mntns"
//
// #ifndef HAVE_SETNS
//
// int
// setns(int fd, int nstype) {
// #ifdef __NR_setns
//   return syscall(__NR_setns, fd, nstype);
// #else
//   errno = ENOSYS;
//   return -1;
// #endif
// }
//
// #endif /* HAVE_SETNS */
//
//
// int
// ChangeNamespace(char *name)
// {
//   char net_path[MAXPATHLEN];
//   char mnt_path[MAXPATHLEN];
//   int fd;
//
//   snprintf(net_path, sizeof(net_path), "%s/%s", NETNS_RUN_DIR, name);
//   snprintf(mnt_path, sizeof(mnt_path), "%s/%s", MNTNS_RUN_DIR, name);
//
//   fd = open(net_path, O_RDONLY);
//   if (fd < 0) {
//     perror("open net");
//     return -1;
//   }
//
//   if (setns(fd, 0) < 0) {
//     perror("setns net");
//     return -1;
//   }
//
//   fd = open(mnt_path, O_RDONLY);
//   if (fd < 0) {
//     perror("open mnt");
//     return -1;
//   }
//
//   if (setns(fd, 0) < 0) {
//     perror("setns mnt");
//     return -1;
//   }
//
//   return 0;
// }
//
// int
// __main(int argc, char *argv[]) {
//     ChangeNamespace("ns");
//     return 0;
// }
//
import "C"
import "unsafe"
func main() {
    name := C.CString("ns")
    defer C.free(unsafe.Pointer(name))
    i := int(C.ChangeNamespace(name))
    if i < 0 {
        panic(i)
    }
}
duanren9163
duanren9163 请访问stackoverflow.com/questions/25704661/…,了解我从Go项目获得的答案。
大约 6 年之前 回复
douju1928
douju1928 相同。
大约 6 年之前 回复
duanbanfei2875
duanbanfei2875 如果将name:=C.CString(“ns”)移到main()之外会怎样?
大约 6 年之前 回复
duankousong9637
duankousong9637 完成。现在perror有错误信息
大约 6 年之前 回复
dongxian8858
dongxian8858 您可能想查看docker如何在libcontainer/namespaces中处理此问题。关于为即将到来的go.sys程序包添加更多支持,至少还有一个未解决的问题:#8447
大约 6 年之前 回复
douyue4334
douyue4334 您还需要调用runtime.LockOSThread以确保正在从预期线程中调用setns。
大约 6 年之前 回复
douxiajia6720
douxiajia6720 您能否更改perror()行以使字符串说明哪个调用失败?仅“无效的论点”不足以解释发生了什么。(我感觉这是一个移动堆栈问题...)
大约 6 年之前 回复

1个回答



您可以使用类似这样的方法一起跳过cgo,我现在无法对其进行测试:</ p>
\ n

  const(
netNS =“ / run / netns /”
mntNS =“ / run / mntns /”

func ChangeNamespace(名称字符串)错误{
fd,err:= syscall.Open(netNS + name,syscall.O_RDONLY,0666)
if err!= nil {
return err
}
推迟syscall.Close(fd)
如果_,_,err:= syscall。 RawSyscall(syscall.SYS_SETNS,uintptr(fd),0,0); err!= nil {
return err
}

fd1,err:= syscall.Open(mntNS + name,syscall.O_RDONLY,0666)
if err!= nil {
return err
}

延迟syscall.Close(fd1)
如果_,_,err:= syscall.RawSyscall(syscall.SYS_SETNS,uintptr(fd1),0,0); err!= nil {
return err
}
return nil
}
</ code> </ pre>
</ div>

展开原文

原文

You could use something like this skipping the cgo all together, I can't test it right now:

const (
    netNS = "/run/netns/"
    mntNS = "/run/mntns/"
)
func ChangeNamespace(name string) error {
    fd, err := syscall.Open(netNS+name, syscall.O_RDONLY, 0666)
    if err != nil {
        return err
    }
    defer syscall.Close(fd)
    if _, _, err := syscall.RawSyscall(syscall.SYS_SETNS, uintptr(fd), 0, 0); err != nil {
        return err
    }

    fd1, err := syscall.Open(mntNS+name, syscall.O_RDONLY, 0666)
    if err != nil {
        return err
    }
    defer syscall.Close(fd1)
    if _, _, err := syscall.RawSyscall(syscall.SYS_SETNS, uintptr(fd1), 0, 0); err != nil {
        return err
    }
    return nil
}

dounao1875
dounao1875 那是一个不同的错误,请报告它,并在原始帖子中添加指向错误报告的链接。
大约 6 年之前 回复
doucai9270
doucai9270 我尝试了gccgo,结果相同...
大约 6 年之前 回复
douyi8315
douyi8315 最后一个想法是尝试使用gccgo,但是无论相同的代码在其他所有方面是否都能工作,都应报告一个错误并链接到此问题。 code.google.com/p/go/issues/entry
大约 6 年之前 回复
dongliang1873
dongliang1873 正如您在go)和c)部分的第一篇文章中所见,我都以root身份运行了这两个代码。 另外,我已经将此代码重写为asm,perl,python,并且所有这些都可以正常工作。 所以对我来说,看起来go必须编译不同。 我在gcc中看不到任何可疑的选项(转到build -n)。 也许6c或6g对该系统调用有影响,但是我对那些工具不熟悉。
大约 6 年之前 回复
dongya4089
dongya4089 您是否有机会以root用户身份运行C代码? 因为我看不到一个系统调用如何正常工作而另一个失败。
大约 6 年之前 回复
drexlz0623
drexlz0623 相同的错误:setns mnt上出现“无效参数”
大约 6 年之前 回复
duanbigan7765
duanbigan7765 错误怎么说?
大约 6 年之前 回复
douci1196
douci1196 我昨天在测试时一定很累,但这不能解决问题。 还是一样的错误。
大约 6 年之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐