summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2016-07-07 07:14:58 -0700
committerKaz Kylheku <kaz@kylheku.com>2020-10-11 09:06:00 -0700
commitd82e2f3c1412acda563eaf11ac7aeed0e58f5687 (patch)
tree943562830bc570a0c2f89e624f0d286550d0d566
parent7a5bbf7e69d340730688ce417cce858e4dc1af74 (diff)
downloadcygnal-d82e2f3c1412acda563eaf11ac7aeed0e58f5687.tar.gz
cygnal-d82e2f3c1412acda563eaf11ac7aeed0e58f5687.tar.bz2
cygnal-d82e2f3c1412acda563eaf11ac7aeed0e58f5687.zip
More secure way of obtaining command interpreter.
Instead of relying on the COMSPEC environment variable, what we can do is assume that the program is called "cmd.exe", and then look for it in the directory reported by the GetSystemDirectoryA Win32 function in kernel32.dll. * winsup/cygwin/path.h (get_cmd_exe_path): New function declared. * winsup/cygwin/spawn.cc (av::setup): Use get_cmd_exe_path instead of getenv("COMSPEC"). (cmd_exe_path): New static variable. (init_cmd_exe_path): New static function. (get_cmd_exe_path): New function. * winsup/cygwin/syscalls.cc (system, getusershell, popen): Use get_cmd_exe_path instead of getenv("COMSPEC").
-rw-r--r--winsup/cygwin/path.h1
-rw-r--r--winsup/cygwin/spawn.cc27
-rw-r--r--winsup/cygwin/syscalls.cc6
3 files changed, 30 insertions, 4 deletions
diff --git a/winsup/cygwin/path.h b/winsup/cygwin/path.h
index b94f13df8..16a1490d7 100644
--- a/winsup/cygwin/path.h
+++ b/winsup/cygwin/path.h
@@ -447,3 +447,4 @@ int normalize_posix_path (const char *, char *, char *&);
PUNICODE_STRING __reg3 get_nt_native_path (const char *, UNICODE_STRING&, bool);
int __reg3 symlink_worker (const char *, path_conv &, bool);
+const char *get_cmd_exe_path();
diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc
index 0f6d48b23..5c67f10a6 100644
--- a/winsup/cygwin/spawn.cc
+++ b/winsup/cygwin/spawn.cc
@@ -13,7 +13,9 @@ details. */
#include <sys/wait.h>
#include <wchar.h>
#include <ctype.h>
+#include <stdio.h>
#include <sys/cygwin.h>
+#include <pthread.h>
#include "cygerrno.h"
#include "security.h"
#include "sigproc.h"
@@ -1296,7 +1298,7 @@ av::setup (const char *prog_arg, path_conv& real_path, const char *ext,
}
if (ascii_strcasematch (ext, ".com"))
break;
- if ((pgm = getenv("COMSPEC")) == NULL) {
+ if ((pgm = const_cast<char *>(get_cmd_exe_path())) == NULL) {
set_errno (EOPNOTSUPP);
return -1;
}
@@ -1425,3 +1427,26 @@ __posix_spawn_execvpe (const char *path, char * const *argv, char *const *envp,
__posix_spawn_sem_release (sem, errno);
return -1;
}
+
+static const char *cmd_exe_path = NULL;
+
+static void init_cmd_exe_path(void)
+{
+ char sysdir[NT_MAX_PATH];
+ char cmdname[] = "cmd.exe";
+ unsigned int nchars;
+
+ if ((nchars = GetSystemDirectoryA(sysdir, sizeof sysdir)) < sizeof sysdir) {
+ unsigned int total = nchars + 1 + sizeof cmdname + 1;
+ char *path = static_cast<char *>(cmalloc_abort(HEAP_STR, total));
+ snprintf(path, total, "%s\\%s", sysdir, cmdname);
+ cmd_exe_path = path;
+ }
+}
+
+const char *get_cmd_exe_path()
+{
+ static pthread_once_t cmd_exe_once = PTHREAD_ONCE_INIT;
+ pthread_once (&cmd_exe_once, init_cmd_exe_path);
+ return cmd_exe_path;
+}
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index 68813d4c9..64c73c38d 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -2825,7 +2825,7 @@ system (const char *cmdstring)
int res = -1;
const char* command[4];
- const char *cmdexe = getenv("COMSPEC");
+ const char *cmdexe = get_cmd_exe_path();
if (cmdexe == NULL)
return res;
@@ -4383,7 +4383,7 @@ extern "C" char *
getusershell ()
{
if (shell_index == 0) {
- char *cmdexe = getenv("COMSPEC");
+ char *cmdexe = const_cast<char *>(get_cmd_exe_path());
if (cmdexe != NULL) {
shell_index = 1;
return cmdexe;
@@ -4428,7 +4428,7 @@ popen (const char *command, const char *in_type)
const char *type = in_type;
char fdopen_flags[3] = "\0\0";
int pipe_flags = 0;
- const char *cmdexe = getenv("COMSPEC");
+ const char *cmdexe = get_cmd_exe_path();
#define rw fdopen_flags[0]
#define bintext fdopen_flags[1]