<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On 9 January 2015 at 23:11, Kees Cook <span dir="ltr"><<a href="mailto:kees@outflux.net" target="_blank">kees@outflux.net</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hi Bryce,<br>
<span class=""><br>
On Fri, Jan 09, 2015 at 01:24:39PM -0800, Bryce Harrington wrote:<br>
> On Fri, Jan 09, 2015 at 11:33:57AM +0100, Marek Chalupa wrote:<br>
> > Yeah and one more thing:<br>
><br>
> Btw, any reason this is offlist?<br>
><br></span></blockquote><div><br></div><div>No, just clicked on the wrong button (reply instead of reply to all), sorry. I just resend it.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span class="">
> > PR_SET_PTRACER is since Linux 3.4. What happens with older kernels or with<br>
> > Yama disabled?<br>
><br>
> If I understand how the prctl handlers work, if Yama is not loaded then<br>
> PR_SET_PTRACER will just be ignored if it is set.  I'll cc author to be<br>
> sure.<br>
<br>
</span>The prctl will return EINVAL if Yama is not loaded. (i.e. just ignore the<br>
prctl).<br>
<span class=""><br>
><br>
> Good point on pre-3.4 kernels.  I'll #ifdef around it.<br>
<br>
</span>I recommend:<br>
<br>
#include <sys/prctl.h><br>
#ifndef PR_SET_PTRACER<br>
# define PR_SET_PTRACER 0x59616d61<br>
#endif<br>
<span class=""><br>
<br>
><br>
> > I suppose that prctl call fails but since the return code is not used, it<br>
> > is ignored and everything continues like before without prctl, right?<br>
><br>
> >From my understanding of yama_lsm.c, there wouldn't be an error code in<br>
> the case that Yama was not enabled (i.e. rc = 0).  With Yama enabled, it<br>
> looks like prctl will error if it can't get the tracer task, or in out<br>
> of memory conditions.<br>
><br>
> I suppose if the prctl call fails, we could bail out at that point.  We<br>
> wouldn't know whether a debugger is attached or not though, so perhaps<br>
> in that case is_debugger_attached() should return 0?  Looks like we<br>
> return 0 in other error cases.<br>
<br>
</span>If the prctl fails, there's no Yama, so no need for the prctl, so it can be<br>
ignored.<br>
<div><div class="h5"><br>
><br>
> Thanks for the review; will re-roll the patchset.<br>
><br>
> Bryce<br>
><br>
> > Cheers,<br>
> > Marek<br>
> ><br>
> > On 9 January 2015 at 11:26, Marek Chalupa <<a href="mailto:mchqwerty@gmail.com">mchqwerty@gmail.com</a>> wrote:<br>
> ><br>
> > ><br>
> > ><br>
> > > On 7 January 2015 at 21:34, Bryce Harrington <<a href="mailto:bryce@osg.samsung.com">bryce@osg.samsung.com</a>><br>
> > > wrote:<br>
> > ><br>
> > >> This fixes a regression in the testsuite since c3653f7f, where four of<br>
> > >> the timeout tests fail with "Timeouts suppressed" messages.<br>
> > >><br>
> > >> The timeouts are being suppressed because the testsuite is erroneously<br>
> > >> detecting that a debugger is attached.  This detection mechanism<br>
> > >> (adopted from libinput) uses ptrace to test if there is a debugger<br>
> > >> parent process that can be attached.  Unfortunately, this is an<br>
> > >> unreliable test: Kernel security policies exist to restrict the scope of<br>
> > >> ptrace to prevent processes from snooping on one another.[1] This<br>
> > >> security policy is set as the default on Ubuntu, and potentially other<br>
> > >> Linux distributions.[2]<br>
> > >><br>
> > >> The Yama documentation suggests, "For software that has defined<br>
> > >> application-specific relationships between a debugging process and its<br>
> > >> inferior (crash handlers, etc), prctl(PR_SET_PTRACER, pid, ...) can be<br>
> > >> used.  An inferior can declare which other process (and its descendents)<br>
> > >> are allowed to call PTRACE_ATTACH against it."<br>
> > >><br>
> > >> The child needs to be synchronized to the client to prevent a race<br>
> > >> condition where the child might try to operate before the parent has<br>
> > >> finished its prctl call.  This synchronization is done via pipes.<br>
> > >><br>
> > >> 1:<br>
> > >> <a href="http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=2d514487faf188938a4ee4fb3464eeecfbdcf8eb" target="_blank">http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=2d514487faf188938a4ee4fb3464eeecfbdcf8eb</a><br>
> > >> 2:<br>
> > >> <a href="https://wiki.ubuntu.com/SecurityTeam/Roadmap/KernelHardening#ptrace_Protection" target="_blank">https://wiki.ubuntu.com/SecurityTeam/Roadmap/KernelHardening#ptrace_Protection</a><br>
> > >><br>
> > >> Signed-off-by: Bryce Harrington <<a href="mailto:bryce@osg.samsung.com">bryce@osg.samsung.com</a>><br>
> > >> ---<br>
> > >>  tests/test-runner.c | 35 ++++++++++++++++++++++++++++++++---<br>
> > >>  1 file changed, 32 insertions(+), 3 deletions(-)<br>
> > >><br>
> > >> diff --git a/tests/test-runner.c b/tests/test-runner.c<br>
> > >> index b813b69..11d064e 100644<br>
> > >> --- a/tests/test-runner.c<br>
> > >> +++ b/tests/test-runner.c<br>
> > >> @@ -34,6 +34,7 @@<br>
> > >>  #include <errno.h><br>
> > >>  #include <limits.h><br>
> > >>  #include <sys/ptrace.h><br>
> > >> +#include <linux/prctl.h><br>
> > >><br>
> > ><br>
> > > Better use <sys/prctl.h>. prctl() is declared in sys/prctl.h.<br>
> > > linux/prctl.h only defines the values for arguments (and is included by<br>
> > > sys/prctl.h)<br>
> > ><br>
> > ><br>
> > >><br>
> > >>  #include "test-runner.h"<br>
> > >><br>
> > >> @@ -255,13 +256,33 @@ is_debugger_attached(void)<br>
> > >>  {<br>
> > >>         int status;<br>
> > >>         int rc;<br>
> > >> -       pid_t pid = fork();<br>
> > >> +       pid_t pid;<br>
> > >> +       int pipefd[2];<br>
> > >><br>
> > >> -       if (pid == -1)<br>
> > >> +       if (pipe(pipefd) == -1) {<br>
> > >> +               perror("pipe");<br>
> > >>                 return 0;<br>
> > >> +       }<br>
> > >> +<br>
> > >> +       pid = fork();<br>
> > >> +       if (pid == -1) {<br>
> > >> +               perror("fork");<br>
> > >> +               close(pipefd[0]);<br>
> > >> +               close(pipefd[1]);<br>
> > >> +               return 0;<br>
> > >> +       }<br>
> > >><br>
> > >>         if (pid == 0) {<br>
> > >> -               pid_t ppid = getppid();<br>
> > >> +               char buf;<br>
> > >> +               pid_t ppid;<br>
> > >> +<br>
> > >> +               /* Wait until parent is ready */<br>
> > >> +               close(pipefd[1]); /* Close unused write end */<br>
> > >> +               while (read(pipefd[0], &buf, 1) > 0);<br>
> > >><br>
> > > +               close(pipefd[0]);<br>
> > >> +<br>
> > >> +               /* Attempt to ptrace the parent */<br>
> > >> +               ppid = getppid();<br>
> > >>                 rc = ptrace(PTRACE_ATTACH, ppid, NULL, NULL);<br>
> > >>                 if (rc == 0) {<br>
> > >>                         waitpid(ppid, NULL, 0);<br>
> > >> @@ -273,6 +294,14 @@ is_debugger_attached(void)<br>
> > >>                 }<br>
> > >>                 _exit(rc);<br>
> > >>         } else {<br>
> > >> +               close(pipefd[0]);<br>
> > >> +<br>
> > >> +               /* Enable child to ptrace the parent process */<br>
> > >> +               prctl(PR_SET_PTRACER, pid);<br>
> > >> +<br>
> > >> +               /* Signal to client that parent is ready */<br>
> > >> +               close(pipefd[1]);<br>
> > >><br>
> > ><br>
> > > Maybe this would deserve better description, because signaling something<br>
> > > by closing the pipe is not clear IMO.<br>
<br>
</div></div>Since the pipe is blocking, it should be sufficient. I don't think it's<br>
needed to actually perform a write. The read will block until the close,<br>
and on close, the read will return 0, which is what it's waiting for<br>
(or for an error).<br>
<br></blockquote><div>Yep, I understand how it works, but I had to go thourgh the code back and forth to make myself sure that I get it. Therefore I suggested to add a comment that explains how the signaling works :)<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
-Kees<br>
<div class=""><div class="h5"><br>
> > ><br>
> > ><br>
> > ><br>
> > >>                 waitpid(pid, &status, 0);<br>
> > >>                 rc = WEXITSTATUS(status);<br>
> > >>         }<br>
> > >> --<br>
> > >> 1.9.1<br>
> > >><br>
> > >> _______________________________________________<br>
> > >> wayland-devel mailing list<br>
> > >> <a href="mailto:wayland-devel@lists.freedesktop.org">wayland-devel@lists.freedesktop.org</a><br>
> > >> <a href="http://lists.freedesktop.org/mailman/listinfo/wayland-devel" target="_blank">http://lists.freedesktop.org/mailman/listinfo/wayland-devel</a><br>
> > >><br>
> > ><br>
> > ><br>
> > > For both patches:<br>
> > ><br>
> > > Reviewed-by: Marek Chalupa <<a href="mailto:mchqwerty@gmail.com">mchqwerty@gmail.com</a>><br>
> > ><br>
> > ><br>
<br>
</div></div><span class=""><font color="#888888">--<br>
Kees Cook                                            @<a href="http://outflux.net" target="_blank">outflux.net</a><br></font></span></blockquote><div><br></div><div>Thanks,<br></div><div>Marek <br></div></div><br></div></div>