[Lldb-commits] [lldb] r243511 - When debugserver fails to attach to a process on a Darwin

Jason Molenda jmolenda at apple.com
Tue Jul 28 18:42:16 PDT 2015


Author: jmolenda
Date: Tue Jul 28 20:42:16 2015
New Revision: 243511

URL: http://llvm.org/viewvc/llvm-project?rev=243511&view=rev
Log:
When debugserver fails to attach to a process on a Darwin
system, make a couple of additional checks to see if the
attach was denied via the System Integrity Protection that
is new in Mac OS X 10.11.  If so, return a special E87
error code to indicate this to lldb.

Up in lldb, if we receive the E87 error code, be specific
about why the attach failed.

Also detect the more common case of general attach failure
and print a better error message than "lost connection".

I believe this code will all build on Mac OS X 10.10 systems.
It may not compile or run on earlier versions of the OS.
None of this should build on other non-darwin systems.

Modified:
    lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
    lldb/trunk/tools/debugserver/source/DNB.cpp
    lldb/trunk/tools/debugserver/source/DNB.h
    lldb/trunk/tools/debugserver/source/RNBRemote.cpp

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp?rev=243511&r1=243510&r2=243511&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp Tue Jul 28 20:42:16 2015
@@ -3804,8 +3804,28 @@ ProcessGDBRemote::AsyncThread (void *arg
                                             break;
                                         }
                                         case eStateInvalid:
-                                            process->SetExitStatus(-1, "lost connection");
-                                            break;
+                                        {
+                                            // Check to see if we were trying to attach and if we got back
+                                            // the "E87" error code from debugserver -- this indicates that
+                                            // the process is not debuggable.  Return a slightly more helpful
+                                            // error message about why the attach failed.
+                                            if (::strstr (continue_cstr, "vAttach") != NULL
+                                                && response.GetError() == 0x87)
+                                            {
+                                                process->SetExitStatus(-1, "cannot attach to process due to System Integrity Protection");
+                                            }
+                                            // E01 code from vAttach means that the attach failed
+                                            if (::strstr (continue_cstr, "vAttach") != NULL
+                                                && response.GetError() == 0x1)
+                                            {
+                                                process->SetExitStatus(-1, "unable to attach");
+                                            }
+                                            else
+                                            {
+                                                process->SetExitStatus(-1, "lost connection");
+                                            }
+                                                break;
+                                        }
 
                                         default:
                                             process->SetPrivateState (stop_state);

Modified: lldb/trunk/tools/debugserver/source/DNB.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/DNB.cpp?rev=243511&r1=243510&r2=243511&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/DNB.cpp (original)
+++ lldb/trunk/tools/debugserver/source/DNB.cpp Tue Jul 28 20:42:16 2015
@@ -455,6 +455,19 @@ DNBProcessLaunch (const char *path,
     return INVALID_NUB_PROCESS;
 }
 
+// If there is one process with a given name, return the pid for that process.
+nub_process_t
+DNBProcessGetPIDByName (const char *name)
+{
+    std::vector<struct kinfo_proc> matching_proc_infos;
+    size_t num_matching_proc_infos = GetAllInfosMatchingName(name, matching_proc_infos);
+    if (num_matching_proc_infos == 1)
+    {
+        return matching_proc_infos[0].kp_proc.p_pid;
+    }
+    return INVALID_NUB_PROCESS;
+}
+
 nub_process_t
 DNBProcessAttachByName (const char *name, struct timespec *timeout, char *err_str, size_t err_len)
 {

Modified: lldb/trunk/tools/debugserver/source/DNB.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/DNB.h?rev=243511&r1=243510&r2=243511&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/DNB.h (original)
+++ lldb/trunk/tools/debugserver/source/DNB.h Tue Jul 28 20:42:16 2015
@@ -51,6 +51,7 @@ nub_process_t   DNBProcessLaunch
                                          char *err_str, 
                                          size_t err_len);
 
+nub_process_t   DNBProcessGetPIDByName  (const char *name);
 nub_process_t   DNBProcessAttach        (nub_process_t pid, struct timespec *timeout, char *err_str, size_t err_len);
 nub_process_t   DNBProcessAttachByName  (const char *name, struct timespec *timeout, char *err_str, size_t err_len);
 nub_process_t   DNBProcessAttachWait    (const char *wait_name, nub_launch_flavor_t launch_flavor, bool ignore_existing, struct timespec *timeout, useconds_t interval, char *err_str, size_t err_len, DNBShouldCancelCallback should_cancel = NULL, void *callback_data = NULL);

