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

2021-02-11 01:15:53 +08:00
 mingl0280

有个需求如下: 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

3090 次点击
所在节点    Linux
14 条回复
gyf304
2021-02-11 04:27:26 +08:00
flock 是 advisory 的 不强制锁上的
mingl0280
2021-02-11 06:35:34 +08:00
@gyf304 这就很蛋疼了,Windows 下面我记得是开 named pipe 的时候有个 flag,可以禁止重复打开同一个管道。
wevsty
2021-02-11 12:35:40 +08:00
可以用 apparmor 或者 SELinux 来限制其他程序 open
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
2021-02-11 13:02:24 +08:00
ysc3839
2021-02-11 18:19:16 +08:00
@mingl0280 印象中 Windows 的 Named Pipe 更类似 Unix socket,需要服务器进行类似 accept 的操作 (ConnectNamedPipe),客户端才能连接上。
mingl0280
2021-02-12 23:56:46 +08:00
@BlackL 对的,要重新挂载文件系统,根本没法整这个。
no1xsyzy
2021-02-13 13:41:48 +08:00
在同一个内核,其他 root 也不能读就只有 AppArmor 和 SELinux 了。

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

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

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

如果两边的程序都可以修改,也只需要保证 Confidentiality 的话,可以两边加个密( D-H 密钥交换 + AES )(大概有点 overkill )
mingl0280
2021-02-14 00:05:35 +08:00
@no1xsyzy 加密满足不了性能需求(板子性能弱,定制裁剪版 IOT 设备),ramfs 考虑过但是 ramfs 挂载得改系统内核,也很麻烦。
no1xsyzy
2021-02-14 14:02:13 +08:00
@mingl0280 ramfs tmpfs SELinux AppArmor 有一个就行了吧,内核都被裁也太惨了
或者有 loop 弄个文件 mount -o rw,loop,mand ?
codehz
2021-02-14 20:14:21 +08:00
不是,你终端方面防破解有用吗。。。有 root 人家直接读写内存就能 dump 出来了啊。
这个思路就很有问题。。。
mingl0280
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
2021-02-15 02:25:03 +08:00
@no1xsyzy 不是什么有没有的问题,是你不能假设客户有这些东西。
no1xsyzy
2021-02-15 22:22:46 +08:00
@mingl0280 受我经历所限,我拍脑袋认为是完整的解决方案了……

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/752889

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX