qyb的博客

One more hop for Kermit

http://lwn.net/Articles/448636/
By Jonathan Corbet
June 22, 2011

翻译:马少兵

在过去最美好的时代,我做 VMS 系统管理员的时候,那时 ARPAnet 还是一个很小、龟速的网络,而且接入点及其有限。当一些牛人基于UUCP连接建立了USENET,Unix系统还没有被广泛使用。但已经开始出现了个人电脑,电子公告板系统也开始被建立,我们中的一些幸运儿还能够买得起1200波特的调制解调器。在那些日子里所使用的调制解调器工具是一个叫做 kermit 的小程序,并且下载是完全免费的。俺已经不记得最后一次使用调制解调器是哪个时候,但是我仍然会很有兴趣去看到,已经30多年的工程即将通过最后的过渡,和其他的一样,最终走向自由软件。

那个年代的许多系统,尤其是没有任何政府预算支持的,其“网络接口”是串口。通过该接口,我们可以连接到计算机工作,也是它让我们在那个时代获得了最早的远程服务。任何通过RS232联网的用户首先需要在计算机的RS232接口和modem的RS232接口之间交换串行数据。尽管Unix系统通过一个叫“cu”的工具来达到这个目的,但是人们还是倾向于用kermit来代替。

Kermit最早起源于美国哥伦比亚大学,是把它作为多种不同网络环境下的计算机通信的方法。相比”cu”,kermit具有容易安装到软盘、设置和使用的特点。仅仅只需要弄清有多少数据位、多少停止位、多少校验位(RS232是最流行的标准)、以及适合与调制解调器上的ATD命令相对应的类型是什么等。Kermit甚至可以对不同处理字符集之间进行转换;也可以直接同 EBCDIC主机通信。

在一个很短的时间内,Kermit开发了一些适合文件传输的功能。该协议是相当有效率的,而且它的设计还包括用于处理串口通信中偶尔出现的控制字符,将8位数据转为7位数据等。该协议的健壮性意味着,它可“工作于”任何两种类型结构的机器之间。所以在前互联网时代,Kermit成为了最流行的文件传输协议,是不足为奇的。

尽管哥伦比亚大学以源代码方式发布了Kermit的多个版本;包括从 BBS 下载,DECUS磁带等,但是从来不是自由软件。造成这样问题的主要原因是,当kermit首次发布和使用的时候,自由软件许可证还没有出现。虽然哥伦比亚大学已经考虑将代码发布到一个公共的领域,但是这种决定看起来并不是最好的。

因为我们想使得Kermit软件能够被公开共享,而不是仅仅发布到一个公共领域,虽然这看起来是矛盾的。我们觉得通过拥有版权,可以防止企业独占该软件,以及所带来的将该软件成为一种商业产品而出售的情况。因为在我们面前已经发生了一系列这样的事件,由于一些大学将自己的代码发布至公共领域,结果被公司重写,最终使得公司占据了该代码的版权。

Kermit许可证会随着时间变化而改变,但是“你可以使用在非商业化的程序中”的情况是保持不变的。Kermit许可证的最终版本允许,可以将该代码绑定在免费的操作系统之中,但是禁止在没有允许的情况下修改源代码。因此事实是,尽管Kermit许可证和Linux操作系统一样允许分发,但是由于它不是一个真正的免费软件,而导致大量的发行版最终躲避使用它。

除了免费的操作系统以外,任何人想要发布商业化与Kermit有关的系统,必须向哥伦比亚大学购买许可证($3-10/each)。

在过去,Kermit已经取得了引人注目的成绩。但是随之而来的互联网已经取代它的位置。现在利用手机,都可以运行ssh协议。RS232逐渐退出了历史舞台。内核的开发者仍然在某些情况下用串口进行调试,但是我估计,大部分的LWN读者从未考虑过什么是 null modem cable. Kermit的用户肯定会逐渐萎缩,对那些需要的人来说,仍然会被使用和购买

