[PATCH] Core: fixed environment on exit better
Roman Arutyunyan
arut at nginx.com
Wed Jun 28 15:36:34 UTC 2023
Hi,
On Wed, Jun 28, 2023 at 06:08:35PM +0300, Maxim Dounin wrote:
> Hello!
>
> On Wed, Jun 28, 2023 at 04:45:16PM +0400, Roman Arutyunyan wrote:
>
> > On Sat, Jun 24, 2023 at 05:06:46AM +0300, Maxim Dounin wrote:
> > > Hello!
> > >
> > > On Fri, Jun 23, 2023 at 07:55:47PM +0400, Sergey Kandaurov wrote:
> > >
> > > > # HG changeset patch
> > > > # User Sergey Kandaurov <pluknet at nginx.com>
> > > > # Date 1687535739 -14400
> > > > # Fri Jun 23 19:55:39 2023 +0400
> > > > # Node ID 34a8e1a4161542896c11c4a5c60d6a6fe1931e3d
> > > > # Parent c681f4906d838ac45b517fada4c4274ade03fd3c
> > > > Core: fixed environment on exit better.
> > > >
> > > > The fix in 6822:c045b4926b2c to replace environment allocations from a pool
> > > > was incomplete, such that it left pool owned allocations for variables set
> > > > with values using the "env" directive. Another consumer of this interface
> > > > is the QUIC BPF helper that uses the environment variable NGINX_BPF_MAPS.
> > > > The fix is to re-allocate variables with malloc, to avoid use after free.
> > > > If memory allocation failed, the only option is to expel from environment.
> > > >
> > > > The observed symptoms are similar to described in 6822:c045b4926b2c, that
> > > > is a segmentation fault on worker process exit from atexit() handler seen
> > > > with 3rd party modules or if nginx was built with lcov profiling.
> > > >
> > > > diff --git a/src/core/nginx.c b/src/core/nginx.c
> > > > --- a/src/core/nginx.c
> > > > +++ b/src/core/nginx.c
> > > > @@ -631,17 +631,48 @@ ngx_cleanup_environment(void *data)
> > > > {
> > > > char **env = data;
> > > >
> > > > - if (environ == env) {
> > > > + char *p, **penv;
> > > > + size_t size;
> > > > + ngx_uint_t i, n;
> > > >
> > > > - /*
> > > > - * if the environment is still used, as it happens on exit,
> > > > - * the only option is to leak it
> > > > - */
> > > > -
> > > > + if (environ != env) {
> > > > + ngx_free(env);
> > > > return;
> > > > }
> > >
> > > Note: if we assume that the environment can be arbitrary modified,
> > > I don't think it's enough. For example, a setenv() call can
> > > replace environ with something different, so this code will free
> > > env and exit, but pool-allocated variables will be still
> > > referenced by the new environ.
> >
> > Another problem is if setenv() was called, environ may have been
> > reallocated with realloc() which may result in double-free in this function,
> > even with current code.
>
> I don't think that realloc() is allowed here. At least BSD libc
> does not try to do this and only use realloc() on it's internal
> storage, and glibc does the same.
You're right. I see, glibc only realloc()'ates what it allocated itself.
stdlib/setenv.c:
/* If this variable is not a null pointer we allocated the current
environment. */
static char **last_environ;
[..]
--
Roman Arutyunyan
More information about the nginx-devel
mailing list