Opened 7 years ago
Closed 7 years ago
#1454 closed defect (duplicate)
ngx_palloc may return a heap-buffer-overflow address if the parameter size is not aligned when call ngx_create_pool
Reported by: | Iven Xu | Owned by: | |
---|---|---|---|
Priority: | minor | Milestone: | |
Component: | other | Version: | 1.13.x |
Keywords: | pool misaligned | Cc: | |
uname -a: | Linux 3.10.106-1-0044 #1 SMP Mon Jul 17 15:20:12 CST 2017 x86_64 x86_64 x86_64 GNU/Linux | ||
nginx -V: | nginx version: nginx/1.13.5 |
Description
Hi,
Recently I use nginx as proxy server, and I also write a third-module for nginx. But I found a problem with the nginx pool.
I create a pool with the size 4098(it is a mistake, 4096 is the size that I really want). And I found sometimes the memory address that ngx_palloc returned is wrong.I use AddressSanitizer to detect the memory bugs, the AddressSanitizer will print message like this:
==39791== ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6062009a5508 at pc 0x466604 bp 0x7ffd93c864e0 sp 0x7ffd93c864d0
WRITE of size 1 at 0x6062009a5508 thread T0
#0 0x466603 (nginx+0x466603)
#1 0x8265de (nginx+0x8265de)
#2 0x823f67 (nginx+0x823f67)
#3 0x81c13a (nginx+0x81c13a)
#4 0x81b3ed (nginx+0x81b3ed)
#5 0x4700fc (nginx+0x4700fc)
#6 0x62df01 (nginx+0x62df01)
#7 0x6017db (nginx+0x6017db)
#8 0x544f13 (nginx+0x544f13)
#9 0x55cca5 (nginx+0x55cca5)
#10 0x55b3b7 (nginx+0x55b3b7)
#11 0x56b6cf (nginx+0x56b6cf)
#12 0x53d981 (nginx+0x53d981)
#13 0x53d4fc (nginx+0x53d4fc)
#14 0x53d38e (nginx+0x53d38e)
#15 0x56969f (nginx+0x56969f)
#16 0x565e87 (nginx+0x565e87)
#17 0x563d39 (nginx+0x563d39)
#18 0x55fc95 (nginx+0x55fc95)
#19 0x502475 (nginx+0x502475)
#20 0x4d3828 (nginx+0x4d3828)
#21 0x4fb3a5 (nginx+0x4fb3a5)
#22 0x4f1f75 (nginx+0x4f1f75)
#23 0x4f7efe (nginx+0x4f7efe)
#24 0x4f66a5 (nginx+0x4f66a5)
#25 0x45b352 (nginx+0x45b352)
#26 0x7f7e8daa8b14 (/usr/lib64/libc-2.17.so+0x21b14)
#27 0x45a4d0 (nginx+0x45a4d0)
0x6062009a5508 is located 6 bytes to the right of 4098-byte region [0x6062009a4500,0x6062009a5502)
Finally, I found the reason from the code. It is because of the size of the pool.
Let's look at the ngx_palloc_small.
static ngx_inline void *
ngx_palloc_small(ngx_pool_t *pool, size_t size, ngx_uint_t align)
{
u_char *m;
ngx_pool_t *p;
p = pool->current;
do {
m = p->d.last;
if (align) {
m = ngx_align_ptr(m, NGX_ALIGNMENT);
}
if ((size_t) (p->d.end - m) >= size) {
p->d.last = m + size;
return m;
}
p = p->d.next;
} while (p);
return ngx_palloc_block(pool, size);
}
Suppose the size is 4098 when call ngx_create_pool, so the p->d.end will be not aligned. If p->d.last = p->d.end - 1(this situation is likely to happen), p->d.last will be not aligned too. When call ngx_palloc_small with align is set 1, the temporary variables "m" is assigned to p->d.last. Because the align is set 1, "m" will be aligned for NGX_ALIGNMENT, and the "m" will be larger than p->d.end. The statement of if( (size_t) (p->d.end - m) >= size )will succeed(p->d.end - m is negative,but it connvert to be size_t which is unsigned). At last, the return memory address is overflow on the heap. For example, p->d.end = 0x6062009a5502, p->d.last = 0x6062009a5501, m = 0x6062009a5508 after alignment. The return memory address is m(0x6062009a5508 ) which is overflow.
This error is caused by the size which is not aligned when I called ngx_create_pool. But it is not a mandatory requirement that the size of pool must be aligned.
So, in my opinion nginx should return a correct memory address even if the size of pool is not aligned. Am I right?
It is mandatory. The problem cannot be triggered without 3rd-party code. You can't configure
connection_pool_size
orrequest_pool_size
to an unaligned size.