Add test for denied process attach by pid and fix found bugs in Process/ProcessPOSIX.cpp
authorOleksiy Vyalov <ovyalov@google.com>
Wed, 19 Nov 2014 18:27:45 +0000 (18:27 +0000)
committerOleksiy Vyalov <ovyalov@google.com>
Wed, 19 Nov 2014 18:27:45 +0000 (18:27 +0000)
and FreeBSD/ProcessMonitor.

http://reviews.llvm.org/D6240

llvm-svn: 222372

lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.h
lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
lldb/source/Target/Process.cpp
lldb/test/functionalities/process_attach/attach_denied/Makefile [new file with mode: 0644]
lldb/test/functionalities/process_attach/attach_denied/TestAttachDenied.py [new file with mode: 0644]
lldb/test/functionalities/process_attach/attach_denied/main.cpp [new file with mode: 0644]

index dc30ebd..84e35ba 100644 (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
index 68bf2f8..935fd85 100644 (file)
@@ -290,7 +290,7 @@ private:
     static void *
     AttachOpThread(void *args);
 
-    static bool
+    static void
     Attach(AttachArgs *args);
 
     static void
index 702ff80..0e5ab5a 100644 (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();
index f565011..3b50799 100644 (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);
             }
         }
     }
diff --git a/lldb/test/functionalities/process_attach/attach_denied/Makefile b/lldb/test/functionalities/process_attach/attach_denied/Makefile
new file mode 100644 (file)
index 0000000..87600bb
--- /dev/null
@@ -0,0 +1,7 @@
+LEVEL = ../../../make
+
+CXX_SOURCES := main.cpp
+
+EXE := AttachDenied
+
+include $(LEVEL)/Makefile.rules
diff --git a/lldb/test/functionalities/process_attach/attach_denied/TestAttachDenied.py b/lldb/test/functionalities/process_attach/attach_denied/TestAttachDenied.py
new file mode 100644 (file)
index 0000000..1307481
--- /dev/null
@@ -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()
diff --git a/lldb/test/functionalities/process_attach/attach_denied/main.cpp b/lldb/test/functionalities/process_attach/attach_denied/main.cpp
new file mode 100644 (file)
index 0000000..0fc99f1
--- /dev/null
@@ -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;
+}