可能在三月份,哥伦比亚大学宣布不再支持Kermit项目的维护了。其中一个可能性是由于商业许可证的销售额减少,导致没有足够的日常管理费来维持目前的工作。在2011.7.31号以后,哥伦比亚大学将不再开发任何的代码加入到Kermit系统中,也不再提供系统支持和维护服务。已经运行了30年得工程即将结束。

哥伦比亚大学计划在Kermit系统结束以前还要做一件事情,那就是将该软件放置于BSD许可证下。C-Kermit9.0版本就携带该许可证信息;6月15号,首个测试版已经发布。9.0版本将支持FORCE-3包协议(“使用在恶劣环境下”),改进了相应的脚本、修复了很多地方的bug等。因此9.0版本的发布,大概会选取一个距离7月31号截止日期之前的某一天,不仅仅有新的功能。而且将会首次免费发布。

由于这种变化的结果,Kermit将会很快出现在你的发行版的仓库中;对于大多数的Linux用户,这一点关注度可能很小。但是对于我们中的大多数,有时候通过串口连接是唯一和系统进行通信的方式。虽然Kermit系统远不是我们唯一的选择,但它相当不错。我们很欢迎Kermit能够加入开源软件社区。

Topic: sohulinux

一个Crypt_Blowfish加密中存在的漏洞

A hole in crypt_blowfish
By Jake Edge
June 22, 2011

翻译:史玉良

最近在crypt_blowfish密码散列库中发现了一个长期以来一直存在的bug。由于crypt_blowfish加密算法已经存在多年(据称该bug可以追溯到1998或1997年!),并已广泛应用于其他安装包(例如PHP)和一些Linux发行版中;从该事件可以看到,一个广泛应用的底层库若出现bug时可能会引发相当大的麻烦。该bug对于安全性的影响不大,因为它只影响到一些不常用于做口令的字符。但对于那些存储了由该库函数而产生的散列密码的部分人来说,这个bug就会有些头疼。

密码散列技术是一个用于鉴权机制(例如登陆一个系统或网络应用)的标准技术。明文密码并不需要存储,而由明文密码派生出来的密文需要存储。SHA-1Blowfish cipher是比较有代表性的用于该目的的单向加密散列技术。当用户输入密码时,调用相同的Hash函数,并将生成的密文与已经存储的密文做比对。这个想法是,即使攻击者侵入了密码数据库,他们也需要破解那里存储的密码散列值才行。正如其名称所示,crypt_blowfish是在Blowfish算法的基础上实现的密码散列技术。

这个bug本身很简单,其修复方法在C程序员看来是显而易见的。在面向对象的程序设计系统中,需要把 BF_std.c: BF_std_set_key()中的
tmp |= *ptr;
改为:

tmp |= (unsigned char)*ptr;

基本上来说这是一个符号扩展的bug。对于那些不是C程序员的黑客,可能需要一点解释。当存储在*ptr中的值高位被置为1时,它将被视为一个负数。因此,在该值与tmp(一个无符号整型)做或运算之前,它会被提升到4字节并做符号扩展。例如一个byte值0x80会变成0xffffff80。正如人们所预料的那样,之后的或运算将会产生一个错误结果。

这个问题实际上是由John the Ripper(JtR)口令破译软件程序发现的。作为创建测试套件的一部分, "magnum"(万能)尝试去破解由一个库(并非crypt_blowfish)的散列函数产生的包含有单个非ASCII字符(£或0xa3)的口令。由于JtR和crypt_blowfish 共用相同的Blowfish加密算法实现,同时使用时测试会通过,但是算法其它的实现将产生正确的散列,从而会不匹配JtR所产生的散列。

JtR和crypt_blowfish的开发者Alexander Peslyak(同时也是Solar的设计者)分析了这个bug产生的影响并发现,一些口令组合通过散列运算会产生差异很小的相同值(例如"ab£" 产生的值为"£"),这将会使得口令破译变得简单。进一步的分析显示,在最高位被置1的字符前出现的一些字符在计算散列值时会被有效的忽略。这意味着一个比用户给出的密码更简单的密码也会被视为有效——这是对用户口令作用的一个重大削弱。

