mirror of
https://github.com/intel/llvm.git
synced 2026-01-16 05:32:28 +08:00
Add test for denied process attach by pid and fix found bugs in Process/ProcessPOSIX.cpp
and FreeBSD/ProcessMonitor. http://reviews.llvm.org/D6240 llvm-svn: 222372
This commit is contained in:
@@ -1115,14 +1115,13 @@ ProcessMonitor::AttachOpThread(void *arg)
|
||||
{
|
||||
AttachArgs *args = static_cast<AttachArgs*>(arg);
|
||||
|
||||
if (!Attach(args))
|
||||
return NULL;
|
||||
Attach(args);
|
||||
|
||||
ServeOperation(args);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
ProcessMonitor::Attach(AttachArgs *args)
|
||||
{
|
||||
lldb::pid_t pid = args->m_pid;
|
||||
@@ -1134,27 +1133,24 @@ ProcessMonitor::Attach(AttachArgs *args)
|
||||
{
|
||||
args->m_error.SetErrorToGenericError();
|
||||
args->m_error.SetErrorString("Attaching to process 1 is not allowed.");
|
||||
goto FINISH;
|
||||
return;
|
||||
}
|
||||
|
||||
// Attach to the requested process.
|
||||
if (PTRACE(PT_ATTACH, pid, NULL, 0) < 0)
|
||||
{
|
||||
args->m_error.SetErrorToErrno();
|
||||
goto FINISH;
|
||||
return;
|
||||
}
|
||||
|
||||
int status;
|
||||
if ((status = waitpid(pid, NULL, 0)) < 0)
|
||||
{
|
||||
args->m_error.SetErrorToErrno();
|
||||
goto FINISH;
|
||||
return;
|
||||
}
|
||||
|
||||
process.SendMessage(ProcessMessage::Attach(pid));
|
||||
|
||||
FINISH:
|
||||
return args->m_error.Success();
|
||||
}
|
||||
|
||||
size_t
|
||||
|
||||
@@ -290,7 +290,7 @@ private:
|
||||
static void *
|
||||
AttachOpThread(void *args);
|
||||
|
||||
static bool
|
||||
static void
|
||||
Attach(AttachArgs *args);
|
||||
|
||||
static void
|
||||
|
||||
@@ -341,6 +341,11 @@ ProcessPOSIX::DoDestroy()
|
||||
{
|
||||
assert(m_monitor);
|
||||
m_exit_now = true;
|
||||
if (GetID() == LLDB_INVALID_PROCESS_ID)
|
||||
{
|
||||
error.SetErrorString("invalid process id");
|
||||
return error;
|
||||
}
|
||||
if (!m_monitor->Kill())
|
||||
{
|
||||
error.SetErrorToErrno();
|
||||
|
||||
@@ -3397,14 +3397,13 @@ Process::Attach (ProcessAttachInfo &attach_info)
|
||||
else
|
||||
{
|
||||
if (GetID() != LLDB_INVALID_PROCESS_ID)
|
||||
{
|
||||
SetID (LLDB_INVALID_PROCESS_ID);
|
||||
const char *error_string = error.AsCString();
|
||||
if (error_string == NULL)
|
||||
error_string = "attach failed";
|
||||
|
||||
SetExitStatus(-1, error_string);
|
||||
}
|
||||
const char *error_string = error.AsCString();
|
||||
if (error_string == NULL)
|
||||
error_string = "attach failed";
|
||||
|
||||
SetExitStatus(-1, error_string);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
LEVEL = ../../../make
|
||||
|
||||
CXX_SOURCES := main.cpp
|
||||
|
||||
EXE := AttachDenied
|
||||
|
||||
include $(LEVEL)/Makefile.rules
|
||||
@@ -0,0 +1,49 @@
|
||||
"""
|
||||
Test denied process attach.
|
||||
"""
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import tempfile
|
||||
import unittest2
|
||||
import lldb
|
||||
from lldbtest import *
|
||||
|
||||
exe_name = 'AttachDenied' # Must match Makefile
|
||||
|
||||
class AttachDeniedTestCase(TestBase):
|
||||
|
||||
mydir = TestBase.compute_mydir(__file__)
|
||||
|
||||
@skipIfWindows
|
||||
def test_attach_to_process_by_id_denied(self):
|
||||
"""Test attach by process id denied"""
|
||||
|
||||
self.buildDefault()
|
||||
exe = os.path.join(os.getcwd(), exe_name)
|
||||
|
||||
temp_dir = tempfile.mkdtemp()
|
||||
self.addTearDownHook(lambda: shutil.rmtree(temp_dir))
|
||||
|
||||
# Use named pipe as a synchronization point between test and inferior.
|
||||
pid_pipe_path = os.path.join(temp_dir, "pid_pipe")
|
||||
os.mkfifo(pid_pipe_path)
|
||||
|
||||
# Spawn a new process
|
||||
popen = self.spawnSubprocess(exe, [pid_pipe_path])
|
||||
self.addTearDownHook(self.cleanupSubprocesses)
|
||||
|
||||
pid_pipe = open(pid_pipe_path, 'r')
|
||||
self.addTearDownHook(lambda: pid_pipe.close())
|
||||
pid = pid_pipe.read()
|
||||
|
||||
self.expect('process attach -p ' + pid,
|
||||
startstr = 'error: attach failed:',
|
||||
error = True)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import atexit
|
||||
lldb.SBDebugger.Initialize()
|
||||
atexit.register(lambda: lldb.SBDebugger.Terminate())
|
||||
unittest2.main()
|
||||
@@ -0,0 +1,93 @@
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#if defined(PTRACE_ATTACH)
|
||||
#define ATTACH_REQUEST PTRACE_ATTACH
|
||||
#define DETACH_REQUEST PTRACE_DETACH
|
||||
#elif defined(PT_ATTACH)
|
||||
#define ATTACH_REQUEST PT_ATTACH
|
||||
#define DETACH_REQUEST PT_DETACH
|
||||
#else
|
||||
#error "Unsupported platform"
|
||||
#endif
|
||||
|
||||
bool writePid (const char* file_name, const pid_t pid)
|
||||
{
|
||||
int fd = open (file_name, O_WRONLY);
|
||||
if (fd == -1)
|
||||
{
|
||||
fprintf (stderr, "open(%s) failed: %s\n", file_name, strerror (errno));
|
||||
return false;
|
||||
}
|
||||
char buffer[64];
|
||||
snprintf (buffer, sizeof(buffer), "%ld", (long)pid);
|
||||
|
||||
bool res = true;
|
||||
if (write (fd, buffer, strlen (buffer)) == -1)
|
||||
{
|
||||
fprintf (stderr, "write(%s) failed: %s\n", buffer, strerror (errno));
|
||||
res = false;
|
||||
}
|
||||
close (fd);
|
||||
return res;
|
||||
}
|
||||
|
||||
void sigterm_handler (int)
|
||||
{
|
||||
}
|
||||
|
||||
int main (int argc, char const *argv[])
|
||||
{
|
||||
if (argc < 2)
|
||||
{
|
||||
fprintf (stderr, "invalid number of command line arguments\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
const pid_t pid = fork ();
|
||||
if (pid == -1)
|
||||
{
|
||||
fprintf (stderr, "fork failed: %s\n", strerror (errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pid > 0)
|
||||
{
|
||||
// Make pause call to return when SIGTERM is received.
|
||||
signal (SIGTERM, sigterm_handler);
|
||||
if (ptrace (ATTACH_REQUEST, pid, NULL, 0) == -1)
|
||||
{
|
||||
fprintf (stderr, "ptrace(ATTACH) failed: %s\n", strerror (errno));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (writePid (argv[1], pid))
|
||||
pause (); // Waiting for the debugger trying attach to the child.
|
||||
|
||||
if (ptrace (DETACH_REQUEST, pid, NULL, 0) != 0)
|
||||
fprintf (stderr, "ptrace(DETACH) failed: %s\n", strerror (errno));
|
||||
}
|
||||
|
||||
kill (pid, SIGTERM);
|
||||
int status = 0;
|
||||
if (waitpid (pid, &status, 0) == -1)
|
||||
fprintf (stderr, "waitpid failed: %s\n", strerror (errno));
|
||||
}
|
||||
else
|
||||
{
|
||||
// child inferior.
|
||||
pause ();
|
||||
}
|
||||
|
||||
printf ("Exiting now\n");
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user