2016年7月

提供 Maven 中央仓库托管服务的 Sonatype 公司说, Java 组件下载中,有 1/16 的下载组件中包含了已知的安全问题。

Sonatype 声称,开发者们每年要下载超过 310 亿个/次 Java 组件,每天也会新增超过 1 千个新组件以及超过 1 万个的组件新版本。

现在企业都采用托管式的中央组件仓库来存储他们的代码。这些代码中有一些来自私有项目,而更多的则来自于开源代码,在多数情况下,他们只是下载开源代码并导入到其项目中,而不做必要的安全审计。

Sonatype 发现现在企业中的百分之八、九十的代码都是由开源组件构成的,它们直接来自公开的代码导入。

由于这些安全缺陷都是公开的,而且 Sonatype 能够访问到其托管服务的服务器统计数据,相比其他人来说他们得到的数据会更多,因此他们警告开发者们要注意在他们的代码中使用不安全的或过期的组件所带来的风险。

这个警告对于公司来说更加严重,因为如果攻击者对采用有缺陷的组件创建的应用进行攻击,结果就可能导致更多的经济损失。

更老的组件的缺陷率高达三倍

在分析了来自几个不同行业的三千家机构的两万五千个以上的企业应用之后,Sonatype 发现平均每年每个企业都会下载大约五千个不同的组件。

组件越老,就越有可能包含安全缺陷。甚至更糟糕的是, 其中 97% 的下载的组件不能很方便的跟踪和审计。而如果公司仅仅是要修复两千个应用中的 10% 的安全漏洞,就大约需要 742 万美金的巨额投入。

这些问题说明企业需要对软件供应链进行管理,以避免将来出现的缺陷问题。花费在组件安全审计上的时间,将在该项目的以后出现安全漏洞后得到回报。

从这种托管的中央代码仓库中移除有缺陷的组件也应该成为这些项目背后的社区的最高优先级的工作。

软件供应链报告中包含了当今软件供应链的更多信息。

 title=

这是一个针对 PHP、Go、Python 等语言的 CGI 应用的漏洞。

httpoxy 是一系列影响到以 CGI 或类 CGI 方式运行的应用的漏洞名称。简单的来说,它就是一个名字空间的冲突问题。

  • RFC 3875 (CGI)中定义了从 HTTP 请求的 Proxy 头部直接填充到环境变量 HTTP_PROXY 的方式
  • HTTP_PROXY 是一个常用于配置外发代理的环境变量

这个缺陷会导致远程攻击。如果你正在运行着 PHP 或 CGI 程序,你应该马上封挡 Proxy 头部!马上! 具体做法参见下面。httpoxy 是一个服务器端 web 应用漏洞,如果你没有在服务器端部署这些代码,则不用担心。

如果我的 Web 应用存在这种漏洞会怎么样?

当一个利用了此漏洞的 HTTP 客户端发起请求时,它可以做到:

  • 通过你的 Web 应用去代理请求别的 URL
  • 直接让你的服务器打开指定的远程地址及端口
  • 浪费服务器的资源,替攻击者访问指定的资源

httpoxy 漏洞非常容易利用。希望安全人员尽快扫描该漏洞并快速修复。

哪些受到影响?

以下情况会存在安全漏洞:

  • 代码运行在 CGI 上下文中,这样 HTTP_PROXY 就会变成一个真实的或模拟的环境变量
  • 一个信任 HTTP_PROXY的 HTTP 客户端,并且支持代理功能
  • 该客户端会在请求内部发起一个 HTTP(或 HTTPS)请求

下列情形是已经发现存在该缺陷的环境:

语言环境HTTP 客户端
PHPphp-fpm mod\_phpGuzzle 4+ Artax
Pythonwsgiref.handlers.CGIHandler twisted.web.twcgi.CGIScriptrequests
Gonet/http/cginet/http

肯定还有很多我们没有确定是否存在缺陷的语言和环境。

PHP

  • 是否存在缺陷依赖于你的应用代码和 PHP 库,但是影响面看起来似乎非常广泛
  • 只要在处理用户请求的过程中使用了一个带有该缺陷的库,就可能被利用
  • 如果你使用了有该缺陷的库,该缺陷会影响任意 PHP 版本

    • 甚至会影响到替代的 PHP 运行环境,比如部署在 FastCGI 模式下的 HHVM
  • 确认影响 Guzzle、Artax 等库,可能还有很多很多的库也受影响

    • Guzzle 4.0.0rc2 及其以后版本受影响,Guzzle 3 及更低版本不受影响
    • 其它的例子还有 Composer 的 StreamContextBuilder 工具类

