From patchwork Tue Jul 4 08:22:04 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Liebler X-Patchwork-Id: 21397 Received: (qmail 105948 invoked by alias); 4 Jul 2017 08:22:12 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 105938 invoked by uid 89); 4 Jul 2017 08:22:11 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-24.4 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_LAZY_DOMAIN_SECURITY, RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.2 spammy=73, rwp, 23548, variations X-HELO: mx0a-001b2d01.pphosted.com Subject: Re: [PATCH] S390: Sync ptrace.h with kernel. [BZ #21539] To: libc-alpha@sourceware.org References: <20170613200522.GA14306@altlinux.org> From: Stefan Liebler Cc: Florian Weimer Date: Tue, 4 Jul 2017 10:22:04 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.1.0 MIME-Version: 1.0 In-Reply-To: X-TM-AS-GCONF: 00 x-cbid: 17070408-0040-0000-0000-000003BABEFB X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 17070408-0041-0000-0000-000025B51D25 Message-Id: <7ce52670-669c-d9c0-dcf0-4d328bbeda79@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2017-07-04_04:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 suspectscore=1 malwarescore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1703280000 definitions=main-1707040144 On 06/30/2017 12:09 PM, Florian Weimer wrote: > On 06/19/2017 03:10 PM, Stefan Liebler wrote: >> * sysdeps/unix/sysv/linux/s390/tst-ptrace-singleblock.c: >> New file. > > The test fails for me like this on s390x: > > [root@ibm-z-25 build]# bash testrun.sh misc/tst-ptrace-singleblock > cat /proc/23548/maps > 80000000-80004000 r-xp 00000000 fd:00 1883202 > /root/build/misc/tst-ptrace-singleblock > 80004000-80005000 r--p 00003000 fd:00 1883202 > /root/build/misc/tst-ptrace-singleblock > 80005000-80006000 rw-p 00004000 fd:00 1883202 > /root/build/misc/tst-ptrace-singleblock > 2aa00794000-2aa007ba000 r-xp 00000000 fd:00 34794498 > /root/build/elf/ld.so > 2aa007ba000-2aa007bb000 r--p 00025000 fd:00 34794498 > /root/build/elf/ld.so > 2aa007bb000-2aa007bd000 rw-p 00026000 fd:00 34794498 > /root/build/elf/ld.so > 3fffd1e9000-3fffd1ea000 rw-s 00000000 00:04 146001 > /dev/zero (deleted) > 3fffd1ea000-3fffd1ec000 rw-p 00000000 00:00 0 > 3fffd1ec000-3fffd38d000 r-xp 00000000 fd:00 34794501 > /root/build/libc.so > 3fffd38d000-3fffd391000 r--p 001a0000 fd:00 34794501 > /root/build/libc.so > 3fffd391000-3fffd393000 rw-p 001a4000 fd:00 34794501 > /root/build/libc.so > 3fffd393000-3fffd39a000 rw-p 00000000 00:00 0 > 3ffffe62000-3fffff83000 rw-p 00000000 00:00 0 > [stack] > child IA: 0x3fffd22ac62 last_break: 0x2aa0079e218 > error: ../sysdeps/unix/sysv/linux/s390/tst-ptrace-singleblock.c:111: not > true: ptrace (req_singleblock, pid, NULL, NULL) == 0 > The PTRACE_SINGLEBLOCK of the tracer will stop after: brasl %r14,! > error: 1 test failures > [root@ibm-z-25 build]# > > Relevant package versions: > > kernel-3.10.0-689.el7.s390x > kernel-headers-3.10.0-689.el7.s390x > devtoolset-6-gcc-6.3.1-3.1.el7.s390x > > Please let me know if you need additional information to debug this. > > Thanks, > Florian > Uuups. I also see this behaviour on a RHEL 7.3 machine. We've checked that request 12 wasn't used in s390 kernel for other meanings as PTRACE_SINGLEBLOCK. But we've missed the fact, that it has been introduced with kernel 3.15. On older kernels -1 is returned with errno EIO. Please have a look at the attached patch. I've adjusted the test: Now ptrace request 12 is first done with data argument pointing to a buffer: -If request 12 is interpreted as PTRACE_GETREGS, it will store the regs to buffer without an error. Here the test expects that the buffer is untouched and an error is returned. -If request 12 is interpreted as PTRACE_SINGLEBLOCK, it will fail as data argument is no valid signal. -If request 12 is not implemented, it will also fail. Afterwards the request 12 is done with zero data argument: -If the kernel has support for PTRACE_SINGLEBLOCK (then the kernel header asm/ptrace.h defines this macro), the ptrace call is not allowed to fail and has to continue the tracee until next taken branch. -If the kernel has no support for PTRACE_SINGLEBLOCK, the ptrace call has to fail with EIO. Then I continue the tracee with PTRACE_CONT. -If the request 12 is interpreted as PTRACE_GETREGS, it will fail too. It fails with EFAULT on intel / power as data argument is NULL. According to the man-page: "Unfortunately, under Linux, different variations of this fault will return EIO or EFAULT more or less arbitrarily". But if request 12 is interpreted as PTRACE_GETREGS, the first ptrace call will touch the buffer which is detected by this test. Any thoughts? If this change is okay, I'll commit it. Thanks. Stefan ChangeLog: * sysdeps/unix/sysv/linux/s390/tst-ptrace-singleblock.c: Support running on kernels without PTRACE_SINGLEBLOCK. commit 5e668ce6055d6c690dec773b41c11a801265cd21 Author: Stefan Liebler Date: Tue Jul 4 10:20:05 2017 +0200 S390: Fix tst-ptrace-singleblock if kernel does not support PTRACE_SINGLEBLOCK. The request PTRACE_SINGLEBLOCK was introduced in Linux 3.15. Thus the ptrace call will fail on older kernels. Thus the test is now testing PTRACE_SINGLEBLOCK with data argument pointing to a buffer on stack which is assumed to fail. If the request would be interpreted as PTRACE_GETREGS, then the ptrace call will not fail and the regs are written to buf. If we run with a kernel with support for PTRACE_SINGLEBLOCK a ptrace call with data=NULL, is not allowed to fail. If we run with a kernel without support for PTRACE_SINGLEBLOCK a ptrace call with data=NULL, has to fail with EIO. ChangeLog: * sysdeps/unix/sysv/linux/s390/tst-ptrace-singleblock.c: Support running on kernels without PTRACE_SINGLEBLOCK. diff --git a/sysdeps/unix/sysv/linux/s390/tst-ptrace-singleblock.c b/sysdeps/unix/sysv/linux/s390/tst-ptrace-singleblock.c index 95a2f55..65858cb 100644 --- a/sysdeps/unix/sysv/linux/s390/tst-ptrace-singleblock.c +++ b/sysdeps/unix/sysv/linux/s390/tst-ptrace-singleblock.c @@ -26,6 +26,8 @@ #include #include #include +#include +#include /* Ensure that we use the PTRACE_SINGLEBLOCK definition from glibc ptrace.h in tracer_func. We need the kernel ptrace.h for structs ptrace_area @@ -63,6 +65,10 @@ tracer_func (int pid) gregset_t regs2; int status; + int ret; +#define MAX_CHARS_IN_BUF 4096 + char buf[MAX_CHARS_IN_BUF + 1]; + size_t buf_count; while (1) { @@ -104,11 +110,67 @@ tracer_func (int pid) The s390 kernel has no support for PTRACE_GETREGS! Thus glibc ptrace.h is adjusted to match kernel ptrace.h. + The glibc sys/ptrace.h header contains the identifier + PTRACE_SINGLEBLOCK in enum __ptrace_request. In contrast, the kernel + asm/ptrace.h header defines PTRACE_SINGLEBLOCK. + This test ensures, that PTRACE_SINGLEBLOCK defined in glibc works as expected. If the kernel would interpret it as PTRACE_GETREGS, then the tracee will not make any progress - and this testcase will time out. */ - TEST_VERIFY_EXIT (ptrace (req_singleblock, pid, NULL, NULL) == 0); + and this testcase will time out or the ptrace call will fail with + different errors. */ + + /* Ptrace request 12 is first done with data argument pointing to + a buffer: + -If request 12 is interpreted as PTRACE_GETREGS, it will store the regs + to buffer without an error. + + -If request 12 is interpreted as PTRACE_SINGLEBLOCK, it will fail + as data argument is used as signal-number and the address of + buf is no valid signal. + + -If request 12 is not implemented, it will also fail. + + Here the test expects that the buffer is untouched and an error is + returned. */ + memset (buf, 'a', MAX_CHARS_IN_BUF); + ret = ptrace (req_singleblock, pid, NULL, buf); + buf [MAX_CHARS_IN_BUF] = '\0'; + buf_count = strspn (buf, "a"); + TEST_VERIFY_EXIT (buf_count == MAX_CHARS_IN_BUF); + TEST_VERIFY_EXIT (ret == -1); + + /* Ptrace request 12 is done with zero data argument: + -If the kernel has support for PTRACE_SINGLEBLOCK (then the kernel + header asm/ptrace.h defines this macro), the ptrace call is not allowed + to fail and has to continue the tracee until next taken branch. + + -If the kernel (<3.15) has no support for PTRACE_SINGLEBLOCK, the + ptrace call has to fail with EIO. Then I continue the tracee with + PTRACE_CONT. + + -If the request 12 is interpreted as PTRACE_GETREGS, it will fail too. + It fails with EFAULT on intel / power as data argument is NULL. + According to the man-page: "Unfortunately, under Linux, different + variations of this fault will return EIO or EFAULT more or less + arbitrarily". + But if request 12 is interpreted as PTRACE_GETREGS, the first ptrace + call will touch the buffer which is detected by this test. */ + errno = 0; + ret = ptrace (req_singleblock, pid, NULL, NULL); +#ifdef PTRACE_SINGLEBLOCK + /* The kernel has support for PTRACE_SINGLEBLOCK ptrace request. */ + TEST_VERIFY_EXIT (errno == 0); + TEST_VERIFY_EXIT (ret == 0); +#else + /* The kernel (< 3.15) has no support for PTRACE_SINGLEBLOCK ptrace + request. */ + TEST_VERIFY_EXIT (errno == EIO); + TEST_VERIFY_EXIT (ret == -1); + + /* Just continue tracee until it exits normally. */ + TEST_VERIFY_EXIT (ptrace (PTRACE_CONT, pid, NULL, NULL) == 0); +#endif } }