应该指出的是,Solar的设计者关于这个问题的细节说明及其产生的影响即将公布。他的CVE(通用漏洞披露)要求相当详尽,并且他为这个错误承担所有的责任。其他发现projects中存在安全漏洞的程序员也应该按照他的先例来处理类似情况。

JtR并没有什么实际问题,由于它可以更新算法,所以它可以正确破解高比特位设置为1的密码。此外,它可以继续使用老的算法来破解由于hash函数错误生成的密码。但是使用crypt_blowfish的应用就不可同日而语了。高位被置位可能相当少见——至少对于那些只服务ASCII用户的网站是这样,但是目前还没有简单的方法来判别存储的散列值是否有效。

对可能存在错误的密码散列值(包括现行的Openwall Linux (Owl), SUSE和 ALT Linux上的用crypt_blowfish算法产生散列值存储的密码数据库)的管理员来说,最安全的解决方案就是使现有的所有密码失效而后要求用户重新设置密码。这简直是逻辑噩梦。不过,这取决于如何简单、安全并且不需要通过现有密码鉴权就能使用户可以设置新密码。要求用户登陆以后改变现有密码是一种替代方案,不过这可能会给攻击者可乘之机。它同时为所有未登陆的用户保留原有密码不变。

攻击者利用这一漏洞登陆一个网站的风险相当小,但却是存在。如果一个网站的登陆过程容易受到暴力攻击,那么这个bug会使这个攻击变得容易,至少对于特定的密码类型是这样的。另一方面,如果密码数据库已经暴露出来,并且一些密码没有被破解(至少对于没有使用JtR程序的攻击者),这个信息可以给他们提供破译那些密码的方法。最终的分析结论是,这是一个可以被利用的,但并不会让管理员们陷入恐慌的漏洞。

令人惊讶的是这个bug在广泛被使用的库中存在了超过了13年!到目前为止,没有人用这种方式测试它,至少没有公开。这应该给那些使用固定版本软件(包括免费的和专有的)一些警示。自由软件(crypt_blowfish已经被置于公共领域,这可能在法律上有点模糊,但是这与自由软件的理念是一致的)有更多,更容易的机会来检查和测试代码,不过,只有实实在在的测试才是有效的。

毫无疑问,bugs依旧潜伏于我们每天所依赖的各种面向安全的库中,因此,定期地、系统地测试这些类库(还有那些没有用于安全用途的代码)可以帮助我们查出bugs。虽然超过10年才发现了这一bug,但值得指出的是,在此期间它可能已经被其他人发现。攻击者显然也在做自己的测试工作,不过他们的测试结果通常不会公布出来。可能和这里讨论的情况不一样,不过应该始终认识到,公开披露一个漏洞和它被发现之间是没有必然联系的(可能在被公开之前已经有人发现了)。

Topic: sohulinux

Brother Louie

周日开车的时候,从收音机里听到这首歌。

我靠,实在是太老了,太怀旧了。。下回去卡拉OK完全可以尝试

Topic: 音乐

新的连续内存分配器

A reworked contiguous memory allocator
By Jonathan Corbet
June 14, 2011

翻译:王鑫/李潇

关于分配大块儿连续物理内存的问题经常在 LWN 讨论。虚拟内存,由其性质决定了它总会将页面分散到整个系统;内核长时间运行后,可供分配的页面极少会出现一个挨一个的情况。多年来,内核开发者们处理这个问题的方式就是尽可能地避免对大范围连续内存分配的依赖。内核代码很少会试图分配超过两个的连续物理页面。

