麒麟操作系统内核同其他操作系统内核的相似性分析(2)
2007-09-29 12:32:18 来源:WEB开发网和刚才一样。左边来自FreeBSD 5.3的代码,右边来自Kylin 2.0的代码(但是为了举例,函数前后顺序稍作调整)。在两段代码实际上非常相似,但是由于代码前后的顺序不同,导致只有一个代码块sigcode()可以匹配的上,相似度仅为47.6%。
针对这类情况,我的解决办法是将代码块按照标号/函数名进行排序。经过排序,上述代码段比对将变为:
begin(): begin():
mov {Address},%eax mov {Address},%eax
lea {Offset}(%eax),%esp lea {Offset}(%eax),%esp
xor %ebp,%ebp xor %ebp,%ebp
mov {Address},%esi mov {Address},%esi
mov %esi,{Offset}(%eax) mov %esi,{Offset}(%eax)
pushl{Address} pushl{Address}
call <init386> call <init386>
add {Number},%esp add {Number},%esp
call <mi_startup> call <mi_startup>
add {Number},%esp add {Number},%esp
sigcode(): sigcode():
call *{Offset}(%esp) call *{Offset}(%esp)
lea {Offset}(%esp),%eax lea {Offset}(%esp),%eax
push %eax push %eax
testl{Number},{Offset}(%eax) testl{Number},{Offset}(%eax)
jne <sigcode+{Offset}> jne <sigcode+{Offset}>
movl {Offset}(%eax),%gs | movw {Offset}(%eax),%gs
mov {Number},%eax mov {Number},%eax
push %eax push %eax
int {Number} int {Number}
jmp <sigcode+{Offset}> jmp <sigcode+{Offset}>
nop nop
现在,这两段代码只有一行不同,相似度也就变为了95.2%。
但是这种依赖于标号/函数名排序的做法有效的程度实际上是有局限的。首先,并不是所有函数名都会保存于可执行代码中,至少inline函数就会在编译时扩展到调用的语句位置,还有一些函数在编译器优化时被优化掉。所以,不同的编译器,或者不同的编译参数都有可能导致某些函数名在执行体中消失,从而导致排序失败。另外,不是所有的可执行体都会保留函数名,对于Windows的PE文件来说,如果不用debug模式编译的话,除了导出函数外,其他的函数名一般不会保存在执行文件中,
在我用同样的方法分析Windows文件内核的时候出现了比较严重的问题,即使血亲关系很近的两个版本的Windows内核,无论排序或者不排序,相似度都非常的低,对于这类PE文件根本无法反映出相似度。所以,在最终的分析中,我剔出了原本列在比较目标中的XP内核。
因为ELF的这个特点,这次我的分析将只对使用ELF的文件格式的内核进行分析。
2.1.4 比较
在原本的计划中,我曾考虑采用常用于字符串相似度比较的编辑距离(Levenshtein Distance)算法[5]。这个算法的含义,是计算两字符串之间的距离有多远。编辑距离是指,从原字符串变化到目的字符串最少需要进行多少次包括添加、修改、删除在内的操作。举例而言:
如果计算kitten和sitting之间的编辑距离,我们最少需要进行3次操作,
1、 kitten -> sitten (修改s->k)
2、 sitten -> sittin (修改i->e)
3、 sittin -> sitting (增加 g)
因此,kitten和sitting之间的编辑距离是3。这个算法是俄国的科学家Vladimir Levenshtein在1965年提出的。这个算法主要是应用在DNA分析、拼字检查、语音辨识和抄袭侦测上。[6]
但是这个算法的计算复杂度太高,是O(nm)的复杂度。对于平均大小在100万行的操作系统内核源代码来说,就是万亿次级别的比对。对于普通的计算机,平均每两个内核的比对就要花去数小时。而此次参与比对的内核将有20个左右,完成一个比较完整的比对过程将会出现几百次比对,那么就要花数个月的时间,不太现实。
因此,这次我采用的是简化的比对办法。通过diff命令来比较两个内核源文件的差异。Diff使用的是一种更聪明的计算方法,虽然最坏情况差不太多,但是大多数情况下具有较高的性能[7]。
通过diff给出的结果可以得知第一个文件增改多少行代码后,就可以变为第二个文件。diff的算法和其实对于修改我们并不介意,我们只关心增加多少行代码就可以变为第二个文件。
假设内核A的代码有a行,内核B的代码有b行。而从内核A变化到内核B需要添加c行,由内核B变化到内核A需要d行。由此,我们可以得知,在内核A中,存在有b-c行代码和内核B是相同的。因此,我们将内核A中所存在的内核B的代码行数除以内核A自身的代码行数定义为两个内核的相似度,即
A->B的相似度 = (b-c) / a |
由公式可知,A->B和B->A的计算结果将有可能不同。因为我们判断相似度的原因不单纯是看二者的差异,更重要的是看他们之间的血亲关系的远近,因此我们取双向转换中的最大值,作为A<->B之间的相似度。
A-B间的相似度 = max( (b-c) / a, (a-d) / b ) |
2.1.5 小结
分析方法还有待完善,可以看出,二进制可执行文件的分析依旧还有很大的难度,很容易受到各种外围环境的变化而导致相似度大幅下降,而无法反映真实的相似度。因此对于那些刻意隐瞒相关性的二进制可执行文件来说还是比较容易的逃过这种分析方法的检测。
但是,分析方法的缺陷却只会导致相似度的下降,而不会导致差异很大的代码产生很高的相似度。因此,我这次采用这次分析方法主要就是确定麒麟操作系统内核与其他操作系统之间的相似度的下限,并从数据中试图分析出他们的血亲关系。
2.2 多种操作系统内核相似度比较
为了比对尽量客观,这次参加比对的操作系统内核包括,FreeBSD, NetBSD, OpenBSD, Linux, Solaris和银河麒麟操作系统,共6个操作系统,22个内核。
原计划中,要将Mac OS X中的Darwin 8.0.1, 7.0.1拿来比对,可是由于其文件格式是Mach-O的,而我又没有支持Mach-O的objdump,所以暂时无法参与比对。另外,原计划曾打算拿相关性更差的Windows NT系列的系统内核来进行比对,可是由于之前所说的PE格式问题而导致的相似度没有参考价值,所以,这次也没有将其列入最终的比对。
为了确认比对的有效性,我们将先对FreeBSD, NetBSD和OpenBSD之间的比对来审视其比对效果。
2.2.1 FreeBSD间不同版本内核相似度分析
FreeBSD是一种Unix衍生操作系统,由BSD, 386BSD和4.4BSD发展而来的Unix的一个重要分支。而BSD的全称是“伯克利软件发布”,是美国加州大学伯克利分校计算机系统研究组所制作的一套包括内核在内完整的操作系统,起源于AT&T的Unix V6,但是后来由于与AT&T的版权纠纷问题,彻底的删除了AT&T在BSD内核中的代码,大约占10%左右。也正是这场官司,而给了Linux得以飞速发展的机遇。在版权问题解决后,BSD借助其高质量的代码,在开放源代码的世界里有了飞速的发展,分别产生了3个重要的分支,FreeBSD, OpenBSD, NetBSD。FreeBSD发展至今,已经成为公认的相当可靠和健壮的操作系统。[9,10]
因为焦点集中在FreeBSD身上,而且特别是5.x和6.x的系统上,因此这回参与比较的FreeBSD的内核版本较多,分别有FreeBSD 5.0, 5.1, 5.2, 5.2.1, 5.3, 5.4, 5.5 beta 4和6.0。
原始内核目标内核 | 汇编行数 | freebsd_5.0 | freebsd_5.1 | freebsd_5.2 | freebsd_5.2.1 | freebsd_5.3 | freebsd_5.4 | freebsd_5.5.b4 | freebsd_6.0 |
freebsd_5.0 | 913,353 | - | 697423 | 712361 | 714811 | 969174 | 1001579 | 1016967 | 1146371 |
freebsd_5.1 | 958,699 | 652223 | - | 682433 | 681769 | 1029692 | 1002484 | 1034263 | 1112613 |
freebsd_5.2 | 1,048,418 | 572280 | 604662 | - | 3252 | 817759 | 865407 | 850969 | 1124929 |
freebsd_5.2.1 | 1,049,592 | 493098 | 607199 | 2078 | - | 816434 | 870479 | 881654 | 1124304 |
freebsd_5.3 | 1,161,593 | 742327 | 762747 | 705826 | 724190 | - | 35581 | 78219 | 977778 |
freebsd_5.4 | 1,174,287 | 744511 | 811979 | 732332 | 733290 | 22906 | - | 25985 | 901307 |
freebsd_5.5.b4 | 1,187,447 | 741616 | 783626 | 735617 | 734211 | 40295 | 12975 | - | 358820 |
freebsd_6.0 | 1,271,723 | 791490 | 805184 | 905427 | 907359 | 753022 | 766311 | 622653 | - |
上表中所列出的是FreeBSD的各个版本之间的差异行数,即前面所说到的c。左边列出的是原始内核,顶端列出的是目的内核。左边给出了原始内核的行数。
差异行数和相似度具有相同的含义,毕竟相似度也是通过差异行数计算出来的,因此在以后的叙述中,我们将只列出相似度对比的表格。
下面就是FreeBSD各个版本之间的内核相似度比较。
原始内核目的内核 | 汇编行数 | freebsd_5.0 | freebsd_5.1 | freebsd_5.2 | freebsd_5.2.1 | freebsd_5.3 | freebsd_5.4 | freebsd_5.5.b4 | freebsd_6.0 |
freebsd_5.0 | 913,353 | - | 28.61% | 36.79% | 36.65% | 21.07% | 18.91% | 18.67% | 13.72% |
freebsd_5.1 | 958,699 | 27.24% | - | 38.18% | 38.37% | 13.76% | 17.92% | 15.98% | 16.60% |
freebsd_5.2 | 1,048,418 | 32.53% | 33.77% | - | 99.80% | 32.80% | 29.46% | 32.09% | 14.00% |
freebsd_5.2.1 | 1,049,592 | 40.04% | 33.49% | 99.69% | - | 32.89% | 28.95% | 29.13% | 14.05% |
freebsd_5.3 | 1,161,593 | 14.72% | 16.87% | 29.49% | 28.01% | - | 98.03% | 95.49% | 25.31% |
freebsd_5.4 | 1,174,287 | 14.38% | 12.49% | 26.92% | 26.94% | 96.97% | - | 98.91% | 31.54% |
freebsd_5.5.b4 | 1,187,447 | 14.46% | 14.74% | 26.34% | 26.56% | 94.43% | 97.80% | - | 76.88% |
freebsd_6.0 | 1,271,723 | 9.58% | 12.07% | 11.24% | 11.18% | 32.13% | 32.08% | 44.41% | - |
由于操作系统是逐步发展而来的,因此从5.0-5.5 beta 4都是在前者的基础上,修补前者中出现的bug,并增添新的特性而产生的。我们可以从这个FreeBSD的相似度表中看到这种传承关系。我们可以看出,基本上是越靠近当前版本相似度越高,而离当前版本越远相似度就越低。其中有一些特例的情况,5.1和5.2似乎比较特殊,可能是由于某种原因在5.1中策略有所调整,而在5.2.1或者5.3中又逐渐的恢复回来。
5.2.1和5.2的相似度达到了99.80%,这是正常的,由于在5.2之后,有一系列关键服务,如wu-ftp, OpenSSH和XFree86等的缓冲区溢出的漏洞被揭露出来,致使FreeBSD出于安全考虑而在5.2发布后仅一个月多的时间就立即发布了新的版本,因此5.2.1和5.2的内核上的差异实际上很低,主要是在外围程序上修补了很多安全漏洞[15]。但是出乎我意料的,我没想到在很容易被干扰而降低相似度的情况下,竟然可以达到这么高的相似度,说明这种分析方法对于代码相似度分析在一般情况下是有效的。究其原因,应该是因为FreeBSD的前后传承关系,所以不同的版本虽然代码有不少变动,但是默认的内核配置文件变动不大,因此才有可能出现这种比较高的相似度。另外我们也可以看出,FreeBSD在5.3以后,包括5.4和5.5的内核变动量都不大,由此可以感觉到5.x的系统可能已经基本成熟。
FreeBSD 6.0与5.3以前版本的相似度都不太高,主要是因为6.0已经是和5.x属于不同的代码分支,相对于5.x来说代码有了较大的变化。而另一方面,6.0的分支是在5.4版本发布后建立的,因此,6.0的内核与之前内核的相似度偏低,却和FreeBSD 5.3, 5.4, 5.5 beta 4的相似度较高。
总体上,基本符合版本相近,代码相近的客观事实,分析方法是成功的。
2.2.2 FreeBSD、NetBSD和OpenBSD的内核相似度分析
NetBSD和FreeBSD一样,也是从美国加州伯克利大学的4.3BSD和386BSD衍生出来的Unix操作系统。它以设计简洁、代码规范和高可移植性的特点而著称。从服务器到嵌入式设备都有它的身影[10]。而OpenBSD则是从NetBSD 1.0衍生而来的[11]。因此OpenBSD和NetBSD相对FreeBSD而言具有更近的血亲关系。
原始内核目标内核 | 汇编行数 | freebsd_5.3 | freebsd_6.0 | netbsd_2.1 | netbsd_3.0 | openbsd_3.7 | openbsd_3.8 |
freebsd_5.3 | 1,161,593 | - | 25.31% | 16.55% | 16.61% | 16.78% | 16.74% |
freebsd_6.0 | 1,271,723 | 32.13% | - | 16.65% | 16.22% | 15.89% | 16.24% |
netbsd_2.1 | 1,503,585 | 13.08% | 13.68% | - | 53.35% | 17.53% | 16.72% |
netbsd_3.0 | 1,616,659 | 11.76% | 12.65% | 24.40% | - | 13.96% | 14.61% |
openbsd_3.7 | 1,228,137 | 15.60% | 16.54% | 20.77% | 18.44% | - | 88.89% |
openbsd_3.8 | 1,260,707 | 15.26% | 16.52% | 20.65% | 18.47% | 84.56% | - |
从这个数据表中,我们可以看出计算出来的数据可以反映这种已知的血亲关系。FreeBSD 与NetBSD和OpenBSD的相似度基本在16.5%左右,而NetBSD与OpenBSD的相似度则相对较高。NetBSD 2.1和OpenBSD的相似度为20.65% ~ 20.77%,NetBSD 3.0和OpenBSD的相似度也有18.44%,都高于FreeBSD与NetBSD和OpenBSD的相似度。虽然数值差别并不大,但是具有规律性,基本上也是客观地反映了真实的情况的。
2.2.3 Kylin与FreeBSD, OpenBSD, NetBSD, Linux, Solaris的内核相似度分析
现在我们开始对银河麒麟操作系统进行相似度比对。参与比对的开放源代码操作系统内核有FreeBSD 5.0, FreeBSD 5.2, FreeBSD 6.0, NetBSD 2.1, NetBSD 3.0, OpenBSD 3.7, OpenBSD 3.8, Linux 2.6.16, OpenSolaris 5.11,共9个内核。
除了刚才介绍过的FreeBSD, NetBSD和OpenBSD外,还增加了Linux和Solaris。Linux是Linus基本上从零起步写出来的操作系统,虽然参考了Minix和Unix的实现,但是基本上没有大量的使用任何其它Unix发布的代码[12]。因此,虽然Linux也是一个类Unix系统,然而由于是独立开发的,所以它和前面所列出的BSD衍生操作系统和后面将要提到的Solaris的血亲关系比较远。
从历史的角度来讲,Solaris和BSD很有渊源。在80年代,Sun基于BSD Unix发布了自己版本的UNIX,SunOS。而在90年代初,由于受到AT&T与BSD的官司影响,Sun将其SunOS 4替换为与AT&T共同开发的UNIX System V Release 4的一个版本,并更名为Solaris 2[13]。在2004年早期,Sun开始了一项计划,名为OpenSolaris,将Solaris逐步的放到开放源代码社区中。并在2005年的6月中旬开放了大部分的Solaris源代码[14]。现在已经有一些基于OpenSolaris源代码的操作系统,这次采用的就是一个名为Belenix的Live CD发布版本0.4.2种的内核,uname显示的是SunOS 5.11。
此次引入Solaris来进行比对,也是从一方面希望能够从分析数据中客观地反映出Solaris,相比Linux而言,和BSD有更近的血亲关系。
关于参与比对的麒麟操作系统内核,我们将从发布版本中获得的四个版本的内核拿来进行比对,Kylin 2.0.0, Kylin 2.0.14, Kylin 2.0.21, Kylin 2.0.21 lsb。需要说明的是,官方网站上发布了2.0.14和2.0.18。其中Kylin 2.0.0是来自于麒麟系统安装盘的引导部分,通过uname –a显示出的版本是2.0.0。Kylin 2.0.21虽然是官方网站给出的光盘镜像的版本号,可是启动后,通过uname –a得到的版本号却是2.0.18,这点可能是麒麟开发组在版本管理上的混乱所导致的。
下面就是分析后得到的数据表;
原始内核目标内核 | 汇编行数 | fb 5.0 | fb 5.2 | fb 6.0 | k 2-0 | k 2-14 | k 2-21 | k 2-21 lsb | l 2.6.16 | nb 2.1 | nb 3.0 | ob 3.7 | ob 3.8 | os 5.11 |
freebsd_5.0 | 913,353 | - | 36.79% | 13.72% | 40.53% | 30.43% | 30.43% | 40.53% | 6.46% | 11.24% | 11.37% | 10.91% | 10.87% | 5.02% |
freebsd_5.2 | 1,048,418 | 32.53% | - | 14.00% | 48.18% | 34.02% | 34.02% | 48.18% | 5.75% | 11.02% | 10.91% | 10.95% | 10.94% | 4.55% |
freebsd_6.0 | 1,271,723 | 9.58% | 11.24% | - | 12.63% | 13.19% | 13.14% | 12.63% | 6.61% | 16.65% | 16.22% | 15.89% | 16.24% | 5.21% |
kylin_2.0.0 | 1,120,079 | 31.92% | 41.94% | 14.55% | - | 91.06% | 91.06% | 100.00% | 5.38% | 10.83% | 10.31% | 10.20% | 10.35% | 4.35% |
kylin_2.0.14 | 1,190,443 | 23.55% | 29.98% | 24.61% | 85.60% | - | 100.00% | 85.60% | 5.04% | 10.63% | 10.64% | 10.30% | 10.44% | 4.06% |
kylin_2.0.21 | 1,190,562 | 23.52% | 29.95% | 21.04% | 85.57% | 99.99% | - | 85.57% | 5.03% | 10.72% | 10.63% | 10.29% | 10.44% | 4.06% |
kylin_2.0.21_lsb | 1,120,079 | 31.92% | 41.94% | 14.55% | 100.00% | 91.06% | 91.06% | - | 5.38% | 10.83% | 10.31% | 10.20% | 10.35% | 4.35% |
linux_2.6.16 | 666,204 | 9.47% | 9.71% | 13.13% | 5.38% | 5.38% | 5.39% | 5.38% | - | 11.89% | 12.09% | 12.21% | 12.07% | 6.30% |
netbsd_2.1 | 1,503,585 | 6.49% | 7.42% | 13.68% | 8.06% | 8.18% | 7.97% | 8.06% | 5.20% | - | 53.35% | 17.53% | 16.72% | 4.10% |
netbsd_3.0 | 1,616,659 | 6.19% | 7.11% | 12.65% | 7.54% | 7.90% | 7.89% | 7.54% | 4.98% | 24.40% | - | 13.96% | 14.61% | 3.73% |
openbsd_3.7 | 1,228,137 | 7.95% | 9.58% | 16.54% | 9.27% | 9.97% | 9.71% | 9.27% | 6.43% | 20.77% | 18.44% | - | 88.89% | 5.20% |
openbsd_3.8 | 1,260,707 | 7.72% | 8.84% | 16.52% | 8.88% | 9.53% | 9.52% | 8.88% | 6.29% | 20.65% | 18.47% | 84.56% | - | 5.00% |
OpenSolaris_5.11 | 396,534 | 11.87% | 12.00% | 16.84% | 12.50% | 12.46% | 12.46% | 12.50% | 13.37% | 15.90% | 15.82% | 16.66% | 16.49% | - |
从数据表中反映出来的血亲关系来看,Kylin 2.0的内核和FreeBSD 5.x的血亲关系最近,在30.43%-48.18%之间,和FreeBSD 6.0的关系稍远,在14.55%-24.61%之间。而和其他的操作系统关系都比较疏远。和NetBSD、OpenBSD的相似度在10%左右,而同Linux的相似度只有5.38%,
与OpenSolaris的相似度虽然比NetBSD和OpenBSD还高,达到了12.50%,但是这个绝对数值不应该视为OpenSolaris与麒麟的关系更接近。因为,OpenSolaris的代码行数仅有396,534行,仅相当于NetBSD的1/4。在相似度计算公式中,分母较小,容易致使结果的相似度较大,因此不应该说麒麟内核和Solaris更相似,应该说麒麟内核同Solaris,NetBSD和OpenBSD的相似度相当。
另外,我们可以注意到OpenSolaris和FreeBSD 6, NetBSD, OpenBSD的相似度略高于其他系统内核,但是都比较低。我们从这个不大的差异中可以感觉到Solaris同BSD的或近或远的关系。其实虽然Solaris代码已经不是基于BSD构建的Unix了,但是由于SVR4中也吸收了BSD的部分代码,因此Solaris在相似度上,还是客观的体现了和BSD偏近的关系。
从数据中我们还可以看到麒麟的这几个内核的相似度很高。Kylin 2.0.0和Kylin 2.0.21 lsb的相似度是100%,Kylin 2.0.14和2.0.21的相似度也是接近100.00%。其中的具体差异行数如下:
原始内核目标内核 | 汇编行数 | kylin_2.0.0 | kylin_2.0.14 | kylin_2.0.21 | kylin_2.0.21_lsb |
kylin_2.0.0 | 1,120,079 | - | 170,553 | 170,641 | 0 |
kylin_2.0.14 | 1,190,443 | 101,029 | - | 145 | 101,029 |
kylin_2.0.21 | 1,190,562 | 101,328 | 26 | - | 101,328 |
kylin_2.0.21_lsb | 1,120,079 | 0 | 170,553 | 170,641 | - |
我们可以看出其实光盘引导用的内核同安装后的/boot/kernel_lsb/ 目录下的内核是相同的。而Kylin 2.0.21和2.0.14相比仅仅修改了几十行代码而已,变动很小,从数值上看,变动主要是增加了一些代码。而从2.0.0到2.0.14变动稍大一些。
在后面的分析中,我们没必要对很相似的内核一起进行重复分析,因此,将基于Kylin 2.0.0和Kylin 2.0.21这两个麒麟内核进行分析。
从现在的结果我们已经可以看出麒麟和FreeBSD的5.x版本有很近的血亲关系,最高达到了与FreeBSD 5.2的48.18%的相似度,这种相似性甚至已经明显超过了和FreeBSD具有很近的同源关系的NetBSD, OpenBSD。即使是最初基于NetBSD的代码而建立的OpenBSD,在与其渊源极深的NetBSD比较时,最高也不过20.77%的相似度。
至此,我们基本上可以确定麒麟操作系统内核中有大量的FreeBSD 5.x 的源代码。为了进一步确定麒麟操作系统和FreeBSD的相似性到底有多少,我们接下来将针对Kylin内核和FreeBSD的内核作比较。
2.2.4 Kylin与FreeBSD各个版本间的内核相似度分析
这次我们针对Kylin和FreeBSD这两个操作系统的内核进行相似度的比对。参与比对的将包括Kylin的2个典型内核和FreeBSD 5.x全系列内核,具体是Kylin 2.0.0, Kylin 2.0.21, FreeBSD 5.0, FreeBSD 5.1, FreeBSD 5.2, FreeBSD 5.2.1, FreeBSD 5.3, FreeBSD 5.4, FreeBSD 5.5 beta4。
原始内核目标内核 | 汇编行数 | fb 5.0 | fb 5.1 | fb 5.2 | fb 5.2.1 | fb 5.3 | fb 5.4 | fb 5.5.b4 | kylin_2.0.0 | kylin_2.0.21 |
freebsd_5.0 | 913,353 | - | 28.61% | 36.79% | 36.65% | 21.07% | 18.91% | 18.67% | 40.53% | 30.43% |
freebsd_5.1 | 958,699 | 27.24% | - | 38.18% | 38.37% | 13.76% | 17.92% | 15.98% | 28.94% | 26.11% |
freebsd_5.2 | 1,048,418 | 32.53% | 33.77% | - | 99.80% | 32.80% | 29.46% | 32.09% | 48.18% | 34.02% |
freebsd_5.2.1 | 1,049,592 | 40.04% | 33.49% | 99.69% | - | 32.89% | 28.95% | 29.13% | 48.15% | 34.47% |
freebsd_5.3 | 1,161,593 | 14.72% | 16.87% | 29.49% | 28.01% | - | 98.03% | 95.49% | 57.94% | 50.48% |
freebsd_5.4 | 1,174,287 | 14.38% | 12.49% | 26.92% | 26.94% | 96.97% | - | 98.91% | 56.24% | 51.88% |
freebsd_5.5.b4 | 1,187,447 | 14.46% | 14.74% | 26.34% | 26.56% | 94.43% | 97.80% | - | 39.47% | 50.16% |
kylin_2.0.0 | 1,120,079 | 31.92% | 20.99% | 41.94% | 41.97% | 60.26% | 59.04% | 42.59% | - | 91.06% |
kylin_2.0.21 | 1,190,562 | 23.52% | 16.68% | 29.95% | 29.93% | 52.04% | 50.87% | 50.35% | 85.57% | - |
Kylin 2.0.0和FreeBSD 5.3的相似度达到了60.26%,与FreeBSD也达到了59.04%的相似度。我们可以注意到,即使是FreeBSD的5.0 – 5.3版本之间的相似度也没有超过40.04%。5.3、5.4和5.5的高相似度前面已经解释了,应该是5.x系列的内核趋于稳定了,因此修补较多增添新的特性较少所致。
按照麒麟开发人员的解释,麒麟操作系统内核服务层使用的是FreeBSD 5.0的代码。可是,从我们的分析数据可以明显看出,Kylin 2.0.0和FreeBSD 5.0的相似度有40.53%,而与FreeBSD 5.3的相似度达到了60.26%,因此我们有理由相信麒麟使用的是FreeBSD 5.3或者5.4的代码。
当然,我们可以理解为这是开发人员的声明[3]中的一个笔误,他想说FreeBSD 5.x,而不是FreeBSD 5.0。但是,另一方面,如果说仅仅是外围服务层使用的是FreeBSD的话,那么麒麟与FreeBSD 5.3的相似度不应该高过FreeBSD自家不同版本之间的相似度。既然麒麟2.0.0内核与FreeBSD 5.3达到了60.26%的相似度,那么我们可以肯定地说,麒麟操作系统内核源代码至少有一半以上使用的是FreeBSD 5.3的源代码。
2.2.5 Kylin与FreeBSD 5.3, 5.4不同编译配置下的内核相似度分析
为了能够进一步了解麒麟操作系统内核同FreeBSD内核的相似度,接下来,我们将对FreeBSD 5.3和5.4在不变动任何源代码的情况下,重新进行编译,增加一些在Kylin 2.0中出现的模块。这样做的是希望在不修改FreeBSD代码的前提下,看看不同的编译配置是否能够使得FreeBSD与麒麟操作系统内核的相似度更高。
这次,我们在FreeBSD的内核编译配置文件GENERIC中增加如下三个选项:
options COMPAT_LINUX
options LINPROCFS
device sound
因为麒麟内核的一个亮点就是可以做到和Linux的二进制兼容,所以这主要是增加FreeBSD的Linux兼容性。其实事实上FreeBSD已经可以很好的兼容Linux二进制代码了,按照FreeBSD的内核设计,它完全可以同时支持多种ABI(应用程序二进制接口),并支持同时运行不同系统可执行文件。通过加载COMPAT_LINUX模块,FreeBSD就已经做到了和Linux可执行文件间的二进制兼容,可以执行大部分Linux程序[17]。
而LINPROCFS模块则是模拟了Linux的进程文件系统,也就是我们在Linux下见到的/proc目录,很多Linux的程序需要用到这个系统,因此加载这个模块后,可以让Linux更好的在FreeBSD上运行[18]。
最后增加了sound设备,因为我们通过分析,发现Kylin内核里面加载了各种声卡驱动。需要提及的是,麒麟系统启动比较慢,有可能也是因为编译了过多的不必要的模块进内核所导致的。
原始内核目标内核 | 汇编行数 | freebsd_5.3 | freebsd_5.3_1 | freebsd_5.4 | freebsd_5.4_1 | kylin_2.0.0 | kylin_2.0.21 |
freebsd_5.3 | 1,161,593 | - | 97.47% | 98.03% | 73.12% | 57.94% | 50.48% |
freebsd_5.3_1 | 1,198,401 | 93.78% | - | 80.82% | 98.07% | 56.49% | 56.64% |
freebsd_5.4 | 1,174,287 | 96.97% | 94.55% | - | 96.58% | 56.24% | 51.88% |
freebsd_5.4_1 | 1,210,928 | 91.68% | 97.05% | 94.56% | - | 55.66% | 55.29% |
kylin_2.0.0 | 1,120,079 | 60.26% | 61.19% | 59.04% | 60.17% | - | 91.06% |
kylin_2.0.21 | 1,190,562 | 52.04% | 57.02% | 50.87% | 54.38% | 85.57% | - |
通过比对,我们可以看到,随着增加了Linux兼容性和声卡驱动模块后,Kylin 2.0与FreeBSD的5.3、5.4的相似度均有小幅提高。其中Kylin 2.0.0内核和FreeBSD 5.3的相似度为61.19%。我们有理由相信,随着更多合适的内核模块的加入,Kylin 2.0和FreeBSD的内核相似度有可能会进一步提高。
实际上,经过内核模块的比对,我们也发现了Kylin内核中出现了很多疑似是FreeBSD的其他模块,但是由于每次编译和比对要花费大量的时间,因此,我没有能够一一的加以测试。如果有兴趣的朋友可以进一步测试麒麟系统内核与不同的内核配置文件之间的相似度。
2.2.6 同一份FreeBSD 5.3代码,不同编译配置下的内核相似度分析
接下来,我们将在不修改任何FreeBSD 5.3内核源代码的前提下,尝试用不同的内核编译配置文件对FreeBSD 5.3内核进行编译。希望能够通过这样的尝试看出,同一份源代码,在不同配置文件下能够产生最低多低的相似度,换句话说,就是使相似度下降多少百分比。
在测试中,由于编译和比对的时间太慢,所以,我只用3个不同的内核配置文件编译内核,这相对于可能出现的内核数量是一个很小的比例。因此,我不能够得出最低使相似度下降的百分比,但是我能够得出至少可以使相似度下降多少百分比。换句话说,我能够测试出一个相似度可能被降低的范围,但是实际能够降低的范围比这个还要大。
原始内核目标内核 | 汇编行数 | freebsd_5.3 | freebsd_5.3_1 | freebsd_5.3_2 | freebsd_5.3_3 |
freebsd_5.3 | 1,161,593 | - | 97.47% | 72.01% | 71.62% |
freebsd_5.3_1 | 1,198,401 | 93.78% | - | 96.95% | 94.32% |
freebsd_5.3_2 | 1,256,264 | 66.54% | 45.25% | - | 98.11% |
freebsd_5.3_3 | 1,271,301 | 67.10% | 89.43% | 96.95% | - |
我只是很少的修改了几个内核编译选项,我尽量使生成的内核大小不要差异太大。最后选定了3个比较合适的内核配置文件,它们与FreeBSD 5.3默认配置的内核差异从71.62%到97.47%。我们可以看到仅仅将内核配置文件稍加改动,就可以使同一份源代码编译出来的内核文件降低将近30%的相似度。可以预知的趋势是,随着改动的增大,将能够降低更多的相似度。
既然在不变动源代码的情况下,就可以将相似度降低到70%左右,那么仅仅是服务层采用FreeBSD 5.3代码的麒麟系统内核本应该有相当低的相似度,但是分析数据却得到了61.19%高相似度,因此麒麟操作系统内核的自主代码的比例确实是一个比较值得关注的问题。
2.3 结论
经过这次分析,我们比较了麒麟操作系统内核同FreeBSD, NetBSD, OpenBSD, Linux和Solaris内核的相似度。在发现麒麟内核与FreeBSD 5.x有30.43%-48.18%的相似度后,将麒麟内核与FreeBSD 5.x各个版本进行了比对。通过比对看到麒麟系统与FreeBSD 5.3默认内核达到了60.26%的相似度,在经过微小调整内核配置文件后,相似度又得到了进一步的提高,达到了61.19%。在继续调整内核配置文件之后,这个相似度还有进一步提升的空间。
随后,我们在不修改FreeBSD 5.3源代码的情况下,仅仅通过配置文件的变动,就使内核相似度降低到了71.62%,而且还有可能降的更低。
经过分析,我们可以看出麒麟操作系统与FreeBSD 5.3具有血亲关系,而且麒麟系统相对于FreeBSD 5.3的改动,还没有FreeBSD 5.3相对于FreeBSD 5.2.1改动大。从61.19%的相似度,我们可以认定,麒麟操作系统中至少有60%的代码是来自于FreeBSD 5.3的源代码。
由于简单的修改配置文件就可以使相同代码相似度降低到71.62%,而我们最终所得到的61.19%又是仅仅是麒麟内核同FreeBSD 5.3内核相似度的最小值,因此,实际的麒麟操作系统与FreeBSD 5.3在源代码上的相似度很有可能会达到甚至超过90%。
我们可以推测(但不确定)麒麟操作系统内核可能是通过以下几个步骤产生的。
首先是在FreeBSD 5.3内核源代码的基础上进行了部分的修改,可能是为了增强与LSB的兼容性。
然后,开发了Keta内核模块,来实现Kernel-based静态页面web加速器。
最后,以FreeBSD的默认内核配置文件GENERIC为基础,编译了更多的可选模块进内核。这么做的目的可能是为了让内核更具有通用性。
如果确实如此,那么生成的麒麟操作系统内核与其说是一个新的操作系统内核,不如说是被麒麟开发者打了内核补丁的FreeBSD 5.3更为恰当。
三、尾声
我们很难推测麒麟在内核创新的百分比,从已知的数据我们只能说,创新可能只有10%到20%之间。
首先,麒麟的官方说明中提到“主要是由具有Mach 风格的基本内核层、具有BSD 风格的系统服务层和具有Windows 界面风格的桌面环境组成,前两层在核态运行。”采用Mach微内核层+FreeBSD内核服务层的做法是其一个亮点。微内核构架加上一个成熟操作系统的服务层,是目前比较流行的一个做法,Mac OS X就是这样。在对Mac OS X的xnu内核源代码分析过程中,就可以看到其中的两层内核结构,很清晰。不过在我们反汇编麒麟操作系统内核的分析过程中,竟然连一个与Mach相关的内核函数都没有看到,许多关键的模块也基本上和FreeBSD相同而看不到Mach的身影,因此我们对于麒麟操作系统内核是否真如官方说明所宣称的那样,“具有Mach 风格的基本内核层”,还是抱有很大疑问的。
其次,从其对外宣称的一些麒麟的特性上看,绝大多数都是FreeBSD已经成熟的特性。比如,对Linux达到二进制兼容,事实上,FreeBSD很早以前就已经做到了和Linux二进制兼容了,麒麟直接采用了FreeBSD的内核源代码,也自然而然的支持了这个特性,无非是在于LSB兼容上进一步的做了一些工作。麒麟系统的所宣称的安全性应该也是继承于FreeBSD长期积累下来的健壮和稳定性上。
至于内核级的Web服务器Keta,确实是来自国防科技大学的原创,可以从http://openketa.sourceforge.net/ 取得源代码。不过恰恰是这个内核级的Web服务器Keta,降低了麒麟所宣称的安全性,而且也暴露了国防科技大学在安全性上认知的不足。
内核级代码确实可以大幅提高性能,Linux在2.4的时候也曾经采用一个叫做TUX的内核级的Web加速器来进行静态页面的加速处理。不过这个一直是争论的焦点,相当多的安全人士不推荐Linux这样设计,因为内核级代码虽然较快,但是,一旦发生溢出等安全攻击,那么攻击者就可以直接将自己的代码注入内核空间执行,具有系统最高权限,而不受约束。这将给系统安全性带来极大的隐患。另外,内核级的Web加速器也有其自身弱点,由于功能受限,而不能够用动态页面,只能够支持静态页面,所有的动态页面只有转交给另一个真实的Web服务器,比如Apache Web Server,才能够处理。所以对于动态页面,内核的Web加速器并没有什么明显效果。随着Linux 2.6的NPTL引入,用户模式下的多任务性能得到了大幅提高,TUX就很快被移出标准内核了。而FreeBSD的多任务模型和Linux很不同,特别是在FreeBSD 5.x后多任务模型有很大的改进,FreeBSD的用户模式的多任务性能并不是很差,为了这个不大的性能提高,而严重的降低系统安全性,实在是一个不明智的举动。在这种情况下,还宣称自己是高安全性,显得很不伦不类。
而且,从编译进麒麟内核的模块看,我们可以感到很多桌面系统的模块被加到了默认内核中,但是对外却宣称是服务器操作系统。我们都知道,安全的原则是最小化服务原则。多一个服务,多一个驱动,就多引入了一份不稳定和不安全。可是麒麟内核却加载了很多类似于屏幕保护模块、声卡模块、显卡图形驱动模块、ACPI电源管理的内核模块,这些模块对于一个服务器来说,并不是必须的,而且其中很多代码会给系统带来很大的安全隐患。这绝不单单是引导速度变慢的问题,麒麟宣称自己是服务器操作系统,但是在这点的选择上也是很不明智的。
最后需要提及的是,麒麟所安装的软件大部分是GNU的开放源代码软件,这些软件遵循GPL。它要求如果对任何代码进行了修改,必须开放修改过的源代码。但不幸的是,麒麟操作系统虽然修改了部分的代码,却没有开放出修改后的源代码。从这种意义上说,麒麟操作系统对这些GNU的开源软件有侵权嫌疑。
附录A 进一步分析
如果想进一步的分析麒麟与其他操作系统的相似性,也可以从objdump导出的函数名称的相似度来比较。我曾经分析过FreeBSD 5.3内核和麒麟内核objdump出的函数名的差异。FreeBSD 5.3有14101个函数,Kylin 2.0有14399个函数,其中有4个函数出现在了FreeBSD 5.3而没有出现在Kylin 2.0中;有302个函数出现在了Kylin 2.0 objdump的文件里,而没有出现在FreeBSD 5.3的objdump文件里。经过分析,这302个函数中有223都可以在FreeBSD 5.3的源代码里找到,没有被objdump出来有可能是因为编译环境不同。还剩下79个函数可能是麒麟新增的函数,他们是:
+ acd_describe_proc():
+ ad_print_proc():
+ ata_info():
+ ata_proc_print():
+ bus_usb_proc():
+ g_conftxt_class_proc():
+ g_conftxt_geom_proc():
+ g_conftxt_proc():
+ ifa_ifwithnet_packet():
+ kevent_epoll_ctl():
+ kevent_epoll_wait():
+ kqueue_scan_epoll():
+ linprocfs_doata0info():
+ linprocfs_doata1info():
+ linprocfs_donetarp():
+ linprocfs_donetroute():
+ linprocfs_dopartitions():
+ linprocfs_doprogress():
+ linprocfs_doscsi():
+ linprocfs_dousbdevices():
+ linprocfs_dousbhub():
+ linux_emul_convpath_orig():
+ linux_gifindex():
+ linux_ioctl_floppy():
+ linux_sifflags():
+ linux_to_bsd_sifhwaddr():
+ mdchange_vnode():
+ mpt_get_tgt_negotiated_params():
+ mpt_physdisk_status():
+ mpt_print_header(): [OpenBSD]
+ mpt_print_raid_config():
+ mpt_raid_vol_status():
+ mpt_read_cfg_page_with_alloc():
+ mpt_read_config_info_raid(): [OpenBSD]
+ mpt_set_tgt_params():
+ packet_abort():
+ packet_appenctl():
+ packet_attach():
+ packet_bind():
+ packet_connect():
+ packet_control():
+ packet_detach():
+ packet_dhd_input():
+ packet_disconnect():
+ packet_init():
+ packet_input():
+ packet_output():
+ packet_peeraddr():
+ packet_proto_input():
+ packet_send():
+ packet_shutdown():
+ packet_sockaddr():
+ ptmsclose():
+ ptmsopen():
+ ptmx_clone():
+ ptmxclose():
+ ptmxinit():
+ ptmxopen():
+ raid_get_physdisk_by_num():
+ read_raid_info():
+ resolve_raid_targets():
+ scsi_proc_inquiry():
+ shmperm():
+ splash_progress():
+ syscons_progress():
+ sysctl_kern_umass():
+ usb_bus_exist():
+ usbd_add_procinfo():
+ usbd_devinfo_sn():
+ usbd_remove_procinfo():
+ xpt_announce_proc():
+ xpt_find_umass():
+ xpt_proc_periph():
+ xptdaannouncefunc():
以及
+ vfs_nmount():
+ mpt_read_config_info_ioc():
+ linux_epoll_create():
+ linux_epoll_ctl():
+ linux_epoll_wait():
如果单从函数名比对的统计上看的话,14399个函数,只有79个函数可能是原创的。与FreeBSD 5.3在函数名上的相似度有99.45%。这个相似程度十分惊人,但是仅凭函数名相似不足以说明逻辑上相似,因此,在分析报告中,这个分析数据只作为参考数据放到附录中。感兴趣的朋友可以进一步的分析。
更多精彩
赞助商链接