fix 319235 --db-attach=yes is broken with Yama ptrace scoping enabled
On Ubuntu systems, ptrace_scoping could forbid a process to ptrace another.
This ptrace scoping was already handled for vgdb by using SET_PTRACER
(the valgrind process must be ptraced by vgdb when it is blocked
in a syscall).
set_ptracer is however also needed when the old mechanism --db-attach=yes
is used.
The following changes are done:
* make the set_ptracer logic callable outside gdbserver
* make set_ptracer less restrictive (i.e. allow all
  processes of the user to ptrace). This removes a limitation for vgdb.
* call the set_ptracer in the child launched for --db-attach=yes
* cleaned up the ptrace scope restriction message and doc as vgdb
  is now working properly by default, even with ptrace_scope enabled.



git-svn-id: svn://svn.valgrind.org/valgrind/trunk@13384 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/NEWS b/NEWS
index 7de23c4..e4f6768 100644
--- a/NEWS
+++ b/NEWS
@@ -222,6 +222,7 @@
 315959    [390] valgrind man page has bogus SGCHECK (and no BBV) OPTIONS section
 316144    [390] valgrind.1 manpage contains unknown ??? strings for some core option references
 316145    [390] callgrind command line options in manpage reference (unknown) callgrind manual
+319235    [390] --db-attach=yes is broken with Yama ptrace scoping enabled
 n-i-bz    [390] report error for vgdb snapshot requested before execution
 n-i-bz    [390] Some wrong command line options could be ignored
 n-i-bz    [390] same as 303624 (fixed in 3.8.0), but for x86 android
diff --git a/coregrind/m_debugger.c b/coregrind/m_debugger.c
index e53094b..1c967ef 100644
--- a/coregrind/m_debugger.c
+++ b/coregrind/m_debugger.c
@@ -35,6 +35,7 @@
 #include "pub_core_xarray.h"
 #include "pub_core_clientstate.h"
 #include "pub_core_debugger.h"
+#include "pub_core_gdbserver.h"
 #include "pub_core_libcbase.h"
 #include "pub_core_libcprint.h"
 #include "pub_core_libcproc.h"
@@ -363,6 +364,7 @@
 
    if (pid == 0) {
       /* child */
+      VG_(set_ptracer)();
       rc = VG_(ptrace)(VKI_PTRACE_TRACEME, 0, NULL, NULL);
       vg_assert(rc == 0);
       rc = VG_(kill)(VG_(getpid)(), VKI_SIGSTOP);
diff --git a/coregrind/m_gdbserver/remote-utils.c b/coregrind/m_gdbserver/remote-utils.c
index 8a9c969..59a698e 100644
--- a/coregrind/m_gdbserver/remote-utils.c
+++ b/coregrind/m_gdbserver/remote-utils.c
@@ -105,12 +105,7 @@
    return 0; // all is ok.
 }
 
