Opened 3 years ago
Last modified 2 years ago
#2416 closed defect
Memory overrun due to alignment issues when cross-compiling mingw on linux — at Version 1
| Reported by: | Orgad Shaneh | Owned by: | |
|---|---|---|---|
| Priority: | minor | Milestone: | |
| Component: | nginx-core | Version: | 1.22.x |
| Keywords: | memory security vulnerability | Cc: | Orgad Shaneh |
| uname -a: | MINGW64_NT-10.0-19043 | ||
| nginx -V: |
nginx version: nginx/1.22.1
built with OpenSSL 1.1.1s 1 Nov 2022 TLS SNI support enabled configure arguments: --crossbuild=win32 --with-http_stub_status_module --with-http_ssl_module --with-http_realip_module --without-http_scgi_module --without-http_uwsgi_module --with-openssl=../openssl --with-stream --with-stream_ssl_module --with-http_auth_request_module --with-http_sub_module --without-http_auth_basic_module --with-http_gzip_static_module --conf-path=nginx.conf --with-pcre=pcre --with-zlib=zlib-1.2.13 |
||
Description (last modified by )
Hi,
When I cross-compile nginx for Windows on linux host using mxe, NGX_ALIGNMENT is set to 16. This is set in auto/os/conf:
But the pool is allocated using plain malloc (on Windows target), which is *not* aligned to 16 bytes (it's aligned to 4), so pool->d.end is 4-byte aligned.
Now, in ngx_palloc_small, the following code causes integer underflow, and the comparison doesn't work as expected:
m = p->d.last;
if (align) {
m = ngx_align_ptr(m, NGX_ALIGNMENT);
}
if ((size_t) (p->d.end - m) >= size) { /* <------- This condition */
p->d.last = m + size;
return m;
}
Since m is aligned, and end is not, end - m can be a negative number. Then it is cast to size_t, which is unsigned, and so it just keeps writing past the memory pool, and overruns the next pool.
A minimal patch that solves this issue is:
-
src/core/ngx_palloc.c
a b ngx_palloc_small(ngx_pool_t *pool, size_t size, ngx_uint_t align) 160 160 m = ngx_align_ptr(m, NGX_ALIGNMENT); 161 161 } 162 162 163 if ( (size_t) (p->d.end - m) >= size) {163 if (m + size <= p->d.end) { 164 164 p->d.last = m + size; 165 165 166 166 return m;
But it would be better to assign the right alignment for Windows, even when cross-building. And also ensure that end is aligned correctly.
I also noticed that the default alignment when not set is sizeof(long), which is wrong for Win64. It should be sizeof(intptr_t).
Build command:
