fix(rm-forbid): convert st_dev to kernel MKDEV encoding before writin… - #160
Open
yuKing123-king wants to merge 1 commit into
Open
yuKing123-king wants to merge 1 commit into
yuKing123-king wants to merge 1 commit into
Conversation
…g rule Signed-off-by: Wang Yu <wangyu6@uniontech.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
修复的 Bug
rm-forbid的-p和-d参数写入的设备号编码与 BPF 侧读取的编码不一致,导致所有 major ≠ 0 的文件系统上保护静默失效——被进程占用的文件仍可被删除,工具完全不拦。根因:
dev_old2new()转换函数已定义(rm-forbid.cpp:36-41),但parse_args的-p和-d两个 case 从未调用它,是死代码。/home(major=253, minor=0)的值stat()返回的st_dev(glibc 编码)(major<<8)|minors_dev(内核 MKDEV 编码)(major<<20)|minorBPF 侧(rm-forbid.bpf.c:71,79)直接读内核的
dir->mnt->mnt_sb->s_dev(MKDEV 编码),用户态存的却是st_dev(glibc 编码)。两个值对任何major ≠ 0的文件系统永远不相等 →rule->dev != fs_dev恒成立 →return 0(放行删除)。为什么
/tmp"碰巧能用":/tmp是 tmpfs,major=0,两种编码公式在major=0时结果恰好相等((0<<8)|minor == (0<<20)|minor),所以/tmp上保护生效,掩盖了 bug。一旦换到/home(major=253)、/(major=8)等真实磁盘分区,保护立即静默失效。对照参考:同仓库的
frtp.cpp:343正确调用了dev_old2new(st.st_dev),rm-forbid是唯一漏掉的工具。改了哪些地方
仅
filter/rm-forbid.cpp的parse_args函数两行:get_fs_dev()的输出(打印给用户看的设备号)保持不变——它打印 glibc 编码值,与stat -c %d一致,用户可用-d <该值>复现,自洽。dev_old2new()函数本身无需改动,只是被调用了。为什么这样修复
dev_old2new()(rm-forbid.cpp:36-41)就是为此定义的,使用gnu_dev_major/gnu_dev_minor拆分 glibc 编码,再按(major<<20)|minor重组为 MKDEV 编码,与 BPF 侧的MAJOR/MINOR宏(rm-forbid.bpf.c:27-28)严格对称。它只是没被调用,调用即可。-p和-d都改:两个 case 写的是同一个rule.dev字段,BPF 侧用同一个s_dev比对,编码必须统一。-d接受的值来自stat -c %d(glibc 编码),同样需要转换,否则-d路径的 bug 与-p完全相同。get_fs_dev打印值不动:打印 glibc 编码(64768)对用户最友好——它和stat -c %d一致,用户能理解和复现。转换发生在"存入 rule"这一步,对用户透明。Rule结构、不碰get_fs_dev、不碰过滤逻辑。改动量与 bug 严重性(保护静默失效)成正比。