举个例子说,如果你在 Drupal 中使用 Guzzle 6 模块发起外发请求(比如请求一个天气 API),该模块发起的请求就存在这个 httpoxy 缺陷。

Python

  • Python 代码只有部署在 CGI 模式下才存在缺陷,一般来说,存在缺陷的代码会使用类似 wsgiref.handlers.CGIHandler 的 CGI 控制器

    • 正常方式部署的 Python web 应用不受影响(大多数人使用 WSGI 或 FastCGI,这两个不受影响),所以受到影响的 Python 应用要比 PHP 少得多
    • wsgi 不受影响,因为 os.environ 不会受到 CGI 数据污染
  • 存在缺陷的 requests 库必须信任和使用 os.environ['HTTP_PROXY'],并且不做内容检查

Go

  • Go 代码必须部署在 CGI 下才受影响。一般来说受到影响的代码会使用 net/http/cgi

    • 像 Python 一样,这并不是部署 Go 为一个 Web 应用的通常方式。所以受到影响的情形很少
    • 相较而言,Go 的 net/http/fcgi 包并不设置实际的环境变量,所以不受影响
  • 存在缺陷的 net/http 版本需要在外发请求中信任并使用 HTTP_PROXY ,并不做内容检查

马上修复

最好的修复方式是在他们攻击你的应用之前尽早封挡 Proxy 请求头部。这很简单,也很安全。

  • 说它安全是因为 IETF 没有定义 Proxy 请求头部,也没有列在 IANA 的消息头部注册中。这表明对该头部的使用是非标准的,甚至也不会临时用到
  • 符合标准的 HTTP 客户端和服务器绝不应该读取和发送这个头部
  • 你可以从请求中去掉这个头部或者干脆整个封挡使用它的请求
  • 你可以在上游没有发布补丁时自己来解决这个问题

    • 当 HTTP 请求进来时就检查它,这样可以一次性修复好许多存在缺陷的应用
    • 在反向代理和应用防火墙之后的应用剔除 Proxy 请求头部是安全的

如何封挡 Proxy 请求头部依赖于你的配置。最容易的办法是在你的 Web 应用防火墙上封挡该头部,或者直接在 Apache 和 Nginx 上做也行。以下是一些如何做的指导:

Nginx/FastCGI

使用如下语句封挡传递给 PHP-FPM、PHP-PM 的请求头,这个语句可以放在 fastcgi.conf 或 fastcgi\_param 中(视你使用了哪个配置文件):

fastcgi_param HTTP_PROXY "";

在 FastCGI 模式下,PHP 存在缺陷(但是大多数使用 Nginx FastCGI 的其它语言则不受影响)。

Apache

对于 Apache 受影响的具体程度,以及其它的 Apache 软件项目,比如 Tomcat ,推荐参考 Apache 软件基金会的官方公告。 以下是一些主要信息:

如果你在 Apache HTTP 服务器中使用 mod_cgi来运行 Go 或 Python 写的脚本,那么它们会受到影响(这里 HTTP_PROXY 环境变量是“真实的”)。而 mod_php 由于用于 PHP 脚本,也存在该缺陷。

如果你使用 mod\_headers 模块,你可以通过下述配置在进一步处理请求前就 unset 掉 Proxy 请求头部:

RequestHeader unset Proxy early

如果你使用 mod\_security 模块,你可以使用一个 SecRule 规则来拒绝带有 Proxy 请求头部的请求。下面是一个例子,要确保 SecRuleEngine 打开了。你可以根据自己的情况调整。

SecRule &REQUEST_HEADERS:Proxy "@gt 0" "id:1000005,log,deny,msg:'httpoxy denied'"

最后,如果你使用 Apache Traffic Server 的话,它本身不受影响。不过你可以用它来剔除掉 Proxy 请求头部,以保护其后面的其它服务。具体可以参考 ASF 指导

HAProxy

通过下述配置剔除该请求头部:

http-request del-header Proxy

Varnish