近来,关于大范围连续内存分配的需求越来越多。需求之一是超大页面数,尤其是transparent huge pages feature。另一个则是老树开新花了:硬件不能执行分散/收集DMA。任何只能对连续物理内存区域做DMA的设备(缺少I/O内存管理单元)都要求一个物理上连续的缓冲区来协同工作。这个要求通常是相对低端(stupid)的硬件的一个标志;你可以祈求这样的硬件随着时间越来越少。而我们所关注的是获得一定的能力的同时仍然保留着连续DMA要求的那些设备。比如,视频采集引擎,它能够采集完全高清的数据,然后在其上进行一系列的转换,但是它仍然会需要一个连续的缓冲区用来保存结果。高清视频的出现加剧了这个问题,那些物理连续的缓冲区现在比原来需要分配得更多,而且更难被分配了。

大概一年前,LWN 就开始关注解决这个问题的连续内存分配补丁。这个补丁集遵循着在启动时保留一大块内存的神圣而又庄严的传统,而这个的唯一目的就是为了满足大范围的分配需求。多年以来,这个技术一直被“bigphysarea”补丁所使用,或者简单地在启动内核时使用一个mem=的参数,用来留下一段未使用的物理内存。Android pmem driver也是从保留区域中分配大块内存的。这个方法当然有效,将近20年的经验足以证明它。保留内存的不利之处则在于它对其他任何想使用它的东西都是无效的;如果设备没用使用这块内存,它就简单地被闲置起来。这种内存的浪费在内核开发者和用户之间变得越来越不得心。

基于上述及更多的原因,CMA补丁从未被加入进去。尽管问题并没有被解决而且也没有开发者在其上工作,最新版的CMA补丁集看起来十分不同,虽然仍然有些问题需要解决,但是看起来本补丁集有较大的机会加入到主线中。

这个CMA分配器仍然能够同保留内存区域的方式一起工作,但那很明显不是想要的操作模式。相反,新的CMA试图维护当需要时能够创建连续大块内存的内存区域。为了那个目的,CMA依靠“migration type”机制被深度构建进内存管理代码中。

在每一个区段内,成块的页面被标记为被那些可移动的或可回收的页面使用。可移动的页面主要是那些缓存页或者匿名内存页,它们通过页表和page cache radix tree来访问。这些页的内容可以随着页表和树的更新而相应地被移动到其它地方。可回收页,则是在需要时返回给内核;它们像inode cache一样保存数据结构。不可移动页通常是那些内核拥有直接指针的页面,比如,通过kmalloc()申请的内存不能在不破坏任何东西的情况下被移动。

内存管理子系统试图将可活动页面保持在一起。如果要通过移动页面来获得掉一整块空闲内存,一个单独的固定页面就可破坏整个过程。通过将可活动页面分组,内核希望能不用遇到这个障碍就释放更多的页面,内存压缩代码目前就是依靠这些可活动页面才能工作。

CMA通过增加一个新的“CMA”迁移类型来延伸这个机制;它很像”可活动“类型,但有几点不一样。“CMA”类型比较棘手,内核不能改变被标志为CMA的页面的迁移类型。内存分配器不会从CMA区域分配固定页面,对于其他任何用途,只有当没有其他选择的时候才会分配CMA页面。如果一切顺利的话,被标志为CMA用途的内存区域只会包含可活动页面,并且有数量可观的空闲页面。

换句话说,被标志为CMA用途的内存对系统其余地方保持可用,只有一条限制,那就是它只包含可活动页面。当驱动需要一片连续的内存时,CMA分配器就在它的一个特定范围挤出足够的页面创建一个适当大小的连续缓冲区。如果在这里面的页面真正是可活动,分配器就提供驱动所需要的缓冲区。当缓冲区不再需要的时候,内存也可以被用作其他用途。

有人可能好奇为什么需要这样的机制,因为内存压缩机制就已经能够给transparent huge page创建大片物理上连续的块。那样的代码是可用的:我自己的 Linux 系统,在写这篇文章前,有大约25%被分配为大页面。这个问题的答案就是DMA缓冲区相对大页面有一些不同的要求。DMA缓冲区可能更大,例如,transparent huge page几乎在所有架构里都是2MB大小,而DMA缓冲区能有10M或者更多。如果底层的硬件足够“奇怪”的话,可能有必要将DMA缓冲区放在特定内存范围内,而CMA开发者 Marek Szyprowski看起来似乎就有这种“奇怪”硬件的需求。最终,2MB的大页面必须也有2MB的对齐,而对DMA缓冲区的对齐要求就宽松的多。CMA分配器能取得被请求数量的内存而不用过度担心严格的对齐要求。

