Archive for 2010
利用HTTPS代理访问GitHub
网上找了不少设置方法,终于翻出来一个可行的,和大家分享下。
1. 安装corkscrew,ArchLinux和Ubuntu的源里就有,也可以从http://www.agroman.net/corkscrew/下载源码编译一个。
2. 修改~/.ssh/config
Host gitproxy User git Hostname ssh.github.com Port 443 ProxyCommand corkscrew proxy.example.com 3128 %h %p IdentityFile /home/username/.ssh/id_rsa
修改其中的proxy.example.com和3128为代理IP和端口,如果代理需要帐号密码,就在ProxyCommand这一行的最后加上密码文件,内容为用户名:密码。
IdentitiFile的参数是对应于GitHub中帐号的私钥地址。
3. 使用git@gitproxy作为新地址访问GitHub即可,例如要clone git@github.com:foo/bar.git,执行git clone git@gitproxy:foo/bar.git即可。
原文地址:http://www.wetware.co.nz/blog/2010/03/cant-access-github-behind-proxy-or-firewall/
User git
Hostname ssh.github.com
Port 443
ProxyCommand /usr/local/bin/corkscrew proxy.example.com 3128 %h %p
IdentityFile /home/jordan/.ssh/id_rsa
跨站脚本攻击和BluePrint
Blueprint: Robust prevention of cross-site scripting attacks for existing browsers
这篇论文提出了一种防范是跨站脚本攻击(XSS)的新的方法,发在IEEE S&P 2009上,作者是UIUC的Mike Ter Louw。
所谓跨站脚本攻击,简单地说就是在网页中注入非法的脚本代码,从而达到攻击的效果。比较著名的例子有当年在MySpace上泛滥的Samy蠕虫,通过特殊的脚本注入手段,每一位访问Samy主页的用户,他们的主页都会被修改加上一段Samy is my hero文字,并且他们的主页也会被植入攻击代码,从而把这段脚本扩散给更多的用户。
通常防范跨站脚本攻击的方式有两种。一种做在服务器端,为每一段用户上传的内容做检查,并剔除恶意代码。但这种方式很难保证能过滤掉所有的恶意字符串,一方面攻击方法防不甚防,有兴趣的朋友可以参考下XSS Cheat Sheet,上面给出了很多一般人很难想到的攻击代码的组合方式。另一方面由于现在大多数论坛和博客都支持<b> <i>等修饰标签,所以简单的标签剔除或者重新编码都不可行。
另一种方法是做在浏览器端,但是由于浏览器无法区分某一段脚本到底是来源于不可信的用户还是可信的站点,所以这种方法实现起来也有很大的困难。
这里实现防范措施的一个难点在于,Web应用把生成HTML的返回给浏览器后,就不参与浏览器的HTML解析工作了。这样浏览器就不知道哪部分出现脚本是安全的,哪部分出现是不安全的。
BluePrint就着眼于这个点,提出了一种让Web应用“参与”HTML解析工作的设计。下面通过论文里面的一个例子,简单介绍下它的防范机制。
假如一位恶意的用户在一个博客上上传了这样一段含有恶意代码的留言:
<p> Here is a page you might find <b """><script>doEvil(. . .)</script>">very</b> interesting: <a href="  javasc
ript:doEvil(. . .);"> Link</a> </p><p style="nop:expres/*xss*/sion(doEvil(. . .))"> Respectfully, Eve </p>
可以看到,这段代码里包含了很多可能引发脚本执行的代码,而要在服务器端把这些所有隐藏的攻击可能找出来是一件比较困难的事。那么BluePrint是怎么在不知道这段代码是否含有恶意代码的前提下处理的呢?
首先,这种由用户上传的不可信的字符串会先在服务器端被解析成一棵树,就像HTML在浏览器中被解析一样,这棵HTML解析树可以用一些简单的DOM API来生成,例如appendChild, createElement等。这些描述如何生成HTML解析树的方法会和数据值(URL、标签属性等)一起,通过特殊的编码(Base64)传递给浏览器。例如上面这段代码,最后在浏览器接收到的HTML中,会变成这样:
<code style="display:none;" id="__bp1">
=Enk/sCkhlcmUgaXMgYSBwYWdlIHlvdSBta...
=SkKICAgICI+dmVyeQ===C/k/QIGhlbHBmd...
=ECg===C/Enk/gCiAgUmVzcGVjdGZ1bGx5L...
</code><script id="__bp1s">
__bp__.cxPCData("__bp1", "__bp1s");
</script>
在浏览器端,这段特殊的代码会被JS库解析成自定义的命令和数据格式,并由前面提到的DOM API动态生成这些HTML结点,从而达到和传统的方式一样的显示效果。当然可信的HTML代码,例如文章正文,还是按传统的方式传输的。
通过这种方式,BluePrint绕过了浏览器对不可信代码的解析,从而防止了不可信代码里内嵌的脚本的执行。
此外还有一些细节的问题,例如为什么使用Base64编码来描述自定义的命令和数据,而不是常用的例如UTF-8呢?这是因为使用UTF-8的话攻击者就有可能通过构造一段特殊的字符串,而这段字符串对应的编码恰好能起到攻击作用。而使用Base64编码就不会有这个问题。
攻击例子中的第5行和第7行还分别包括了通过恶意URL和CSS风格实现的代码,前面提到的措施还不足以防范这两种类型的攻击。论文里面也提到了相应的解决方案,这里不再赘述,有兴趣的朋友可以搜索论文阅读相关部分。
把BluePrint整合到现有的应用程序里也不难,只要把包含不可信内容显示部分的代码重新加一层包装就行了,像这样:
// Code for trusted blog content
// appears untransformed aboveˆˆ.
<?php foreach ($comments as $comment): ?>
<li>
<?php
$model = Blueprint::cxPCData($comment);
echo($model);
?>
</li>
<?php endforeach; ?>
在BluePrint的开销方面,包含25个用户评论的wordpress页面产生速度慢了55%,不过作者提到wordpress本身还有HTML解析和恶意代码检查过滤的功能,用了BluePrint后就不需要这些冗余的检查了,所以把这部分代码去掉会快不少。另外由于不可信内容都需要动态的被解码并创建相应的HTML结点,浏览器端的显示速度慢了很多,作者也解释到这种解析开销其实并不重要,因为通常看一篇博文的时候都是先看内容,由于文章内容本身是可信的,所以会以传统的方式传输并显示,若干秒后再显示评论也未必会对用户体验造成太大的影响。
这篇论文给我的感觉是思路很清晰,抓住了主要的难点后用了对应的方法绕过了浏览器的HTML解析。不过应用面上还有一些局限,只能防止不可信代码中脚本的执行,对于需要执行脚本的情形(例如Blogger上的Gadget)就不适用了。MIT去年发在EuroSys ’09上的BFlow就是针对这样一种情形,通过类似于Flume的标签系统,使得不可信的脚本读取了隐私数据后就无法将它们传输给不可信的网站。
用beamer做了slides,在这里可以下载到: http://zellux-notes.googlecode.com/hg/slides/blueprint/
记录GNU screen中的历史命令
GNU screen中执行的历史命令保存在内存中,默认情况下并不会像在bash中直接执行的命令一样保存在.bash_history中,这在某些场合下带来了一定的不便。
在superuser上看到一个解决方法,指定历史文件的读写方式为追加,并在每次命令行提示符显示的时候,自动更新bash的历史命令记录。要实现这个方法很简单,只要在.bashrc中加入下面两行代码即可
shopt -s histappend export PROMPT_COMMAND="history -a; history -n"
另外如果之前设置过PROMPT_COMMAND的话,只要在history -a前加入$PROMPT_COMMAND; 就行了。
因为1个异常导入190个包
今天reddit programming上的一个帖子,提到了ubuntu上python-apport包的一个bug。
重现这个bug很简单:
Type "help", "copyright", "credits" or "license" for more information. >>> import sys >>> len(sys.modules) 35 >>> foo Traceback (most recent call last): File "", line 1, in NameError: name 'foo' is not defined >>> len(sys.modules) 225 >>>
在执行foo之前,当前导入的包只有35个,执行之后却有了225个。问题出在Ubuntu的Apport系统,它为Python添加了一个异常处理方法,这里面的bug导致了这些多余的包被导入。
这个bug已经被人提交并被确认,目前暂时还没有补丁,最简单的避免方法就是把python-apport包卸载
原文地址: http://rhodesmill.org/brandon/2010/ubuntu-exception-190-modules/
SICP里提到的画图语言
SICP第二章里提到了一种用来画图的Lisp方言,用来演示数据抽象和闭包的表达能力(见http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-15.html#%_sec_2.2.4)。
最近尝试了下,发现soegaard同学已经在PLT Scheme中实现了一个类似的库,可以很方便的在DrScheme上使用。
sicp.plt包使用很简单,在Language->Choose Language中选择Module,然后在需要用到这个包的时候用
(require (planet soegaard/sicp:2:1/sicp))
声明即可。第一次运行时DrScheme会自动下载这个包并安装,如果网络有限制可以先从http://planet.plt-scheme.org/display.ss?package=sicp.plt&owner=soegaard下载然后在DrScheme中选择本地包安装。
另外SICP上使用的两个painter(wave和rogers)没有在这个包里提供,取而代之是diagonal-shading和einstein。
下面这个程序显示了一个简单的分形图像:
#lang scheme
(require (planet "sicp.ss" ("soegaard" "sicp.plt" 2 1)))
(define (right-split painter n)
(if (= n 0)
painter
(let ((smaller (right-split painter (- n 1))))
(beside painter (below smaller smaller)))))
(define (up-split painter n)
(if (= n 0)
painter
(let ((smaller (up-split painter (- n 1))))
(below painter (beside smaller smaller)))))
(define (corner-split painter n)
(if (= n 0)
painter
(let ((up (up-split painter (- n 1)))
(right (right-split painter (- n 1))))
(let ((top-left (beside up up))
(bottom-right (below right right))
(corner (corner-split painter (- n 1))))
(beside (below painter top-left)
(below bottom-right corner))))))
(paint (corner-split diagonal-shading 4))
程序输出:
优化gitk的字体显示
gitk是用Tcl/Tk写的工具,默认使用Tk 8.4,不支持抗锯齿,因此字体显示很难看。好在Tk 8.5支持了部分抗锯齿字体,修改gitk使用Tk 8.5后显示效果会好一点。
以Ubuntu为例,安装tk8.5包后,编辑/usr/bin/gitk文件,把开头调用wish的那行
exec /usr/bin/wish "$0" -- "$@"
改成
exec /usr/bin/wish8.5 "$0" -- "$@"
这样就能在gitk中开启抗锯齿了,虽然效果还不是很好。另外qgit也是一个不错的选择。
WPtouch
这是一个让wordpress对移动设备更友好的插件,下载地址在http://wordpress.org/extend/plugins/wptouch/,当然也可以在wordpress后台查找wptouch并安装。
在iPod Touch上的效果图
Linear Page Table: 更方便地访问页表
Linear page table又叫virtual page table,是一种方便虚拟机监控器(VMM)/操作系统(OS)/应用程序访问页表的技巧。Xen、64位Linux内核、JOS操作系统中都用到了这种技巧。这里以x86_32的虚拟内存管理为例,简单介绍一下它的实现和使用,如有错误敬请指出。
一般情况下,如果OS需要访问某个页表,需要将它映射到自己的虚拟空间中,然后再访问。这样带来两个问题,一是访问比较繁琐,需要临时的页映射;二是对于Exokernel这种fork等行为都是在用户态程序实现的系统,可能会增加一下安全上的问题。因为用户程序在fork的时候需要访问自己的页表,而这时候除非操作系统提供另一些权限控制更精确的系统调用,否则就很难让不可信的应用程序访问自己的页表且不做有害的改动。
Linear page table很好的解决了这两个问题。它的实现很简单,只需要在页目录中增加一项VPT,和一般的页目录项不同的是,这个VPT指向的是页目录本身。
这样带来了什么好处呢?借用一下MIT 6.828课件上的图片来更好的说明这个问题

增加了VPT后,通常的物理地址->虚拟地址的转换还是没变。和之前唯一的不同在于虚拟地址的页目录索引号(PDX)为之前设置的VPT的时候。
举个例子来说,假如现在要访问的虚拟地址是(VPT << 22) | (VPT << 12),即这里的PDX和PTX都等于VPT的时候,整个转换过程是怎么样的呢(假设TLB miss的情况)?首先根据cr3中的物理地址,硬件开始查找页目录中的第VPT项,然后根据这一项中的物理地址,找到了下一级“页表”。注意这时候硬件以为自己得到的页表地址,实际上访问的还是页目录本身。同样,在这个“页表”中找到第VPT项指出去的最终页,得到了最终页的物理地址。因为PTX还是等于VPT,所以最后得到的物理地址还是页目录的。
也就是说,通常的页表访问的顺序是 CR3->页目录->页表->最终页,现在访问这个特殊地址的过程则成了 CR3->页目录->页目录->页目录,通过VPT这一项在页目录上绕了两圈后返回。
接下来,再来看看如何通过这个机制来访问某个页表,假如现在要访问第i个页目录项指向的页表上的第j项,那么我们应该构造这样一个特殊地址:
(VPT << 22) | (i << 12) | (j * 4)
即PDX=VPT, PTX=i, offset=j*4。通过这个地址就能得到需要的页表项了,另外由于(i << 12) | (j * 4) = (i * 1024 + j) * 4,定义vpn为虚拟页的编号,vpn = i * 1024 + j,则这个地址可以转换为
(VPT << 22) + vpn * 4
在JOS中,就是把vpt定义为一个uint32_t的数组,然后vpt[vpn]就是第vpn个虚拟页的页表项了。前面提到的另一个问题,如果要让用户以只读权限访问页表,又应该怎么做呢?很简单,在页目录中为用户设置另一个只读项,指向页目录自己就行了。
gcc中设置特定代码块的优化级别
今天碰到一个gcc优化相关的问题,为了让一个页变成脏页(页表中dirty位被置上),需要执行下面这段代码:
uint32_t *page; // ... page[0] = page[0];
最后一行代码很有可能被gcc优化掉,因为这段代码看起来没有任何实际的作用。那么如何防止gcc对这段代码做优化呢?
设置gcc编译时优化级别为-O0肯定是不合适的,这样对程序性能影响会比较大。stackoverflow上的Dietrich Epp给出了一个强制类型转换的方案:
((unsigned char volatile *)page)[0] = page[0];
通过volatile关键字禁止gcc的优化,和我之前采用的方法类似。
Plow同学给出了另一个利用gcc 4.4特性的方法:
#pragma GCC push_options
#pragma GCC optimize ("O0")
your code
#pragma GCC pop_options
这里用到了gcc 4.4的特性Function Specific Option Pragmas,在特定代码前保存当前的编译选项,然后对特定的代码使用O0优化级别,最后再恢复之前保存的编译选项。
俺觉得这个特性有些场合下挺好用的,在这里分享下,虽然因为编译器版本问题最后我还是用了前面一种方法。
ecb和cscope的结合使用
前几天试用了下ECB,非常喜欢它的定义列表和文件浏览历史的功能。但是却发现了另外一个问题:使用ECB之前我把整个窗口分成左右两块,左边是代码,右边是cscope的查找结果,现在开启ECB之后就不能再切一块窗口给cscope用了。
感谢stackoverflow上的sanitynic,给出了自定义ECB窗口的参考。现在俺终于能把cscope窗口绑定到屏幕左下角啦。
自定义ECB layout其实也挺方便的,上图对应的配置为
(ecb-layout-define "my-cscope-layout" left nil
(ecb-set-methods-buffer)
(ecb-split-ver 0.5 t)
(other-window 1)
(ecb-set-history-buffer)
(ecb-split-ver 0.25 t)
(other-window 1)
(ecb-set-cscope-buffer))
(defecb-window-dedicator ecb-set-cscope-buffer " *ECB cscope-buf*"
(switch-to-buffer "*cscope*"))
(setq ecb-layout-name "my-cscope-layout")
;; Disable buckets so that history buffer can display more entries
(setq ecb-history-make-buckets 'never)
my-cscope-layout这个layout左边窗口分为三部分,最上面的函数列表占一半高度,中间为历史文件列表,下面为cscope的查找结果,它们各占四分之一的高度。
另外再简单提下cscope插件的安装和配置,使用前需确认当前系统已经安装了cscope,另外要有cscope-indexer这个脚本。在cscope/contrib目录下找到一个xcscope.el,复制到Emacs的插件目录中,并在Emacs初始化文件中加入
(require 'xcscope)
即可。某些发行版的包里面似乎没有cscope-indexer和xcscope.el,直接从网上下一个好了。
几个常用的快捷键:
C-c s I 建立cscope索引
C-c s a 设置搜索目录
C-c s d 查找定义
C-c s s 查找字符串
C-c s c 查找调用者
C-c s n 下一个查找结果
C-c s p 上一个查找结果
更多的快捷键可以通过C-h b在cscope-minor-mode区找到。



