squid-2017

Version:

2.6.STABLE14 (fixed in 2.6.STABLE15)

Bug link:

http://bugs.squid-cache.org/show_bug.cgi?id=2017

How it is diagnosed (reproduced or source analysis)?

We reproduced this failure!

Symptom:

This failure involves the remote server sending a ‘302’ (Found) response, but in the end there is no blank line, only a single “\r\n”, so squid failed to forward the response, but instead forwarded a zero-sized failure page.

How to reproduce the failure:

This failure requires the control of a remote server. We used a program that can simulate a webserver and send arbitrary http response (developed by Henrik Nordstrom, a squid developer). This program can be found at:

http://opera.ucsd.edu/errlog/mykeyboard

Running this program is simple:

mykeyboard port_to_listen_to

Then when received with a http request, just send the 302 response with a single \r\n.

Root cause:

Squid didn’t test the header size before making decision to send error page.

--------------------

static void httpReadReply(int fd, void *data) {

 /* Use read system call to read the response. In this case, the response

    page size is zero (which is very suspicious), len == 0. */

 len = read (fd, buf, read_sz);

 if (!httpState->reply_hdr.size && len > 0 && fd_table[fd].uses > 1) {

        /* Skip whitespace */

        while (len > 0 && xisspace(*buf))

            xmemmove(buf, buf + 1, len--);

      if (len < 0) {

        ... ...

-     } else if (len==0 && entry->mem_obj->inmem_hi==0) {

+     } else if (len==0 && entry->mem_obj->inmem_hi==0 && !httpState->reply_hdr.size) {

     /* httpState->reply_hdr.size != 0, len == 0, so during the incorrect execution, it falls into this path! */

     /* This branch decision is not tested, therefore Errlog-AG can insert

        a logging statement here! */

        fwdFail(httpState->fwd, errorCon(ERR_ZERO_SIZE_OBJECT, HTTP_BAD_GATEWAY, httpState->fwd->request));

        httpState->eof = 1;

        comm_close(fd);

   } else if (len == 0) {

      /* After the fix, it should fall into this path. */

        httpState->eof = 1;

        if (httpState->reply_hdr_state < 2)

           /* After the fix, it also fix the “\r\n” problem. */

-            httpProcessReplyHeader(httpState, buf, len);

+            httpProcessReplyHeader(httpState, "\r\n", 2);

        ...

            return;

        }

        comm_close(fd);

        return;

   }

#0  httpReadReply (fd=16, data=0xa36728) at http.c:853

#1  0x000000000042e244 in comm_call_handlers (fd=16, read_event=1,

   write_event=0) at comm_generic.c:264

#2  0x000000000042eaba in do_comm_select (msec=1000) at comm_epoll.c:196

#3  0x000000000042e600 in comm_select (msec=1000) at comm_generic.c:386

#4  0x000000000045e728 in main (argc=2, argv=0x7fffffffe738) at main.c:837

Can developers anticipate the error:

Could be. The read system call above returned a length zero, which is suspicious and might be log-worthy. 

Can Errlog anticipate the error:

Yes. Errlog can either log the 0 return of the read system call, or log the untested branch decision.