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?

Change History (2)

comment:1 by Valentin V. Bartenev, 7 years ago

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.

It is mandatory. The problem cannot be triggered without 3rd-party code. You can't configure connection_pool_size or request_pool_size to an unaligned size.

comment:2 by Maxim Dounin, 7 years ago

Resolution: duplicate
Status: newclosed

Duplicate of #686.

Note: See TracTickets for help on using tickets.