-/* On systems that defines PR_SET_PTRACER, verify if ptrace_scope is
-   is permissive enough for vgdb. Otherwise, call set_ptracer.
-   This is especially aimed at Ubuntu >= 10.10 which has added
-   the ptrace_scope context. */
-static
-void set_ptracer(void)
+void VG_(set_ptracer)(void)
 {
 #ifdef PR_SET_PTRACER
    SysRes o;
@@ -132,11 +127,16 @@
       dlog(1, "ptrace_scope %c\n", ptrace_scope);
       if (ptrace_scope != '0') {
          /* insufficient default ptrace_scope.
-            Indicate to the kernel that we accept to be
-            ptraced by our vgdb. */
-         ret = VG_(prctl) (PR_SET_PTRACER, shared->vgdb_pid, 0, 0, 0);
-         dlog(1, "set_ptracer to vgdb_pid %d result %d\n",
-              shared->vgdb_pid, ret);
+            Indicate to the kernel that we accept to be ptraced. */
+#ifdef PR_SET_PTRACER_ANY
+         ret = VG_(prctl) (PR_SET_PTRACER, PR_SET_PTRACER_ANY, 0, 0, 0);
+         dlog(1, "set_ptracer to PR_SET_PTRACER_ANY result %d\n", ret);
+#else
+         ret = VG_(prctl) (PR_SET_PTRACER, 1, 0, 0, 0);
+         dlog(1, "set_ptracer to 1 result %d\n", ret);
+#endif
+         if (ret)
+            VG_(umsg)("error calling PR_SET_PTRACER, vgdb might block\n");
       }
    } else {
       dlog(0, "Could not read the ptrace_scope setting from %s\n",
@@ -181,7 +181,6 @@
          be reasonably sure someone is reading on the other
          side of the fifo. */
       if (!vgdb_state_looks_bad("bad?@ensure_write_remote_desc")) {
-         set_ptracer();
          write_remote_desc = open_fifo ("write", to_gdb, VKI_O_WRONLY);
       }
    }
@@ -293,7 +292,7 @@
 
    if (!mknod_done) {
       mknod_done++;
-
+      VG_(set_ptracer)();
       /*
        * Unlink just in case a previous process with the same PID had been
        * killed and hence Valgrind hasn't had the chance yet to remove these.
diff --git a/coregrind/pub_core_gdbserver.h b/coregrind/pub_core_gdbserver.h
index f4286c3..9cb06c9 100644
--- a/coregrind/pub_core_gdbserver.h
+++ b/coregrind/pub_core_gdbserver.h
@@ -53,6 +53,12 @@
 // gdbserver is then stopped (using VG_(gdbserver) (0))
 void VG_(gdbserver_exit) (ThreadId tid, VgSchedReturnCode tids_schedretcode);
 
+/* On systems that defines PR_SET_PTRACER, verify if ptrace_scope is
+   is permissive enough for vgdb or --db-attach=yes.
+   Otherwise, call set_ptracer.
+   This is especially aimed at Ubuntu >= 10.10 which has added
+   the ptrace_scope context. */
+void VG_(set_ptracer)(void);
 
 /* Called by low level to insert or remove a break or watch point.
    Break or watch point implementation is done using help from the tool.
diff --git a/coregrind/vgdb.c b/coregrind/vgdb.c
index fed0d92..dc3beda 100644
--- a/coregrind/vgdb.c
+++ b/coregrind/vgdb.c
@@ -101,14 +101,12 @@
 #if defined(PTRACEINVOKER)
 #include <sys/user.h>
 #if defined(VGO_linux)
-#  include <sys/prctl.h>
 #  include <linux/ptrace.h>
 #endif
 #endif
 
 
-// Outputs information for the user about ptrace_scope protection
-// or ptrace not working.
+// Outputs information for the user about ptrace not working.
 static void ptrace_restrictions_msg(void);
 
 static int debuglevel;
@@ -869,11 +867,7 @@
    // address pushed on the stack should ensure this is detected.
 
    /* Not yet attached. If problem, vgdb can abort,
-      no cleanup needed.
-
-      On Ubuntu>= 10.10, a /proc setting can disable ptrace.
-      So, Valgrind has to SET_PTRACER this vgdb. Once this
-      is done, this vgdb can ptrace the valgrind process. */
+      no cleanup needed. */
 
    DEBUG(1, "attach to 'main' pid %d\n", pid);
    if (!attach(pid, "attach main pid")) {
@@ -2049,27 +2043,6 @@
 static
 void ptrace_restrictions_msg(void)
 {
-#  ifdef PR_SET_PTRACER
-   const char *ptrace_scope_setting_file = "/proc/sys/kernel/yama/ptrace_scope";
-   int fd = -1;
-   char ptrace_scope = 'X';
-   fd = open (ptrace_scope_setting_file, O_RDONLY, 0);
-   if (fd >= 0 && (read (fd, &ptrace_scope, 1) == 1) && (ptrace_scope != '0')) {
-      fprintf (stderr,
-               "Note: your kernel restricts ptrace invoker using %s\n"
-               "vgdb will only be able to attach to a Valgrind process\n"
-               "blocked in a system call *after* an initial successful attach\n",
-               ptrace_scope_setting_file);
-   } else if (ptrace_scope == 'X') {
-      DEBUG (1, 
-             "PR_SET_PTRACER defined"
-             " but could not determine ptrace scope from %s\n",
-             ptrace_scope_setting_file);
-   }
-   if (fd >= 0)
-      close (fd);
-#  endif
-
 #  ifndef PTRACEINVOKER
    fprintf(stderr, 
            "Note: ptrace invoker not implemented\n"
diff --git a/docs/xml/manual-core-adv.xml b/docs/xml/manual-core-adv.xml
index ff17351..870996f 100644
--- a/docs/xml/manual-core-adv.xml
+++ b/docs/xml/manual-core-adv.xml
@@ -995,7 +995,8 @@
 
      <para>Connecting to or interrupting a Valgrind process blocked in
      a system call requires the "ptrace" system call to be usable.
-     This may be disabled in your kernel for security reasons.</para>
+     This may be disabled in your kernel for security reasons.
+     </para>
 
      <para>When running your program, Valgrind's scheduler
      periodically checks whether there is any work to be handled by
@@ -1043,24 +1044,9 @@
      <para>Ubuntu versions 10.10 and later may restrict the scope of
      ptrace to the children of the process calling ptrace.  As the
      Valgrind process is not a child of vgdb, such restricted scoping
-     causes the ptrace calls to fail.  To avoid that, when Valgrind
-     gdbserver receives the first packet from a vgdb, it calls
-     <computeroutput>prctl(PR_SET_PTRACER, vgdb_pid, 0, 0,
-     0)</computeroutput> to ensure vgdb can reliably use ptrace.
-     Once <computeroutput>vgdb_pid</computeroutput> has been marked as
-     a ptracer, vgdb can then properly force the invocation of
-     Valgrind gdbserver when needed.  To ensure the vgdb is set as a
-     ptracer before the Valgrind process gets blocked in a system
-     call, connect your GDB to the Valgrind gdbserver at startup by
-     passing <option>--vgdb-error=0</option> to Valgrind.</para>
-
-     <para>Note that
-     this "set ptracer" technique does not solve the problem in the
-     case where a standalone vgdb process wants to connect to the
-     gdbserver, since the first command to be sent by a standalone
-     vgdb must wake up the Valgrind process before Valgrind gdbserver
-     will mark vgdb as a ptracer.
-     </para>
+     causes the ptrace calls to fail.  To avoid that, Valgrind will
+     automatically allow all processes belonging to the same userid to
+     "ptrace" a Valgrind process, by using PR_SET_PTRACER.</para>
 
      <para>Unblocking processes blocked in system calls is not
      currently implemented on Mac OS X and Android.  So you cannot
diff --git a/gdbserver_tests/make_local_links b/gdbserver_tests/make_local_links
index 8e50093..73a2f00 100755
--- a/gdbserver_tests/make_local_links
+++ b/gdbserver_tests/make_local_links
@@ -99,8 +99,7 @@
 # if ptrace not implemented in vgdb or OS restricts the initial attach,
 # some tests would block for a loooonnnng time.
 if gdbserver_tests/vgdb --help 2>&1 |
-    grep -e 'ptrace invoker not implemented' \
-         -e 'kernel restricts ptrace invoker' > /dev/null
+    grep -e 'ptrace invoker not implemented' > /dev/null
 then
     rm -f gdbserver_tests/vgdb.ptraceinvoker
 else