LWN: 怎样让immutable文件彻底无法修改?

栏目: 后端 · 发布时间: 5年前

内容简介:Implementing fully immutable filesBy题图:

Implementing fully immutable files

By Jonathan Corbet,  April 19, 2019

题图: Photo by  Ekrulila  from  Pexels

Linux和其他Unix-like的system一样,都使用了传统的文件权限设置bit的方法来配置哪些人可以访问文件系统里的这个文件。只有很少用户知道,用chattr和lsattr命令可以看到更多的隐藏权限设置bit。这些bit可以把一个文件配置成只允许append(追加模式),或者让一个文件在系统备份的时候被排除在外,让文件在被删除时自动把data覆盖掉,或者不允许此文件被修改。可惜这些保护bit的实现并不完整,也就是说,有些场景下,哪怕文件被标为immutable(不可修改),也其实是能够被修改的。Darrick Wong提出了一组patch来修正这个问题,他实现了一个很可能会影响user space application的功能,他自己称之为“可能会毁灭一切的改法”。

通过chattr的man page帮助页面,我们可以了解到immutable bit如果被置1了,会有如下行为:这个文件就不能被修改了,也就是说不可以被删除,不可以被改名,不可以创建指向这个文件的link(文件链接),文件里面的绝大多数属性信息都不能修改,也不允许用write mode来打开这个文件。

上述描述绝大多数是准确的(至少针对那些支持immutable bit的文件系统来说)。Wong却找到了一个重要例外场景:在immutable bit被设置之前就打开这个文件的进程可以一直拥有对此文件的写权限,只要file descriptor不要释放。也就是说这个文件并不是严格意义上的immutable(不可更改)。

这种不一致的行为很不合理。因此Wong就想把这个机制做完整。这样需要做出两处修改,首先说简单的改动,每当一个进程去对一个file descriptor进行写操作的时候,就调用generic_write_checks()函数来确保这个写操作是合法的。这样当文件被改为immutable之后,写操作write()马上就会返回错误代码。还有需要在do_mmap()函数里也增加类似的检查,这样能避免从这个immutable的file descriptor来创建writable memory mapping(允许写操作的内存映射)。这样基本上就没法修改immutable file文件了。

不过还有个遗留问题,就是可能早就已经有一个相应的writable memory mapping了,这些地方仍然是可以写入的。user-space的代码不需要调用任何system call系统调用,就能去写这块内存区域,因此没法像write()和mmap()一样简单加check来解决。不过好在已经有了一个比较好的机制来预防这类写入了,那就是文件系统的管理writable mapping的机制。文件系统之前面临的问题很类似,就是当user space去写一块writable mapping来更改文件的时候,文件系统收不到任何通知,这样就无法确保新写入的数据最终能写入存储外设去。所以文件系统采用的技巧就死把这块区域配置成write-protect的模式。这样当user-space去写这块内存区域的时候,就会出发page fault,然后kernel可以修改这个page为可写模式,并且同时通知文件系统这个page被人写了。当文件系统模块的代码最终把修改过的page写入磁盘的时候,就可以把相关page再次改为write-protect模式,相当于标记这个page为clean状态,然后等待捕捉下一次写入。

因此,我们可以利用这个机制来预防对immutable file的写操作,那就是在page fault发生的时候。kernel如果此时发现文件是immutable的,就直接返回错误值SIGBUS给user space。可惜,如果这个page本来就是已经被标记成writable的话,就没法捕捉到了。也就是说user space可以继续写这部分writable的区域,而不被截获。因此最后一步需要修改每一个文件系统来支持这个功能。这就是为什么Wong的patch那么大了。文件系统的代码里面早就有一个ioctl()函数,每次文件被设为immutable的时候这个ioctl()函数都会被调用到,因此这个ioctl()函数里面此时需要增加如下动作:如果有direct I/O操作在进行,那必须得在把文件真正改为immutable之前先完成那些direct I/O操作;当前memory map里面处于dirty状态(意味着有写入的数据还未刷写到外存里面去)的page都需要被flush到permanent storage外存里面去。上述操作完成后才能真正把文件配置成immutable,这样才能保证文件的persist状态(内容一致)。最后,所有已经被memory map的属于这个文件的page都被标记为read-only,无法再被直接修改了。大多数种类的文件系统里面,flush dirty page和配置为write-protect都已经被实现为一个函数了,只要调用对了这个函数即可。

最终,当一个文件被标记为immutable的时候,就真的不能再被修改了,直到某个特权用户能清除掉immutable bit。因为这里改变了kernel的行为,之前如果有某些user space的application需要在文件设为immutable之后还要能写入之前已经打开的file descriptor的话,现在就会收到错误返回值,无法正常写入了。有一个有趣的Hyrum's law里面就提到,只要你实现的功能被别人使用了,那么无论里面的实现细节是否是你特意为之的,也不管是否你承诺过这个细节实现,总有一些人会依赖它、利用它的。因此搞不好真的有application目前是依赖这个immutable的特殊用法的。那么Wong就很可能不得不放弃这个patch set。让我们拭目以待吧。

全文完

极度欢迎将文章分享到朋友圈 

长按下面二维码关注:Linux News搬运工,希望每周的深度文章以及开源社区的各种新近言论,能够让大家满意~

LWN: 怎样让immutable文件彻底无法修改?


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Python机器学习基础教程

Python机器学习基础教程

[德]安德里亚斯·穆勒、[美]莎拉·吉多 / 张亮 / 人民邮电出版社 / 2018-1 / 79.00元

本书是机器学习入门书,以Python语言介绍。主要内容包括:机器学习的基本概念及其应用;实践中最常用的机器学习算法以及这些算法的优缺点;在机器学习中待处理数据的呈现方式的重要性,以及应重点关注数据的哪些方面;模型评估和调参的高级方法,重点讲解交叉验证和网格搜索;管道的概念;如何将前面各章的方法应用到文本数据上,还介绍了一些文本特有的处理方法。一起来看看 《Python机器学习基础教程》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

随机密码生成器
随机密码生成器

多种字符组合密码

MD5 加密
MD5 加密

MD5 加密工具