通过下述语句取消该头部,请将它放到已有的 vcl\_recv 小节里面:

sub vcl_recv {
    [...]
    unset req.http.proxy;
    [...]
}

OpenBSD relayd

使用如下语句移除该头部。把它放到已有的过滤器里面:

http protocol httpfilter {
    match request header remove "Proxy"
}

lighttpd (<= 1.4.40)

弹回包含 Proxy 头部的请求。

  • 创建一个 /path/to/deny-proxy.lua文件,让它对于 lighttpd 只读,内容如下:
if (lighty.request["Proxy"] == nil) then return 0 else return 403 end
  • 修改 lighttpd.conf 以加载 mod_magnet 模块,并运行如上 lua 代码:
server.modules += ( "mod_magnet" )
magnet.attract-raw-url-to = ( "/path/to/deny-proxy.lua" )

lighttpd2 (开发中)

从请求中剔除 Proxy 头部。加入如下语句到 lighttpd.conf中:

req_header.remove "Proxy";

用户端的 PHP 修复没有作用

用户端的修复不能解决该缺陷,所以不必费劲:

  • 使用 unset($_SERVER['HTTP_PROXY']) 并不会影响到 getenv() 返回的值,所以无用
  • 使用 putenv('HTTP_PROXY=') 也没效果(putenv 只能影响到来自实际环境变量的值,而不是来自请求头部的)

httpoxy 的历史

该漏洞首次发现与15年前。

2001 年 3 月
Randal L. Schwartz 在 libwww-perl 发现该缺陷并修复。

2001 年 4 月
Cris Bailiff 在 curl 中发现该缺陷并修复。

2012 年 7 月
Net::HTTPHTTP_PROXY 实现中, Ruby 团队的 Akira Tanaka 发现了该缺陷

2013 年 11 月
在 nginx 邮件列表中提到了该缺陷。发现者 Jonathan Matthews 对此不太有把握,不过事实证明他是对的。

2015 年 2 月
Stefan Fritsch 在 Apache httpd-dev 邮件列表中提到了它。

2016 年 7 月
Vend 安全团队的 Scott Geary 发现了对该缺陷,并且它影响到了 PHP 等许多现代的编程语言和库。

所以,这个缺陷已经潜伏了许多年,许多人都在不同方面发现了它的存在,但是没有考虑到它对其它语言和库的影响。安全研究人员为此专门建立了一个网站: https://httpoxy.org/ ,可以在此发现更多内容。

在 Awk 系列的这一节中,我们将看到 awk 最重要的特性之一,字段编辑。

首先我们要知道,Awk 能够自动将输入的行,分隔为若干字段。每一个字段就是一组字符,它们和其他的字段由一个内部字段分隔符分隔开来。

Awk 输出字段和列

如果你熟悉 Unix/Linux 或者懂得 bash shell 编程,那么你应该知道什么是内部字段分隔符(IFS)变量。awk 中默认的 IFS 是制表符和空格。

awk 中的字段分隔符的工作原理如下:当读到一行输入时,将它按照指定的 IFS 分割为不同字段,第一组字符就是字段一,可以通过 $1 来访问,第二组字符就是字段二,可以通过 $2 来访问,第三组字符就是字段三,可以通过 $3 来访问,以此类推,直到最后一组字符。

为了更好地理解 awk 的字段编辑,让我们看一个下面的例子:

例 1:我创建了一个名为 tecmintinfo.txt 的文本文件。

# vi tecmintinfo.txt
# cat tecmintinfo.txt

在 Linux 上创建一个文件

然后在命令行中,我试着使用下面的命令从文本 tecmintinfo.txt 中输出第一个,第二个,以及第三个字段。

$ awk '//{print $1 $2 $3 }' tecmintinfo.txt
TecMint.comisthe

从上面的输出中你可以看到,前三个字段的字符是以空格为分隔符输出的:

  • 字段一是 “TecMint.com”,可以通过 $1 来访问。
  • 字段二是 “is”,可以通过 $2 来访问。
  • 字段三是 “the”,可以通过 $3 来访问。

如果你注意观察输出的话可以发现,输出的字段值并没有被分隔开,这是 print 函数默认的行为。

为了使输出看得更清楚,输出的字段值之间使用空格分开,你需要添加 (,) 操作符。