CMA补丁集为建立内存区域和创建特定范围的“上下文”提供了一个函数集。有简单的cm_alloc()和cm_free()函数来获取和释放缓冲区。虽然如此,但预期设备驱动将不会直接调用CMA,相反,对CMA的意识将被固定在DMA支持函数里。当驱动调用函数如dma_alloc_coherent()时,CMA将自动被使用来满足要求。在大多数情况下,它应该能“正常工作”。

另外一个CMA的关注点是关于特定区域是如何设置的。目前的补丁期望在系统的board file里面做一些特殊的调用。这是一个很ARM式的方法。接下来的目的是去掉board file,这样就会发现其他东西。正如 Arnd Bergmann所指出的那样,将该信息移到设备树也不是一个选择。这其实是一个策略决策。Arnd正努力争取一些能在大部分系统工作的合理默认设置,其它一些少数系统将在后续被加进来。

最终的结果可能是,patch set至少得经过一个迭代才能进入主线。但CMA满足了以前从未遇到过的一个需求。这部分代码有潜在的可能性能够在减小对其余系统的影响的同时,让分配物理地址连续的内存变得更加可靠。看起来它似乎值得拥有。

Topic: sohulinux

PHP 的各个实现

挖个坑,备忘

  • Zend, 这个就不多说了
  • Quercus,原本是 resin 3 的一个特性,现在好似是作为一个独立项目运行... 看论坛上有人已经把它运行在 jetty 上了
  • P8,又一个运行在 JVM 上的 PHP 引擎,是一个 IBM 的项目,相比较 Quercus 而言,传说它比较好的支持了 PHP C 扩展。但这个项目的页面严重过时。另外它不是开源的
  • Phalanger,PHP on .NET,看起来正在积极的开发中,而且还有商业支持
  • PIPP,运行在 Parrot 上的 PHP,这个项目看起来已经死了,而且 Parrot 离被证明还很遥远
  • PHP 编译器,这个概念和前面的 Zend/JVM/Parrot 不太一样,着眼于直接编译出可执行代码,脱离 VM
    1. HipHop,地球人都知道
    2. phc
    3. Roadsend的Raven/rphp,基于 llvm
Topic: 技术

都不容易

暑假过了一个月,达达的心前所无比的野。不爱写作业,想尽办法偷懒

于是最近有那么段时间,几乎每天她妈都和达达发生剧烈冲突

白天我们上班后,奶奶和达达聊天

奶奶:......你说你妈妈容易吗?

达达:那我容易吗?

奶奶:你有什么不容易的

达达:我得让大人高兴

====

是啊,太不容易了

Topic: dada

blk-throttle: Throttle buffered WRITE in balance_dirty_pages()

http://lwn.net/Articles/446121/
From: Vivek Goyal

翻译:王鑫

Hi,

我一直在尝试寻找关于 blog IO controller cgroups 的以下两个问题的解决办法:
  • IO controller 的当前 throttling 逻辑无法限制buffered WRITES。它的实现是在设备上限制所有的 WRITEs,但到那时,buffered WRITE 已经丢失了提交者的上下文,并且大多数的IO进入到设备上的 flusher 线程的上下文中。因此当前并不支持对buffered write的限制。

  • 所有的WRITEs都在设备级上进行限制,这就很容易导致文件系统的串行。

举一个简单的例子,如果一个进程往cache中写入一些页面,然后运行fsync(),这个时候进程才开始被 throttled ,于是它会锁定整个文件系统。在ext4中,我注意到甚至一个简单的“ls”都不会再继续进行了。这个原因可以归结为文件系统并不关注cgroups和以顺序模式的文件系统日志这件导致串行这件事。

