Index: source/Plugins/Process/FreeBSD/ProcessMonitor.h =================================================================== --- source/Plugins/Process/FreeBSD/ProcessMonitor.h +++ source/Plugins/Process/FreeBSD/ProcessMonitor.h @@ -290,7 +290,7 @@ static void * AttachOpThread(void *args); - static bool + static void Attach(AttachArgs *args); static void Index: source/Plugins/Process/FreeBSD/ProcessMonitor.cpp =================================================================== --- source/Plugins/Process/FreeBSD/ProcessMonitor.cpp +++ source/Plugins/Process/FreeBSD/ProcessMonitor.cpp @@ -1115,14 +1115,13 @@ { AttachArgs *args = static_cast(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 @@ { 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 Index: source/Plugins/Process/POSIX/ProcessPOSIX.cpp =================================================================== --- source/Plugins/Process/POSIX/ProcessPOSIX.cpp +++ source/Plugins/Process/POSIX/ProcessPOSIX.cpp @@ -341,6 +341,11 @@ { 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(); Index: source/Target/Process.cpp =================================================================== --- source/Target/Process.cpp +++ source/Target/Process.cpp @@ -3397,14 +3397,13 @@ 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); } } } Index: test/functionalities/process_attach/attach_denied/Makefile =================================================================== --- /dev/null +++ test/functionalities/process_attach/attach_denied/Makefile @@ -0,0 +1,7 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +EXE := AttachDenied + +include $(LEVEL)/Makefile.rules Index: test/functionalities/process_attach/attach_denied/TestAttachDenied.py =================================================================== --- /dev/null +++ test/functionalities/process_attach/attach_denied/TestAttachDenied.py @@ -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() Index: test/functionalities/process_attach/attach_denied/main.cpp =================================================================== --- /dev/null +++ test/functionalities/process_attach/attach_denied/main.cpp @@ -0,0 +1,93 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#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; +}