$ awk '//{print $1, $2, $3; }' tecmintinfo.txt

TecMint.com is the

需要记住而且非常重要的是,($) 在 awk 和在 shell 脚本中的使用是截然不同的!

在 shell 脚本中,($) 被用来获取变量的值。而在 awk 中,($) 只有在获取字段的值时才会用到,不能用于获取变量的值。

例 2:让我们再看一个例子,用到了一个名为 my\_shoping.list 的包含多行的文件。

No    Item_Name                 Unit_Price  Quantity    Price
1     Mouse                     #20,000     1           #20,000
2     Monitor                   #500,000    1           #500,000
3     RAM_Chips                 #150,000    2           #300,000
4     Ethernet_Cables           #30,000     4           #120,000        

如果你只想输出购物清单上每一个物品的单价,你只需运行下面的命令:

$ awk '//{print $2, $3 }' my_shopping.txt 

Item_Name Unit_Price
Mouse #20,000
Monitor #500,000
RAM_Chips #150,000
Ethernet_Cables #30,000

可以看到上面的输出不够清晰,awk 还有一个 printf 的命令,可以帮助你将输出格式化。

使用 printf 来格式化 Item\_Name 和 Unit\_Price 的输出:

$ awk '//{printf "%-10s %s\n",$2, $3 }' my_shopping.txt 

Item_Name  Unit_Price
Mouse      #20,000
Monitor    #500,000
RAM_Chips  #150,000
Ethernet_Cables #30,000

总结

使用 awk 过滤文本或字符串时,字段编辑的功能是非常重要的。它能够帮助你从一个表的数据中得到特定的列。一定要记住的是,awk 中 ($) 操作符的用法与其在 shell 脚本中的用法是不同的!

希望这篇文章对您有所帮助。如有任何疑问,可以在评论区域发表评论。


via: http://www.tecmint.com/awk-print-fields-columns-with-space-separator/

作者:Aaron Kili 译者:Cathonictlyh 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

今日关注

Fedora 项目大使及打包者 Miro Hrončok 向社区发出倡议,希望社区人员能够帮助他们移植一些软件包到最新的 Python 3 上。Fedora 项目总是在支持新技术方面走在前列,在 Python 3 方面也是。有许多使用 Python 写的应用都已经支持了 Python 3,但是不幸的是,它们通常没有为 Fedora 做好打包,所以 Fedora 项目需要更多的志愿者来帮忙做一些移植和打包工作

参与这个工作很容易,你只需要懂得一些 Python 3 语言,然后从 Fedora Python 3 移植数据库中选择你要移植的包,在 Bugzilla 上申明你要移植即可开始。具体的移植工作,你需要提交可以使软件包兼容 Python 3 的 spec 文件,创建补丁并附加到 Bugzilla bug 报告中。完成这一切之后,你的每个补丁都可以为你赢得一枚 Fedora 徽章

 title=

加入 Python 3 移植团队

图文摘要

美军原计划将其 400 万台设备升级到 Windows 10,但是现在由于资金问题,显然没法按照原计划的升级时限进行,目前计划得到明年第二季度才能完成。

IT 正在逐渐迁移到云端。那又是什么驱动了云呢?答案是 Linux。 当连微软的 Azure 都开始拥抱 Linux 时,你就应该知道这一切都已经改变了。

图片: ZDNet

不管你接不接受, 云正在接管 IT 已经成为现实。 我们这几年见证了 云在内部 IT 的崛起 。 那又是什么驱动了云呢? 答案是 Linux 。

Uptime Institute 最近对 1000 个 IT 决策者进行了调查,发现约 50% 左右的资深企业 IT 决策者认为在将来大部分的 IT 工作应该放在云上 或托管网站上。在这个调查中,23% 的人认为这种改变即将发生在明年,有 70% 的人则认为这种情况会在四年内出现。

这一点都不奇怪。 我们中的许多人仍热衷于我们的物理服务器和机架, 但一般运营一个自己的数据中心并不会产生任何的经济效益。

很简单, 只需要对比你运行在你自己的硬件上的资本费用(CAPEX)和使用云的业务费用(OPEX)即可。 但这并不是说你应该把所有的东西都一股脑外包出去,而是说在大多数情况下你应该把许多工作都迁移到云端。

相应地,如果你想充分地利用云,你就得了解 Linux 。

