delphij's Chaos
选择chaos这个词是因为~~实在很难找到一个更合适的词来形容这儿了……
计时攻击是一种通过观测由于某些操作时泄露出来的时间信息来获取更多信息的攻击。由于设计和实现的不同,攻击者能够通过计时得到的信息也会不一样。简而言之,作为安全系统的设计者,必须对可能泄露信息的各种渠道有充分的了解,并针对它们采取因应措施。
今天在和人讨论的时候想到一个例子,这里记下来。
为了阻止采用 GPU 穷举,我们可能会使用一些增加轮数的散列算法。一个设计不完善的登录系统的登录流程大致如下:
假定我们采用了一种够慢的算法来计算散列值,上述流程的问题便是,假如用户不存在,尽管攻击者观察到的提示是一样的"用户名或密码错误",但这个提示出现的时间可能会比用户存在时慢一些。这样,这个登录系统便透露了"用户不存在"这样的信息。
补救的办法是在用户不存在时,也根据同样的算法计算一下散列串,然后再提示"用户名或密码错误";还有一种办法是增加一个随机的延时。具体采用什么样的做法,要看具体的应用场景。
Read more...sh(1) 脚本中,` 和 $() 的作用类似。比如:
rm
find /foo/bar -ctime +3d -type f`` 【注1】
表示将 find 的输出结果作为rm的命令行输入。
常写 sh(1) 脚本的人可能会用另一个写法:
rm $(find /foo/bar -ctime +3d -type f)
这个写法和第一种是等价的。不过,$()的好处是可以嵌套。
个人比较倾向于使用 ` 而不是 $(),主要有三个原因:
【注1】FreeBSD系统中,此处实际可以用 find /foo/bar -ctime +3d -type f -delete
来代替。
常见的场景是由于某种原因 ls 无法使用(内存不足、动态连接库丢失等等)。
因为 shell 通常可以做 * 扩展,所以我们可以用:
echo *
来列出当前目录中的文件。
Read more...FreeBSD 开始用 10 以上的版本号有一段时间了。这个变动立刻导致了大量 ports 无法编译,多数情况下是因为开发者采用了较早版本的 libtool 导致的,具体来说,是类似下面的代码:
case $host_os in
freebsd[123]*) objformat=aout ;;
*) objformat=elf ;;
esac
解法是在星号前面加个小数点。
前段时间的半夜 make 总是在 OpenOffice 上通不过,结果发现是同样的原因。囧死了……当初匹配的时候打个.会死吗?
(这个问题已经在 libtool 2.4.2 以上版本中修正)。教训是,即使是代码生成器,重复的代码导致维护成本的增加。
Read more...目前多数软件产品的安全更新都是在周二或者周三公布了。这种做法 据说 是微软开始采用的,不过具体是谁先开始这么做,目前我还没有找到非常可靠的资料。
一般来说,软件开发者在发布安全更新之前,需要做下面这些事情:
而在用户这边,通常也需要进行少量的测试才可以大面积部署。由于时差的原因,周一或周五发表安全更新有可能会导致有些人必须在周末工作,因此不合适;周三发表安全公告会给 IT 人员留下充足的测试和部署时间,同时又避开了周末。
Read more...之前只有一篇关于较早版本的 strlen(3) 实现的笔记,这里补上我在 2010 年做的新增改进。
与 Pascal 等语言不同,C 的字符串并不保存串的长度,而是在字符串末尾以 nul 字符(’\0’)来表示字符串结束。这个设计决策是上世纪 60 年代作出的,有都市传说是为了省几个字节的空间,不过我个人认为也可能是因为汇编里面到处都是判断是否碰到了 0 的操作。不管怎么说,这个设计令 strlen 变成了一个 O(n) 的操作。
早期的 BSD Unix 采用的 strlen 是非常简单的循环比较每一个字符是不是 nul。1993年,J.T. Conklin 为 i386 系统撰写了一个汇编的版本,这个版本的核心用的是 REP SCASB,实际上和 C 版本的算法是一样的(不知道为什么 C 编译器不能写出同样的代码)。
为了配合 x86_64 平台,后来又有了一个新的汇编版本,这个版本的核心算法是按字匹配,找到包含 nul 字符的字之后,再在其中用原始的算法找到 nul 字符。
我在 2009 年根据这个 x86_64 版本的汇编的思路重写了一个 C 的版本,并在 2010 年做了一次最终的变动,形成了目前的版本。这个版本的大致流程如下:
实现细节
整个算法中,比较难理解的是判断字中是否带 nul 字符。具体的方法是计算两个中间变量:
a = (x - 0x01010101)
b = (~x & 0x80808080)
这里的 0x01010101 和 0x80808080 可以进一步扩展。第一步,如果每个字节都 <= 0x7f,只要那个字节不是 0,做差必然得到一个 < 0x80 的结果(换言之,最高位是0);如果有字节 >= 0x81,做差必然得到一个 > 0x80 的结果。对于等于 0x80 的情况,我们会得到 0x7f,但这并不重要。
Read more...最近两次失败记录的教训。
首先是联编 world 和 kernel (make buildworld buildkernel),这个没啥可说的。假定 / 是 UFS(即,可使用 nextboot),且配置了 watchdog,则操作步骤为:
shutdown -r now
mergemaster -Ui
当然,更简单的方法是先接好IPMI。
Read more...可以在 这里 下载。
和过去一样,风险自担 USE AT YOUR OWN RISK!
这个版本 (20120402) 和上一个版本 (20120114) 相比的改动:
全部改动来自 -CURRENT 或 -STABLE,并已经做过至少两周的疲劳测试。
Read more...今天在电视上看了 C-SPAN 上播出的伯南克讲联储局与经济危机(也可以在网上收看)。之前一直不太明白的一些问题得到了解答,不过还是有一些别的问题不太明白。
伯南克讲了联储局的历史、联邦储蓄保险公司FDIC,金本位,以及大萧条相关的话题。其中,FDIC是罗斯福新政保留至今的一部分。银行在放款之后,手头的现金一定小于储户存入的金额,此时如果出现谣言,那么每一个人合乎逻辑的行为便是去银行排队挤兑,因为如果去晚了,银行可能已经被前面的储户挤兑而没有现金了。另一方面,挤兑会产生连锁反应,谣言会越传越厉害,而银行一旦被挤兑,为了支付现金就必须卖出资产(通常是折价卖出),这会进一步加剧其资金短缺现象并真的导致倒闭,而一所银行倒闭了,会导致其他银行倒闭的传闻显得更加真实。在FDIC出现之前,银行能采取的基本就是一个字拖,暂时关门不支付任何现金,并继续收取贷款付款。在 1933 年的银行业重组中,全美国的银行宣布休假,并逐一核对其资产负债表,恢复其中合乎条件的银行的运营。FDIC实际上扮演的是一个担保人的角色,它以政府的名义担保储户的存款(因为政府的信用有税收等做为担保),这种做法要比银行之间的互相担保有效,事实上在那之前纽约的银行业已经出现了这种互相担保的做法,而显然多家银行之间做短期拆借是不足以抗御集体挤兑的。FDIC的出现,解决了那些不良资产比例不太大的银行关闭导致普通人无法获取现金来购买日用品、食物等基本生活保障品的问题,并使挤兑不再必要。
后面关于金本位的讨论很有意思。伯南克认为大萧条中通缩起了关键性因素。由于经济过热,金本位导致通缩,而通缩导致生产者收入下降,而他们很多是靠贷款来购买生产资料,这样一来生产者破产,从而银行跟着破产,进而引发更进一步的经济危机。这个解释了为什么他在任的这段时间不停地采取量化宽松措施来人为增加货币供应量,不过问题来了:如何在这种情况下阻止经济继续过热呢?因为量化宽松会导致利率下降,这会导致融资成本下降,我认为这种措施似乎比较适合生产过剩引发的经济危机才对?
另一个关于汇率的讨论也比较有意思。他提到中国有很长一段时间的汇率是和美元绑定的,而不是采用浮动汇率。这样,美国因为国内经济需要调节汇率的时候,便会间接影响中国的经济:美国降低利率,假如中国不跟着一起降低利率,便会将通胀输出到中国(由于美国的经济规模更大,以及美元的世界结算货币地位,这种输出是单向的)。所以在继续绑定汇率的前提下留下的只有一个选择就是降息(相当于两国事实上使用的是同一种货币,为了避免外汇流入,就必须跟着调整利率),而这种选择未必是适合中国的实体经济的。
我个人总的感觉,美国的这个经济模式的问题在于,需要一直维持一定的通胀率来避免出现金融危机(显然,金本位是无法适应这个需要的,因为从非洲运黄金到纽约的联储局金库成本相当高),而另一方面,生产不可能无限制地不断膨胀,难道说只能过段时间就果断来一次经济危机来缓和一下?
Read more...发现前面写的完全没什么逻辑,等有时间再来整理吧。
关于贷款。这个主要是我自己的理解总结,不一定对,仅供参考。
在美国,贷款的利率是由几个因素决定的。
首先是和股市类似的"大盘",或者说"基准利率",这个利率是以美国政府发行的中长期国债利率决定的。国债一旦发行,其票面利率便确定了,那么为什么说它是"大盘"呢?因为投资者随时可以在市场上买进或卖出国债,这样一来国债成交的价格便可能不同于其票面价值。假如国债价格下跌,也就意味着实际利率的上升。反之,如果国债价格上升,也就意味着实际利率的下降。
在投资者方面看到的效果就是,如果有大批资金涌入国债,推高其价格,那么新买入国债的人拿到的收益便会减少(因为最后还本付息时是按照票面的本金和利率);反之,如果大家发现有更好的投资纷纷卖出国债,导致其价格下跌,则新买入国债的人拿到的收益便会增加。
为什么美国国债如此重要呢?因为美国国债是目前市场上普遍认为风险最低的投资(说句题外话,如果发生了美国国债危机,则一定也会出现另外一种债券来替代它的地位,不过这个几乎是不可能事件)。另一方面,一般来说,如果债务人信誉良好,贷款债权也被认为是风险较低的投资,但这个风险仍然高于美国国债。既然风险高,那么投资者当然也就希望获得更高的回报,这个回报便反映在价格上,即贷款的利息。
因此,通常银行提供的贷款利息的基准利率,便是国债的市场收益率加上一个数额。这个数额的多少,取决于贷款人的信用分数(FICO Score)。
所以我们会看到一个很有意思的现象:在股市大盘下跌的时候,由于许多投资人会选择撤出资金投入债券市场而推高债券价格,从而降低债券收益率,进而促使银行降低贷款利率;反之,当经济复苏,大量投资人卖出债券并买入股票时,银行也会因应提高贷款利率。
还有一个潜在的外力因素是美国政府(具体实施可能通过央行,即联储局)以"量化宽松"的形式买入债券,或外国政府大量买入债券,从而推高债券价格。此时发生的效果和股市大跌类似。
有时,银行也会考虑未来的利率走势,例如,如果银行预期未来贷款利率会大幅提高,则固定利率的贷款利率会开始有所提高,等等。
常见的贷款形式包括头5、7甚至10年固定利率的30年期可变利率贷款(ARM),以及十五年、三十年期的固定利率贷款。对债务人而言,利率固定的时间越长,未来的不确定性就越小,但对银行而言的风险也就越大。由于银行承担的风险不同,它们对应的利率也依次提高。
Read more...