Skip to content

Commit

Permalink
Cygwin: Fix segfalt when too many command line args are specified.
Browse files Browse the repository at this point in the history
Previously, the number of command line args was not checked for
cygwin process. Due to this, segmentation fault was caused if too
many command line args are specified.
https://cygwin.com/pipermail/cygwin/2023-August/254333.html

Since char *argv[argc + 1] is placed on the stack in dll_crt0_1(),
STATUS_STACK_OVERFLOW occurs if the stack does not have enough
space.

With this patch, char *argv[] is placed in heap instead of stack
and ARG_MAX is increased from 32000 to 2097152 which is default
value of Linux. The argument length is also compared with ARG_MAX
and spawnve() returns E2BIG if it is too long.

Reported-by: Ed Morton
Reviewed-by: Corinna Vinschen <[email protected]>
Signed-off-by: Takashi Yano <[email protected]>
  • Loading branch information
tyan0 committed Aug 28, 2023
1 parent 208c3f6 commit 33cddf7
Show file tree
Hide file tree
Showing 5 changed files with 18 additions and 7 deletions.
7 changes: 2 additions & 5 deletions winsup/cygwin/dcrt0.cc
Original file line number Diff line number Diff line change
Expand Up @@ -978,11 +978,8 @@ dll_crt0_1 (void *)
a change to an element of argv[] it does not affect Cygwin's argv.
Changing the the contents of what argv[n] points to will still
affect Cygwin. This is similar (but not exactly like) Linux. */
char *newargv[__argc + 1];
char **nav = newargv;
char **oav = __argv;
while ((*nav++ = *oav++) != NULL)
continue;
char **newargv = (char **) malloc ((__argc + 1) * sizeof (char *));
memcpy (newargv, __argv, (__argc + 1) * sizeof (char *));
/* Handle any signals which may have arrived */
sig_dispatch_pending (false);
_my_tls.call_signal_handler ();
Expand Down
4 changes: 4 additions & 0 deletions winsup/cygwin/local_includes/winsup.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ uint32_t cygwin_inet_addr (const char *cp);
application provided path strings we handle. */
#define NT_MAX_PATH 32768

/* CYG_ARG_MAX is the maximum total length of command line args.
The value 2097152 is the default ARG_MAX value in Linux. */
#define CYG_ARG_MAX 2097152

/* This definition allows to define wide char strings using macros as
parameters. See the definition of __CONCAT in newlib's sys/cdefs.h
and accompanying comment. */
Expand Down
3 changes: 3 additions & 0 deletions winsup/cygwin/release/3.4.9
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,6 @@ Bug Fixes
- For the time being, disable creating special files using mknod/mkfifo
on NFS.
Addresses: https://cygwin.com/pipermail/cygwin/2023-August/254266.html

- Fix segfault when too many command line args are specified.
Addresses: https://cygwin.com/pipermail/cygwin/2023-August/254333.html
9 changes: 8 additions & 1 deletion winsup/cygwin/spawn.cc
Original file line number Diff line number Diff line change
Expand Up @@ -340,8 +340,9 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
We need to quote any argument that has whitespace or embedded "'s. */

int ac;
size_t arg_len = 0;
for (ac = 0; argv[ac]; ac++)
/* nothing */;
arg_len += strlen (argv[ac]) + 1;

int err;
const char *ext;
Expand Down Expand Up @@ -510,6 +511,12 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
__leave;
}
set (chtype, real_path.iscygexec ());
if (iscygwin () && arg_len > (size_t) sysconf (_SC_ARG_MAX))
{
set_errno (E2BIG);
res = -1;
__leave;
}
__stdin = in__stdin;
__stdout = in__stdout;
record_children ();
Expand Down
2 changes: 1 addition & 1 deletion winsup/cygwin/sysconf.cc
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,7 @@ static struct
};
} sca[] =
{
{cons, {c:ARG_MAX}}, /* 0, _SC_ARG_MAX */
{cons, {c:CYG_ARG_MAX}}, /* 0, _SC_ARG_MAX */
{cons, {c:CHILD_MAX}}, /* 1, _SC_CHILD_MAX */
{cons, {c:CLOCKS_PER_SEC}}, /* 2, _SC_CLK_TCK */
{cons, {c:NGROUPS_MAX}}, /* 3, _SC_NGROUPS_MAX */
Expand Down

0 comments on commit 33cddf7

Please sign in to comment.