diff options
author | CoprDistGit <infra@openeuler.org> | 2024-10-26 05:38:32 +0000 |
---|---|---|
committer | CoprDistGit <infra@openeuler.org> | 2024-10-26 05:38:32 +0000 |
commit | 490d9f3217eb4c04a834d073e479765496ee90a9 (patch) | |
tree | 0b68b2139750553856dd9a42cd8a614b6d6ff493 /backport-CVE-2023-47039.patch | |
parent | 14b6cc6f2f3174b885ea1a6f97c55dd0d0d86f79 (diff) |
automatic import of perlopeneuler24.03_LTS
Diffstat (limited to 'backport-CVE-2023-47039.patch')
-rw-r--r-- | backport-CVE-2023-47039.patch | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/backport-CVE-2023-47039.patch b/backport-CVE-2023-47039.patch new file mode 100644 index 0000000..66bf8b4 --- /dev/null +++ b/backport-CVE-2023-47039.patch @@ -0,0 +1,196 @@ +From 906e92715f4ee68ea95086867f4f97b1f4f10ac3 Mon Sep 17 00:00:00 2001 +From: Tony Cook <tony@develop-help.com> +Date: Tue, 3 Oct 2023 09:40:07 +1100 +Subject: [PATCH] win32: default the shell to cmd.exe in the Windows system + directory + +This prevents picking up cmd.exe from the current directory, or +even from the PATH. + +This protects against a privilege escalation attack where an attacker +in a separate session creates a cmd.exe in a directory where the +target account happens to have its current directory. +--- + t/win32/system.t | 30 ++++++++++++-------- + win32/win32.c | 71 +++++++++++++++++++++++++++++++++++++++++------- + 2 files changed, 79 insertions(+), 22 deletions(-) + +diff --git a/t/win32/system.t b/t/win32/system.t +index 939a02db55..c885059012 100644 +--- a/t/win32/system.t ++++ b/t/win32/system.t +@@ -82,6 +82,7 @@ close $F; + chdir($testdir); + END { + chdir($cwd) && rmtree("$cwd/$testdir") if -d "$cwd/$testdir"; ++ unlink "cmd.exe"; + } + if (open(my $EIN, "$cwd/win32/${exename}_exe.uu")) { + note "Unpacking $exename.exe"; +@@ -104,21 +105,20 @@ else { + } + note "Compiling $exename.c"; + note "$Config{cc} $Config{ccflags} $exename.c"; +- if (system("$Config{cc} $Config{ccflags} $minus_o $exename.c >log 2>&1") != 0) { ++ if (system("$Config{cc} $Config{ccflags} $minus_o $exename.c >log 2>&1") != 0 || ++ !-f "$exename.exe") { + note "Could not compile $exename.c, status $?"; +- note "Where is your C compiler?"; +- skip_all "can't build test executable"; +- } +- unless (-f "$exename.exe") { +- if (open(LOG,'<log')) +- { +- while(<LOG>) { +- note $_; +- } +- } ++ note "Where is your C compiler?"; ++ if (open(LOG,'<log')) ++ { ++ while(<LOG>) { ++ note $_; ++ } ++ } + else { +- warn "Cannot open log (in $testdir):$!"; ++ warn "Cannot open log (in $testdir):$!"; + } ++ skip_all "can't build test executable"; + } + } + copy("$plxname.bat","$plxname.cmd"); +@@ -128,6 +128,12 @@ unless (-x "$testdir/$exename.exe") { + skip_all "can't build test executable"; + } + ++# test we only look for cmd.exe in the standard place ++delete $ENV{PERLSHELL}; ++copy("$testdir/$exename.exe", "$testdir/cmd.exe") or die $!; ++copy("$testdir/$exename.exe", "cmd.exe") or die $!; ++$ENV{PATH} = qq("$testdir";$ENV{PATH}); ++ + open my $T, "$^X -I../lib -w win32/system_tests |" + or die "Can't spawn win32/system_tests: $!"; + my $expect; +diff --git a/win32/win32.c b/win32/win32.c +index 94248ca168..5d54cf8d4a 100644 +--- a/win32/win32.c ++++ b/win32/win32.c +@@ -117,7 +117,7 @@ static char* win32_get_xlib(const char *pl, + + static BOOL has_shell_metachars(const char *ptr); + static long tokenize(const char *str, char **dest, char ***destv); +-static void get_shell(void); ++static int get_shell(void); + static char* find_next_space(const char *s); + static int do_spawn2(pTHX_ const char *cmd, int exectype); + static int do_spawn2_handles(pTHX_ const char *cmd, int exectype, +@@ -600,7 +600,13 @@ tokenize(const char *str, char **dest, char ***destv) + return items; + } + +-static void ++static const char ++cmd_opts[] = "/x/d/c"; ++ ++static const char ++shell_cmd[] = "cmd.exe"; ++ ++static int + get_shell(void) + { + dTHX; +@@ -612,12 +618,53 @@ get_shell(void) + * interactive use (which is what most programs look in COMSPEC + * for). + */ +- const char* defaultshell = "cmd.exe /x/d/c"; +- const char *usershell = PerlEnv_getenv("PERL5SHELL"); +- w32_perlshell_items = tokenize(usershell ? usershell : defaultshell, +- &w32_perlshell_tokens, +- &w32_perlshell_vec); ++ const char *shell = PerlEnv_getenv("PERL5SHELL"); ++ if (shell) { ++ w32_perlshell_items = tokenize(shell, ++ &w32_perlshell_tokens, ++ &w32_perlshell_vec); ++ } ++ else { ++ /* tokenize does some Unix-ish like things like ++ \\ escaping that don't work well here ++ */ ++ char shellbuf[MAX_PATH]; ++ UINT len = GetSystemDirectoryA(shellbuf, sizeof(shellbuf)); ++ if (len == 0) { ++ translate_to_errno(); ++ return -1; ++ } ++ else if (len >= MAX_PATH) { ++ /* buffer too small */ ++ errno = E2BIG; ++ return -1; ++ } ++ if (shellbuf[len-1] != '\\') { ++ my_strlcat(shellbuf, "\\", sizeof(shellbuf)); ++ ++len; ++ } ++ if (len + sizeof(shell_cmd) > sizeof(shellbuf)) { ++ errno = E2BIG; ++ return -1; ++ } ++ my_strlcat(shellbuf, shell_cmd, sizeof(shellbuf)); ++ len += sizeof(shell_cmd)-1; ++ ++ Newx(w32_perlshell_vec, 3, char *); ++ Newx(w32_perlshell_tokens, len + 1 + sizeof(cmd_opts), char); ++ ++ my_strlcpy(w32_perlshell_tokens, shellbuf, len+1); ++ my_strlcpy(w32_perlshell_tokens + len +1, cmd_opts, ++ sizeof(cmd_opts)); ++ ++ w32_perlshell_vec[0] = w32_perlshell_tokens; ++ w32_perlshell_vec[1] = w32_perlshell_tokens + len + 1; ++ w32_perlshell_vec[2] = NULL; ++ ++ w32_perlshell_items = 2; ++ } + } ++ return 0; + } + + int +@@ -635,7 +682,9 @@ Perl_do_aspawn(pTHX_ SV *really, SV **mark, SV **sp) + if (sp <= mark) + return -1; + +- get_shell(); ++ if (get_shell() < 0) ++ return -1; ++ + Newx(argv, (sp - mark) + w32_perlshell_items + 2, const char*); + + if (SvNIOKp(*(mark+1)) && !SvPOKp(*(mark+1))) { +@@ -765,7 +814,8 @@ do_spawn2_handles(pTHX_ const char *cmd, int exectype, const int *handles) + if (needToTry) { + char **argv; + int i = -1; +- get_shell(); ++ if (get_shell() < 0) ++ return -1; + Newx(argv, w32_perlshell_items + 2, char*); + while (++i < w32_perlshell_items) + argv[i] = w32_perlshell_vec[i]; +@@ -3482,7 +3532,8 @@ win32_pipe(int *pfd, unsigned int size, int mode) + DllExport PerlIO* + win32_popenlist(const char *mode, IV narg, SV **args) + { +- get_shell(); ++ if (get_shell() < 0) ++ return NULL; + + return do_popen(mode, NULL, narg, args); + } +-- +2.33.0 + |