Cygwin: kill(1): disallow killing process using raw Windows PID

This may end up killing the wrong process.  Only allow Cygwin PID.

Slightly clean up code: Remove outdated W95 considerations.  Fix
a bug in commandline argument processing.

Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
Corinna Vinschen 2019-02-02 15:00:39 +01:00
parent 448cf5aa4b
commit 8de660271f
1 changed files with 22 additions and 19 deletions

View File

@ -152,29 +152,31 @@ get_debug_priv (void)
} }
static void __stdcall static void __stdcall
forcekill (int pid, int sig, int wait) forcekill (pid_t pid, int sig, int wait)
{ {
// try to acquire SeDebugPrivilege /* try to acquire SeDebugPrivilege */
get_debug_priv(); get_debug_priv();
external_pinfo *p = NULL; external_pinfo *p = NULL;
/* cygwin_internal misinterprets negative pids (Win9x pids) */
if (pid > 0)
p = (external_pinfo *) cygwin_internal (CW_GETPINFO_FULL, pid); p = (external_pinfo *) cygwin_internal (CW_GETPINFO_FULL, pid);
DWORD dwpid = p ? p->dwProcessId : (DWORD) pid; if (!p)
HANDLE h = OpenProcess (PROCESS_TERMINATE, FALSE, (DWORD) dwpid); {
fprintf (stderr, "%s: %d: No such process\n", prog_name, pid);
return;
}
DWORD dwpid = p->dwProcessId;
HANDLE h = OpenProcess (PROCESS_TERMINATE, FALSE, dwpid);
if (!h) if (!h)
{ {
if (!wait || GetLastError () != ERROR_INVALID_PARAMETER) if (!wait || GetLastError () != ERROR_INVALID_PARAMETER)
fprintf (stderr, "%s: couldn't open pid %u\n", fprintf (stderr, "%s: couldn't open pid %u\n", prog_name, dwpid);
prog_name, (unsigned) dwpid);
return; return;
} }
if (!wait || WaitForSingleObject (h, 200) != WAIT_OBJECT_0) if (!wait || WaitForSingleObject (h, 200) != WAIT_OBJECT_0)
if (sig && !TerminateProcess (h, sig << 8) if (sig && !TerminateProcess (h, sig << 8)
&& WaitForSingleObject (h, 200) != WAIT_OBJECT_0) && WaitForSingleObject (h, 200) != WAIT_OBJECT_0)
fprintf (stderr, "%s: couldn't kill pid %u, %u\n", fprintf (stderr, "%s: couldn't kill pid %u, %u\n",
prog_name, (unsigned) dwpid, (unsigned int) GetLastError ()); prog_name, dwpid, GetLastError ());
CloseHandle (h); CloseHandle (h);
} }
@ -232,11 +234,8 @@ main (int argc, char **argv)
print_version (); print_version ();
break; break;
case '?': case '?':
if (gotasig) if (gotasig) /* this is a negative pid, go ahead */
{
--optind;
goto out; goto out;
}
optreset = 1; optreset = 1;
optind = 1 + av - argv; optind = 1 + av - argv;
gotasig = *av + 1; gotasig = *av + 1;
@ -252,18 +251,22 @@ out:
test_for_unknown_sig (sig, gotasig); test_for_unknown_sig (sig, gotasig);
argv += optind; argv += optind;
if (*argv == 0)
{
fprintf (stderr, "%s: not enough arguments\n", prog_name);
return 1;
}
while (*argv != NULL) while (*argv != NULL)
{ {
if (!pid) if (!pid)
pid = strtoll (*argv, &p, 10); pid = strtoll (*argv, &p, 10);
if (*p != '\0' /* INT_MIN <= pid <= INT_MAX. -f only takes positive pids. */
|| (!force && (pid < INT_MIN || pid > INT_MAX)) if (*p != '\0' || pid < (force ? 1 : INT_MIN) || pid > INT_MAX)
|| (force && (pid <= 0 || pid > UINT_MAX)))
{ {
fprintf (stderr, "%s: illegal pid: %s\n", prog_name, *argv); fprintf (stderr, "%s: illegal pid: %s\n", prog_name, *argv);
ret = 1; ret = 1;
} }
else if (pid <= INT_MAX && kill ((pid_t) pid, sig) == 0) else if (kill ((pid_t) pid, sig) == 0)
{ {
if (force) if (force)
forcekill ((pid_t) pid, sig, 1); forcekill ((pid_t) pid, sig, 1);