亚马逊的 AWSApache CloudStackRackspace谷歌的 GCP 以及 OpenStack 的核心都是运行在 Linux 上的。那么结果如何?截至到 2014 年, 在 Linux 服务器上部署的应用达到所有企业的 79% ,而 在 Windows 服务器上部署的则跌到 36%。从那时起, Linux 就获得了更多的发展动力。

即便是微软自身也明白这一点。

Azure 的技术主管 Mark Russinovich 曾说,仅仅在过去的几年内微软就从四分之一的 Azure 虚拟机运行在 Linux 上 变为将近三分之一的 Azure 虚拟机运行在 Linux 上

试想一下。微软,一家正逐渐将云变为自身财政收入的主要来源 的公司,其三分之一的云产业依靠于 Linux 。

即使是到目前为止, 这些不论喜欢或者不喜欢微软的人都很难想象得到微软会从一家以商业软件为基础的软件公司转变为一家开源的、基于云服务的企业

Linux 对于这些专用服务器机房的渗透甚至比它刚开始的时候更深了。 举个例子, Docker 最近发行了其在 Windows 10 和 Mac OS X 上的公测版本 。 这难道是意味着 Docker 将会把其同名的容器服务移植到 Windows 10 和 Mac 上吗? 并不是的。

在这两个平台上, Docker 只是运行在一个 Linux 虚拟机内部。 在 Mac OS 上是 HyperKit ,在 Windows 上则是 Hyper-V 。 在图形界面上可能看起来就像另一个 Mac 或 Windows 上的应用, 但在其内部的容器仍然是运行在 Linux 上的。

所以,就像大量的安卓手机和 Chromebook 的用户压根就不知道他们所运行的是 Linux 系统一样。这些 IT 用户也会随之悄然地迁移到 Linux 和云上。


via: http://www.zdnet.com/article/it-runs-on-the-cloud-and-the-cloud-runs-on-linux-any-questions/

作者:Steven J. Vaughan-Nichols 译者:chenxinlong 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

linus torvalds

1999 年 8 月 10 日,加利福尼亚州圣何塞市,在 LinuxWorld Show 上 Linus Torvalds 在一个坐满 Linux 爱好者的礼堂中发表了一篇演讲。图片来自:James Niccolai

这取决于所处的领域。在软件开发的世界中,他也是个普通人。问题是,这种情况是否应该继续下去?

我认识 Linux 的发明人 Linus Torvalds 已经超过 20 年了。我们不是密友,但是我们欣赏彼此。

最近,因为 Linus Torvalds 的管理风格,他正遭到严厉的炮轰。Linus 无法忍受胡来的人。“代码的质量有多好?”这是他在 Linux 内核的开发过程中评判人的一种方式。

没有什么比这个更重要了。正如 Linus 今年(2015年)早些时候在 Linux.conf.au 会议上说的那样,“我不是一个友好的人,我也不在意你。对我重要的是‘我所关心的技术和内核’。”

现在我也可以和这种只关心技术的人打交道了。如果你不能,你应当避免参加 Linux 内核会议,因为在那里你会遇到许多有这种精英思想的人。这不代表我认为在 Linux 领域所有东西都是极好的,并且不应该受到其他影响而带来改变。我能够和一个精英相处;而在一个男性做主导的大城堡中遇到的问题是,女性经常受到蔑视和无礼的对待。

这就是我看到的最近关于 Linus 管理风格所引发争论的原因 —— 或者更准确的说,他对于个人管理方面是完全冷漠的 —— 就像是在软件开发世界的标准操作流程一样。与此同时,我看到揭示了这个事情需要改变的另外一个证据。

第一次是在 Linux 4.3 发布的时候出现的这个情况,Linus 使用 Linux 内核邮件列表狠狠的数落了一个插入了一些网络方面的代码的开发者——这些代码很“烂”、“生成了如此烂的代码。这看起来太糟糕了,并且完全没有理由这样做。”他继续地咆哮了半天。这里使用“烂”这个词,相对他早期使用的“愚蠢的”这个同义词来说还算好的。

但是,事情就是这样。Linus 是对的。我读了代码后,发现代码确实很烂,并且开发者只是为了用新“overflow\_usub()” 函数而用。

