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:
Oleksiy Vyalov
2014-11-19 18:27:45 +00:00
parent 4325aaa6d9
commit 5d06474b29
7 changed files with 165 additions and 16 deletions

View File

@@ -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

View File

@@ -290,7 +290,7 @@ private:
static void *
AttachOpThread(void *args);
static bool
static void
Attach(AttachArgs *args);
static void

View File

@@ -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();

View File

@@ -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);
}
}
}

View File

@@ -0,0 +1,7 @@
LEVEL = ../../../make
CXX_SOURCES := main.cpp
EXE := AttachDenied
include $(LEVEL)/Makefile.rules

View File

@@ -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()

View File

@@ -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;
}