V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
mingl0280
V2EX  ›  Linux

Linux 下的命名管道如何限制其它进程访问?

  •  
  •   mingl0280 ·
    mingl0280 · 2021-02-11 01:15:53 +08:00 · 3093 次点击
    这是一个创建于 1383 天前的主题,其中的信息可能已经有所发展或是发生改变。

    有个需求如下: Linux 下进程 A (特权)是系统内唯一的管道读取方,如果有其它进程试图在同一个管道上试图读取,则报错退出。包括其它 root 进程都不应该能读取这个管道。

    我现在测试了下如果我正常开管道的话,cat 还是能读取该管道。如果创建管道后删除管道文件并且调用 flock 加上独占锁(在读取进程里),去 /proc/pid/fd 下面依旧能使用 cat 对管道执行第二个读取操作……( cat 好像是用的 ioctl ?) 请问有没有办法把这两个地方都锁上或者不让读取?例如使用 ioctl 之类的(对这个真的不熟),或者这个设计本身有问题,需要换一种实现方式?

    谢谢。

    p.s.测试用到的代码如下: https://gist.github.com/mingl0280/c6d7e88bc3e0c8079498b20ab9afddf3

    读取方: https://gist.github.com/mingl0280/c6d7e88bc3e0c8079498b20ab9afddf3#file-reader_side-cpp

    写入方: https://gist.github.com/mingl0280/c6d7e88bc3e0c8079498b20ab9afddf3#file-writer_side-cpp

    14 条回复    2021-02-15 22:22:46 +08:00
    gyf304
        1
    gyf304  
       2021-02-11 04:27:26 +08:00
    flock 是 advisory 的 不强制锁上的
    mingl0280
        2
    mingl0280  
    OP
       2021-02-11 06:35:34 +08:00
    @gyf304 这就很蛋疼了,Windows 下面我记得是开 named pipe 的时候有个 flag,可以禁止重复打开同一个管道。
    wevsty
        3
    wevsty  
       2021-02-11 12:35:40 +08:00
    可以用 apparmor 或者 SELinux 来限制其他程序 open
    BlackL
        4
    BlackL  
       2021-02-11 13:01:14 +08:00
    [fcntl]( https://man7.org/linux/man-pages/man2/fcntl.2.html)文档里有提到强制锁( Mandatory locking ),可以看一下,似乎开启条件有点苛刻,而且也支持的不好,https://gavv.github.io/articles/file-locks/ 这里有示例
    BlackL
        5
    BlackL  
       2021-02-11 13:02:24 +08:00
    ysc3839
        6
    ysc3839  
       2021-02-11 18:19:16 +08:00 via Android
    @mingl0280 印象中 Windows 的 Named Pipe 更类似 Unix socket,需要服务器进行类似 accept 的操作 (ConnectNamedPipe),客户端才能连接上。
    mingl0280
        7
    mingl0280  
    OP
       2021-02-12 23:56:46 +08:00
    @BlackL 对的,要重新挂载文件系统,根本没法整这个。
    no1xsyzy
        8
    no1xsyzy  
       2021-02-13 13:41:48 +08:00
    在同一个内核,其他 root 也不能读就只有 AppArmor 和 SELinux 了。

    塞容器里可以保证其他容器里的读不了,但是主机可以读。

    极端点,虚拟机,那样的话管道所在的命名空间都不一样(甚至不在同一个内核里)。

    @mingl0280 #7 重新挂载文件系统可否用 tmpfs 挂一个 /run/xxx ?那样重新挂载的范围小很多了。

    如果两边的程序都可以修改,也只需要保证 Confidentiality 的话,可以两边加个密( D-H 密钥交换 + AES )(大概有点 overkill )
    mingl0280
        9
    mingl0280  
    OP
       2021-02-14 00:05:35 +08:00 via Android
    @no1xsyzy 加密满足不了性能需求(板子性能弱,定制裁剪版 IOT 设备),ramfs 考虑过但是 ramfs 挂载得改系统内核,也很麻烦。
    no1xsyzy
        10
    no1xsyzy  
       2021-02-14 14:02:13 +08:00
    @mingl0280 ramfs tmpfs SELinux AppArmor 有一个就行了吧,内核都被裁也太惨了
    或者有 loop 弄个文件 mount -o rw,loop,mand ?
    codehz
        11
    codehz  
       2021-02-14 20:14:21 +08:00
    不是,你终端方面防破解有用吗。。。有 root 人家直接读写内存就能 dump 出来了啊。
    这个思路就很有问题。。。
    mingl0280
        12
    mingl0280  
    OP
       2021-02-15 02:23:57 +08:00
    @codehz memory dump 的技术需求比 cat 一个文件麻烦多了,如果说直接暴力访问内存的技术难度是 100,cat 一个文件的难度就是 1 。
    而且这个需求其实是个跨平台需求(同样的代码需要跑在一个很低性能的板子上和任意一套 Linux 上),加上防的根本不是内存 dump (对,你找错了方向,根本不是防破解而是防的客户的逗逼代码)而是客户如果写了一个或多个 root 进程试图两次打开这个管道并行执行命令……我们这个代码并不需要防破解,反而因为客户跨全球 N 种语言需要防的是那种坑爹代码在 ioctl 上打开多次这个管道文件,然后两个进程同时向同一个管道发送指令的话会直接冲突。这种问题沟通成本很高的,而且也很难调试。
    还有就如同我上面说的,这个东西因为要确保代码行为的一致性,不能给不同的平台放不同的代码,也不能随便弄加密,也不可能说我要个权限挂载个 ramdisk 就能挂载。我已经放弃用 pipe 解决这个问题了,domain socket 香多了……
    mingl0280
        13
    mingl0280  
    OP
       2021-02-15 02:25:03 +08:00
    @no1xsyzy 不是什么有没有的问题,是你不能假设客户有这些东西。
    no1xsyzy
        14
    no1xsyzy  
       2021-02-15 22:22:46 +08:00
    @mingl0280 受我经历所限,我拍脑袋认为是完整的解决方案了……
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1373 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 81ms · UTC 17:22 · PVG 01:22 · LAX 09:22 · JFK 12:22
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.