现在,一些人把 Linus 的这种谩骂的行为看作他脾气不好而且恃强凌弱的证据。我也见过一个完美主义者,在他的领域中,他无法忍受这种糟糕。

许多人告诉我,这不是一个专业的程序员应当有的行为。群众们,你曾经和最优秀的开发者一起工作过吗?据我所知道的,在 Apple,Microsoft,Oracle ,这就是他们的行为。

我曾经听过 Steve Jobs 攻击一个开发者,就像要把他撕成碎片那样。我也被一个 Oracle 的高级开发者责骂一屋子的新开发者吓到过,就像食人鱼穿过一群金鱼那样。

在 Robert X. Cringely 关于 PC 崛起的经典书籍《 意外帝国 Accidental Empires 》,中,他这样描述了微软的软件管理风格,比尔·盖茨像计算机系统一样管理他们,“比尔·盖茨是最高等级,从他开始每一个等级依次递减,上级会向下级叫嚷,刺激他们,甚至羞辱他们。”

Linus 和所有大型的商业软件公司的领导人不同的是,Linus 说在这里所有的东西都是向全世界公开的。而其他人是在自己的会议室中做东西的。我听有人说 Linus 在那种公司中可能会被开除。这是不可能的。他会处于他现在所处的地位,他在编程世界的最顶端。

但是,这里有另外一个不同。如果 Larry Ellison (Oracle 的首席执行官)向你发火,你就别想在这里干了。如果 Linus 向你发火,你会在邮件中收到他的责骂。这就是差别。

你知道的,Linus 不是任何人的老板。他完全没有雇佣和解聘的权利,他只是负责着有着 10000 个贡献者的一个项目而已。他仅仅能做的就是从心理上伤害你。

这说明,在开源软件开发圈和商业软件开发圈中同时存在一个非常严重的问题。不管你是一个多么好的编程者,如果你是一个女性,你的这个身份就是对你不利的。

这种情况并没有在 Sarah Sharp 的身上有任何好转,她现在是一个 Intel 的开发者,以前是一个顶尖的 Linux 程序员。在她博客上10月份的一个帖子中,她解释道:“我最终发现,我不能够再为 Linux 社区做出贡献了。因为在那里,我虽然能够得到技术上的尊重,却得不到个人的尊重……我不想专职于同那些有着点性别歧视或开同性恋玩笑的人一起工作。”

谁会责怪她呢?我不会。很抱歉,我必须说,Linus 就像所有我见过的软件经理一样,是他造成了这种不利的工作环境。

他可能会说,确保 Linux 的贡献者都表现出专业精神和相互尊重不应该是他的工作。除了代码以外,他不关心任何其他事情。

就像 Sarah Sharp 写的那样:

我对于 Linux 内核社区做出的技术努力表示最大的尊重。他们在那维护一些最高标准的代码,以此来平衡并且发展一个项目。他们专注于优秀的技术,以及超过负荷的维护人员,他们有不同的文化背景和社会规范,这意味着这些 Linux 内核维护者说话非常直率、粗鲁,或者为了完成他们的任务而不讲道理。顶尖的 Linux 内核开发者经常为了使别人改正行为而向他们大喊大叫。

这种事情发生在我身上,但它不是一种有效的沟通方式。

许多高级的 Linux 内核开发者支持那些技术上和人性上不讲道理的维护者的权利,即使他们自己是非常友好的一个人,他们不想看到 Linux 内核交流方式改变。

她是对的。

我和其他观察者不同的是,我不认为这个问题对于 Linux 或开源社区在任何方面有特殊之处。作为一个从事技术商业工作超过五年和有着 25 年技术工作经历的记者,我见多了这种不成熟的小孩子行为。

这不是 Linus 的错误。他不是一个经理,他是一个有想象力的技术领导者。看起来真正的问题是,在软件开发领域没有人能够以一种支持的语气来对待团队和社区。

展望未来,我希望像 Linux 基金会这样的公司和组织,能够找到一种方式去授权社区经理或其他经理来鼓励并且强制实施民主的行为。

非常遗憾的是,我们不能够在我们这种纯技术或纯商业的领导人中找到这种管理策略。它不存在于这些人的基因中。


via: http://www.computerworld.com/article/3004387/it-management/how-bad-a-boss-is-linus-torvalds.html

作者:Steven J. Vaughan-Nichols 译者:FrankXinqi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出