有个需求如下: 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
1
gyf304 2021-02-11 04:27:26 +08:00
flock 是 advisory 的 不强制锁上的
|
2
mingl0280 OP @gyf304 这就很蛋疼了,Windows 下面我记得是开 named pipe 的时候有个 flag,可以禁止重复打开同一个管道。
|
3
wevsty 2021-02-11 12:35:40 +08:00
可以用 apparmor 或者 SELinux 来限制其他程序 open
|
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/ 这里有示例
|
5
BlackL 2021-02-11 13:02:24 +08:00
|
6
ysc3839 2021-02-11 18:19:16 +08:00 via Android
@mingl0280 印象中 Windows 的 Named Pipe 更类似 Unix socket,需要服务器进行类似 accept 的操作 (ConnectNamedPipe),客户端才能连接上。
|
8
no1xsyzy 2021-02-13 13:41:48 +08:00
在同一个内核,其他 root 也不能读就只有 AppArmor 和 SELinux 了。
塞容器里可以保证其他容器里的读不了,但是主机可以读。 极端点,虚拟机,那样的话管道所在的命名空间都不一样(甚至不在同一个内核里)。 @mingl0280 #7 重新挂载文件系统可否用 tmpfs 挂一个 /run/xxx ?那样重新挂载的范围小很多了。 如果两边的程序都可以修改,也只需要保证 Confidentiality 的话,可以两边加个密( D-H 密钥交换 + AES )(大概有点 overkill ) |
9
mingl0280 OP @no1xsyzy 加密满足不了性能需求(板子性能弱,定制裁剪版 IOT 设备),ramfs 考虑过但是 ramfs 挂载得改系统内核,也很麻烦。
|
10
no1xsyzy 2021-02-14 14:02:13 +08:00
@mingl0280 ramfs tmpfs SELinux AppArmor 有一个就行了吧,内核都被裁也太惨了
或者有 loop 弄个文件 mount -o rw,loop,mand ? |
11
codehz 2021-02-14 20:14:21 +08:00
不是,你终端方面防破解有用吗。。。有 root 人家直接读写内存就能 dump 出来了啊。
这个思路就很有问题。。。 |
12
mingl0280 OP @codehz memory dump 的技术需求比 cat 一个文件麻烦多了,如果说直接暴力访问内存的技术难度是 100,cat 一个文件的难度就是 1 。
而且这个需求其实是个跨平台需求(同样的代码需要跑在一个很低性能的板子上和任意一套 Linux 上),加上防的根本不是内存 dump (对,你找错了方向,根本不是防破解而是防的客户的逗逼代码)而是客户如果写了一个或多个 root 进程试图两次打开这个管道并行执行命令……我们这个代码并不需要防破解,反而因为客户跨全球 N 种语言需要防的是那种坑爹代码在 ioctl 上打开多次这个管道文件,然后两个进程同时向同一个管道发送指令的话会直接冲突。这种问题沟通成本很高的,而且也很难调试。 还有就如同我上面说的,这个东西因为要确保代码行为的一致性,不能给不同的平台放不同的代码,也不能随便弄加密,也不可能说我要个权限挂载个 ramdisk 就能挂载。我已经放弃用 pipe 解决这个问题了,domain socket 香多了…… |