woaidongmao

文章均收录自他人博客,但不喜标题前加-[转贴],因其丑陋,见谅!~
随笔 - 1469, 文章 - 0, 评论 - 661, 引用 - 0
数据加载中……

nginx fastcgi模块的一个bug

原创文章,转载请注明: 转载自pagefault

本文链接地址: nginx fastcgi模块的一个bug

上周服务器更新到nginx0.8.X之后,nginx出现了core dump的情况,而在0.7.X并不会出现,通过察看core dump文件以及nginx 0.8.x0.7.x的比较,发现core dumpnginx 0.8.40引入下面这个feature才导致的:

*) Feature: a “fastcgi_param” directive with value starting with
“HTTP_” overrides a client request header line.

nginx 0.8.40之后,如果你的fastcgi_param定义的变量以HTTP_开头,则传递给后端的头会忽略request header中的这个头,比如定义了一个 fastcgi_param $HTTP_HOST test, 那么传递给后端时,host这个头的值就是test.

这里的逻辑是这样子的,当nginx创建一个fastcgi request的时候,会先计算所需要的长度,首先是计算header的长度,在计算之前会先分配一个ignored数组(用来保存将要被忽略的头),它的大小是配置文件中fastcgi_param定义的以HTTP_开头的变量的个数. 然后遍历所有的request header,如果发现header的名字和fastcgi_param中定义的变量的(HTTP_开头)名字相同(使用hash),则将这个header指针放到ignored数组中,最后在拷贝request header的时候直接在这个数组里面查找,如果有则跳过,否则拷贝头以及它的值。

看起来没什么问题,可是这里忽略了request header有可能会有重复的这个情况,此时ignored数组可能就会越界,从而导致core dump.


来看对应的代码,引起问题的代码是下面这段(ngx_http_fastcgi_create_request).

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

//这里header_params就是fastcgi_param中定义的变量的(HTTP_开头)个数

        if (flcf->header_params) {

//分配内存

            ignored = ngx_palloc(r->pool, flcf->header_params * sizeof(void *));

            if (ignored == NULL) {

                return NGX_ERROR;

            }

        }

  

        part = &r->headers_in.headers.part;

        header = part->elts;

//开始遍历

        for (i = 0; /* void */; i++) {

  

            if (i >= part->nelts) {

                if (part->next == NULL) {

                    break;

                }

  

                part = part->next;

                header = part->elts;

                i = 0;

            }

  

            if (flcf->header_params) {

         ..............................................................

//headers_hash就是fastcgi_param中定义的变量(HTTP_开头)名字的hash

                if (ngx_hash_find(&flcf->headers_hash, hash, lowcase_key, n)) {

//可以看到只要找到相同的hash,则header_params就会加一.而如果重复的头大于fastcgi_param中定义的变量的(HTTP_开头)的个数,则ignored肯定会越界.

                    ignored[header_params++] = &header[i];

                    continue;

                }

  

                n += sizeof("HTTP_") - 1;

  

            } else {

                n = sizeof("HTTP_") - 1 + header[i].key.len;

            }

举个例子,配置文件里面包含下面的命令:
fastcgi_param HTTP_HOST $http_host;

然后客户端传过来的头中如果包含多个host头,则nginx就会core dump.

 

posted on 2011-06-21 10:57 肥仔 阅读(410) 评论(0)  编辑 收藏 引用 所属分类: Web-后台


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理