因此即使我们获得提交者的cgroup信息到设备并且在设备那里做限制,它仍然会导致文件系统的串行,这并不是一个好主意。

因此怎样去修正这个问题呢?貌似有以下两种办法:
  • 仍然在设备级上去做限制。让文件系统关注cgroups使得多个事务可以以并行的方式(每一个cgroup)同时前进,并且在cgroups之间并不存在那些导致文件系统串行的共享资源。

  • 当WRITEs进入cache时进行限制而不是直到设备才开始 throttle。比如类似balance_dirty_pages()这样的函数。直接IO仍然是在设备级上进行限制的。按照这种方式,关于限制,我们可以避免文件系统日志导致串行

但是这个方法的很重要的一点就是我们控制进入cache的IO速率而不是设备上的IO速率。按照那样的方法则可能会发生flusher过后会提交许多WRITEs到设备,并且我们将会在终端节点上看到许多周期性的IO spike。

因此这个方法可能会有一点帮助,但远远不是一个完整的解决方案。它主要能够帮助那些拥有许多IO资源和有效IO带宽但是希望控制资源分配给低优先级的客户。

方法1看起来很难去修正。在往文件系统写东西的时候,文件系统从不关注cgroups。因此我很怀疑我能够说服文件系统的设计者来改动基础的文件系统和日志记录部分的代码来使得文件系统关注cgroup。

因此我在本系列补丁中仅实现了方法2。方法2并不是一个最好的解决方案,但是它至少给了我们一些在buffered write上的控制能力,这总比一点都不给要好。Andrea Righi也曾经做过一个类似的补丁:
https://lkml.org/lkml/2011/2/28/115

这个补丁是关于bio和任务限制之间的交互的,因此我重做了它。

设计

IO控制器已经有跟踪一个group的IO速率的能力,并且当group超过一定速率时会把bio插入内部队列,并在随后将这些bio分发出去。

本补丁也引入了balance_dirty_pages_ratelimited_nr()中限制dirtying task的能力。现在所有除直接WRITES外的所有WRITEs在设备级上都不会受限制。如果一个dirtying task超过其配置的速率,它将被放入等待队列,当它可以dirty更多页面的时候才被唤醒。

没有新的接口被引入,直接IO和buffered IO都是使用通用IO速率限制。

How To

- Create a cgroup and limit it to 1MB/s for writes.

echo "8:16 1024000" > /cgroup/blk/test1/blkio.throttle.write_bps_device

- Launch dd thread in the cgroup

dd if=/dev/zero of=zerofile bs=4K count=1K

1024+0 records in
1024+0 records out
4194304 bytes (4.2 MB) copied, 4.00428 s, 1.0 MB/s

Any feedback is welcome.

Thanks

Vivek

Topic: sohulinux

Haraka - a Node.js Mail Server

https://github.com/baudehlo/Haraka#readme

看作者的自述:Haraka is a project started by Matt Sergeant, a 10 year veteran of the email and anti-spam world. Previous projects have been the project leader for SpamAssassin and a hacker on Qpsmtpd, a perl based mail server which is quite similar to Haraka (but not as fast due to perl being slower than Javascript).

貌似不是一个蛋疼的项目... 刚刚发布 0.6.0 版本

Why Use Haraka?

Haraka's primary purpose is to provide you with a much easier to extend mail server than most available SMTP servers out there such as Postfix, Exim or Microsoft Exchange, yet while still running those systems for their excellent ability to deliver mail to users.

postfix 一直没有增加 libevent 的支持,对一个这么活跃的项目,以及这么被广泛使用的服务来说有点异乎寻常。从理论上来说,一个邮件系统的I/O能力是被其磁盘信件队列的I/O能力限制住了,所以网络I/O不追求高并发也可以理解。

但是考虑到垃圾邮件,潜在的DDoS攻击,在 postfix 之前弄一个这玩意确实值得考虑。

以前曾经想过用 twisted 做类似的东东,现在看来又多了一个新选择。

最后要说的是,node/v8 的 gc 确实很蛋疼

订阅 RSS - qyb的博客