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

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

内容简介: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文件彻底无法修改?


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

查看所有标签

猜你喜欢:

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

编码整洁之道

编码整洁之道

罗伯特·C.马丁 / 电子工业出版社 / 2012-8 / 59.00元

忍受各种不确定性及不间断的压力并能够获取成功的程序员有一个共通特征:他们都深度关注软件创建实践。他们都把软件看做一种工艺品。他们都是专家。在“鲍勃大叔”看来“专业”的程序员不仅应该具备专业的技能,更应该具备专业的态度,这也是本书阐述的核心。专业的态度包括如何用带着荣誉感、自尊、自豪来面对进行软件开发,如何做好并做得整洁,如何诚实地进行沟通和估算,如何透明并坦诚地面对困难做抉择,如何理解与专业知识相......一起来看看 《编码整洁之道》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换