Modified: lldb/trunk/tools/debugserver/source/RNBRemote.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/RNBRemote.cpp?rev=243511&r1=243510&r2=243511&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/RNBRemote.cpp (original)
+++ lldb/trunk/tools/debugserver/source/RNBRemote.cpp Tue Jul 28 20:42:16 2015
@@ -141,6 +141,23 @@ decode_uint64 (const char *p, int base,
 
 extern void ASLLogCallback(void *baton, uint32_t flags, const char *format, va_list args);
 
+#if defined (__APPLE__)
+// from System.framework/Versions/B/PrivateHeaders/sys/codesign.h
+extern "C" {
+#define CS_OPS_STATUS           0       /* return status */
+#define CS_RESTRICT             0x0000800       /* tell dyld to treat restricted */
+int csops(pid_t pid, unsigned int  ops, void * useraddr, size_t usersize);
+
+// from rootless.h
+bool rootless_allows_task_for_pid (pid_t pid);
+
+// from sys/csr.h
+typedef uint32_t csr_config_t;
+#define CSR_ALLOW_TASK_FOR_PID            (1 << 2)
+int csr_check(csr_config_t mask);
+}
+#endif
+
 RNBRemote::RNBRemote () :
     m_ctx (),
     m_comm (),
@@ -3603,13 +3620,14 @@ RNBRemote::HandlePacket_v (const char *p
     }
     else if (strstr (p, "vAttach") == p)
     {
-        nub_process_t attach_pid = INVALID_NUB_PROCESS;
+        nub_process_t attach_pid = INVALID_NUB_PROCESS;        // attach_pid will be set to 0 if the attach fails
+        nub_process_t pid_attaching_to = INVALID_NUB_PROCESS;  // pid_attaching_to is the original pid specified
         char err_str[1024]={'\0'};
+        std::string attach_name;
         
         if (strstr (p, "vAttachWait;") == p)
         {
             p += strlen("vAttachWait;");
-            std::string attach_name;
             if (!GetProcessNameFrom_vAttach(p, attach_name))
             {
                 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'vAttachWait' pkt");
@@ -3621,7 +3639,6 @@ RNBRemote::HandlePacket_v (const char *p
         else if (strstr (p, "vAttachOrWait;") == p)
         {
             p += strlen("vAttachOrWait;");
-            std::string attach_name;
             if (!GetProcessNameFrom_vAttach(p, attach_name))
             {
                 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'vAttachOrWait' pkt");
@@ -3632,7 +3649,6 @@ RNBRemote::HandlePacket_v (const char *p
         else if (strstr (p, "vAttachName;") == p)
         {
             p += strlen("vAttachName;");
-            std::string attach_name;
             if (!GetProcessNameFrom_vAttach(p, attach_name))
             {
                 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'vAttachName' pkt");
@@ -3645,13 +3661,13 @@ RNBRemote::HandlePacket_v (const char *p
         {
             p += strlen("vAttach;");
             char *end = NULL;
-            attach_pid = static_cast<int>(strtoul (p, &end, 16));    // PID will be in hex, so use base 16 to decode
+            pid_attaching_to = static_cast<int>(strtoul (p, &end, 16));    // PID will be in hex, so use base 16 to decode
             if (p != end && *end == '\0')
             {
                 // Wait at most 30 second for attach
                 struct timespec attach_timeout_abstime;
                 DNBTimer::OffsetTimeOfDay(&attach_timeout_abstime, 30, 0);
-                attach_pid = DNBProcessAttach(attach_pid, &attach_timeout_abstime, err_str, sizeof(err_str));
+                attach_pid = DNBProcessAttach(pid_attaching_to, &attach_timeout_abstime, err_str, sizeof(err_str));
             }
         }
         else
@@ -3675,6 +3691,44 @@ RNBRemote::HandlePacket_v (const char *p
                 m_ctx.LaunchStatus().SetErrorString(err_str);
             else
                 m_ctx.LaunchStatus().SetErrorString("attach failed");
+
+#if defined (__APPLE__)
+            if (pid_attaching_to == INVALID_NUB_PROCESS && !attach_name.empty())
+            {
+                pid_attaching_to = DNBProcessGetPIDByName (attach_name.c_str());
+            }
+            if (pid_attaching_to != INVALID_NUB_PROCESS && strcmp (err_str, "No such process") != 0)
+            {
+                // csr_check(CSR_ALLOW_TASK_FOR_PID) will be nonzero if System Integrity Protection is in effect.
+                if (csr_check(CSR_ALLOW_TASK_FOR_PID) != 0)
+                {
+                    bool attach_failed_due_to_sip = false;
+                    
+                    if (rootless_allows_task_for_pid (pid_attaching_to) == 0)
+                    {
+                        attach_failed_due_to_sip = true;
+                    }
+
+                    if (attach_failed_due_to_sip == false)
+                    {
+                        int csops_flags = 0;
+                        int retval = ::csops (pid_attaching_to, CS_OPS_STATUS, &csops_flags, sizeof (csops_flags));
+                        if (retval != -1 && (csops_flags & CS_RESTRICT))
+                        {
+                            attach_failed_due_to_sip = true;
+                        }
+                    }
+                    if (attach_failed_due_to_sip)
+                    {
+                        SendPacket ("E87");  // E87 is the magic value which says that we are not allowed to attach
+                        DNBLogError ("Attach failed because process does not allow attaching: \"%s\".", err_str);
+                        return rnb_err;
+                    }
+                }
+            }
+                
+#endif
+
             SendPacket ("E01");  // E01 is our magic error value for attach failed.
             DNBLogError ("Attach failed: \"%s\".", err_str);
             return rnb_err;





More information about the lldb-commits mailing list