V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
jeesk
V2EX  ›  Go 编程语言

go 程序进程权限的问题

  •  
  •   jeesk · 2022-06-20 17:14:01 +08:00 · 2241 次点击
    这是一个创建于 648 天前的主题,其中的信息可能已经有所发展或是发生改变。

    因为我的软件需要创建虚拟网卡, 软件就需要 root 权限运行。 有个需求可以读取 macosx 的剪贴板, 这个时候坑就来了, 发现 macosx 的剪贴板做了用户隔离的,root 用户读取不到普通用户的剪贴板。 这就形成了一个死局。哈哈, 这个坑是苹果出来的。

      1. 我想知道能不能够实现一个 go 程序,能够隔离出运行的权限。 把某一段代码的权限降级成 user 用户, 而创建网卡的程序为 root 用户?
      2. 有 Macosx 在 root 用户无法获取剪贴板, 大家有什么好的方案吗? 
      
      
      
      刚才我已经给 https://github.com/ChrisJohnsen/tmux-MacOSX-pasteboard 仓库的 2 位开发者发邮件了,不知道能不能获得他们的帮助。 哎,哎,哎。
    

    MacOSX- pasteboard readme 文件。

      
    The pasteboard service in Mac OS X is registered in a "bootstrap
    namespace" (see Apple’s [TN2083][9]). The namespaces exist in
    a hierarchy: “higher” namespaces include access to “lower”
    namespaces. A process in a lower namespace can not access higher
    namespaces. So, all process can access the lowest, “root” bootstrap
    namespace, but only processes in a higher namespace can access that
    namespace. Processes created as a part of a Mac OS X login session
    are automatically included in the user’s “per-user” bootstrap
    namespace. The pasteboard service is only available to processes in
    the per-user bootstrap namespace.
    
    21 条回复    2022-06-23 14:55:31 +08:00
    Buges
        1
    Buges  
       2022-06-20 17:27:08 +08:00 via Android
    那就分开多个进程呗,这种事情在 Windows 上也很常见,很多程序都用一个带 UAC 盾牌的 xxxHelper.exe 处理特权操作,主程序无需 UAC 。Linux 也可以用一些 cap /euid 等机制提权,也可以在特权操作完成后调用 setuid 主动降权。
    learningman
        2
    learningman  
       2022-06-20 17:29:51 +08:00
    一般来说都是起一个有 root 权限的 daemon ,主进程在普通用户下面跑
    jeesk
        3
    jeesk  
    OP
       2022-06-20 17:40:19 +08:00
    @Buges
    @learningman 两位大佬, 没太懂具体怎么操作, 有没有这方便的资料, 因为我也是临时安排处理问题, 以前没这方面经验的。
    flynaj
        4
    flynaj  
       2022-06-20 19:12:28 +08:00
    @jeesk #3 就是需要 root 权限的那部分离出来单独做一个程序,然后主程序调用。
    helone
        5
    helone  
       2022-06-20 19:19:56 +08:00
    nuk
        6
    nuk  
       2022-06-20 19:30:50 +08:00
    创建网卡用另外一个程序吧,感觉主要问题不是 root 获取不到剪贴板,而是为什么你的程序要用 root 运行。
    jeesk
        7
    jeesk  
    OP
       2022-06-20 19:34:11 +08:00
    @nuk 因为创建网卡需要 root
    jeesk
        8
    jeesk  
    OP
       2022-06-20 19:36:21 +08:00
    @helone 创建网卡我用的是 golang 呀, 不是普通命令
    nuk
        9
    nuk  
       2022-06-20 19:46:48 +08:00
    @jeesk 所以把这部分拆开就好了噻,主程序就不用 root 权限了。像很多 vpn 程序,也就安装网卡的时候请求 root ,有网卡就不会要求 root 了。
    helone
        10
    helone  
       2022-06-20 19:47:11 +08:00
    @jeesk 。。。你就不能写成俩程序,都可以是 GO 写的啊,命令行调用另一个程序执行不就完了嘛
    ysc3839
        11
    ysc3839  
       2022-06-20 20:50:32 +08:00 via Android
    Unix 系统不是有 seteuid 吗?确定是无效的?
    jeesk
        12
    jeesk  
    OP
       2022-06-20 21:20:54 +08:00 via iPhone
    @ysc3839
    @helone
    @nuk
    @helone
    @flynaj 我们用的这个库, 创建一张虚拟网卡, 然后在虚拟网卡上面做数据转发处理。 主要是获取 ifce 对象进行读写监听流量。
    jeesk
        13
    jeesk  
    OP
       2022-06-20 21:21:15 +08:00 via iPhone
    virusdefender
        14
    virusdefender  
       2022-06-20 21:36:35 +08:00
    启动一个 goroutine ,然后 runtime.LockOSThread ,然后 setuid ,这样不会影响主进程的 uid ,或者简单点开一个子命令
    czyt
        15
    czyt  
       2022-06-21 09:12:19 +08:00
    开两个进程,rpc 或者其他方式通信
    tomychen
        16
    tomychen  
       2022-06-21 14:50:39 +08:00
    什么时候 Unix-like 切换权限变成这么大难题了?

    sudo: 我是假的?
    chmod +x: 我可能被忽视了
    jeesk
        17
    jeesk  
    OP
       2022-06-21 15:18:03 +08:00
    ifce, err := water.New(water.Config{
    DeviceType: water.TAP,
    })
    if err != nil {
    log.Fatal(err)
    }
    var frame ethernet.Frame
    n, err := ifce.Read([]byte(frame))
    if err != nil {
    log.Fatal(err)
    }

    这里的 ifce 对象我们用来接收数据, 但是 water.New 需要 root 权限创建。 所以你们说的子命令我个人感觉完全不行。 @virusdefender 大佬说的 lockOsThread 我还没有测试过, 我看看行不行。

    @tomychen
    tomychen
        18
    tomychen  
       2022-06-21 17:49:13 +08:00
    ```
    user@debian:/tmp$ cat test.c
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>

    int main(void)
    {
    system("id");
    setuid(1000);
    setgid(1000);
    system("id");

    }
    user@debian:/tmp$ sudo ./test
    uid=0(root) gid=0(root) groups=0(root)
    uid=1000(user) gid=0(root) groups=0(root)
    ```
    MAC 同理
    jeesk
        19
    jeesk  
    OP
       2022-06-22 10:59:22 +08:00
    @virusdefender 你这个说的设置 uid 是指的是设置 root 的 uid 吗
    virusdefender
        20
    virusdefender  
       2022-06-22 13:29:53 +08:00
    @jeesk set 成你想读取的用户的 uid 啊
    jeesk
        21
    jeesk  
    OP
       2022-06-23 14:55:31 +08:00
    @virusdefender macosx 上面不行的呀
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3651 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 10:27 · PVG 18:27 · LAX 03:27 · JFK 06:27
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.