Messages in this thread | | | Date | Fri, 21 Aug 1998 21:12:40 -0400 | From | brian@nycrc ... | Subject | Ulimit Probrems with Linux |
| |
Hello all,
[Note: This is not a re-submission of the Apache dos Sioux error but a new problem which is related to it and the patch which was posted.]
Recently on bugtraq there was an Apache dos attack posted that caused an exponential increase in memory usage by sending multiple headers. The headers would be merged by sending the string:
User-Agent: [string length of 5]
Sending this 10,000 times would produce the string:
User-Agent [memory consumed=350M]
The problem appears to be in Apache's ap_pstrcat function. The function concatenates the string by first allocating a new buffer and copies the data into it. The problem lies in the fact that the function fails to release the original buffer(s). All of the intermediate states remain in memory after they should have been released.
The fix that was posted effectively limited the number of headers to 100 by patching the function that reads them in to memory. This is incomplete since limiting the number of headers does not limit the size of the header and therefore does not limit the ultimate size of the string. While the patch would correct the example previously cited, it would do nothing for the following:
User-Agent: [string length of 8192]
Sending this 100 times would produce the string:
User-Agent: [memory consumed=42M]
The second example has consumed significantly less memory, however, it is still far more than should have been. There is also the issue that it would require very few simultaneous attacks to achieve the same results as in the first example.
In an attempt to correct the problem altogether ulimit was invoked to restrict the maximum size of it's data segment instead of trying to hack Apache's source. Using the shell script command [ulimit -d 2048] prevented the 40M buffers that were previously occurring, however, instead of taking up 2M the process took up 10M. This was not the expected result.
Next was to hack Apache to make sure it was not resetting the limits internally and it did report the correct limit. After adding to the kernel in /usr/src/linux/mm/mmap.c where it checks the memory limit the kernel reported that the processes were ok.
Now it is necessary to run some test code to see just what was happening with the memory allocation. The following is the first test which was run:
#include<stdio.h> #include<sys/resource.h>
main(int argc,char **argv) { unsigned long int total,size; char *p; size=65536; total=0; for(;;) { getchar(); if (!(p=malloc(size))) { perror("malloc failed"); for(;;) ; } memset(p,0,size); { struct rlimit rlim; getrlimit(RLIMIT_DATA,&rlim); total=total+size; fprintf(stderr,"BMA: rlim: %d\n",rlim.rlim_cur); fprintf(stderr,"BMA: rlim: %lu %lu\n",total,size); } } }
The result here was that just allocating 64k buffers the ulimit invocation works just fine. The next test is where the problem lies. Using the following:
#include<stdio.h> #include<sys/resource.h>
main(int argc,char **argv) { unsigned long int total,size; char *p; size=65536; total=0; for(;;) { getchar(); if (!(p=malloc(size))) { perror("malloc failed"); for(;;) ; } memset(p,0,size); { struct rlimit rlim; getrlimit(RLIMIT_DATA,&rlim); total=total+size; fprintf(stderr,"BMA: rlim: %d\n",rlim.rlim_cur); fprintf(stderr,"BMA: rlim: %lu %lu\n",total,size); size=size+65536; } } }
results in allocating the increasingly larger blocks which indicates the ulimit invocation has failed. This represents the same results as the originally reported Apache dos attack.
From these tests I can only conclude that if you use malloc to allocate buffers larger than 128k the problem will occur consistently. Even if ulimit is set to 100 bytes an 8M segment is allocated somewhere. Generally speaking, most code does not do this, however, this appears to be a case where Apache does. Either there is a significant flaw in my thinking on this or a flaw in the way linux is allocating memory. If it's the former, well, apologies in advance. If it is the latter, I believe it must be addressed since it creates a vulnerability that represents a serious bug.
The tests were run on both libc5.3.12 and glibc2.0.5 using a linux 2.0.35 kernel. I ran strace on the Apache sever and noticed that it was running the brk system call to increase the data segment. It was also running mmap. Is that where the memory is going? I assume that malloc is making these calls because Apache did not have any mmaps that were in the segment of code that I was testing.
I wasn't sure whether this would be more appropriate if posted to bugtraq, linux-kernel or linux- admin so I picked two out of the three.
Thanks, Brian Ackerman Computer Resource Center Inc.
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.altern.org/andrebalsa/doc/lkml-faq.html
| |