tests: add prctl-name.test, prctl-pdeathsig.test and prctl-tsc.test
Eugene Syromyatnikov
evgsyr at gmail.com
Mon Nov 21 12:46:59 UTC 2016
Hello.
Thank you for your contribution. Thanks to it, several bugs in current prctl
decoder implementation have been revealed. Please take a look
On Thu, Nov 17, 2016 at 09:17:27PM +0800, JingPiao Chen wrote:
> From 8995d87f0c27d40d574f032bf483f6ae2b5f7375 Mon Sep 17 00:00:00 2001
> From: JingPiao Chen <chenjingpiao at foxmail.com>
> Date: Thu, 17 Nov 2016 21:15:51 +0800
> Subject: [PATCH] tests: add prctl-name.test, prctl-pdeathsig.test and
> prctl-tsc.test
>
>
> * tests/prctl-name.c:New file.
Missing space.
> * tests/prctl-name.test: Likewise.
The established description format for the new *.test files is "New test".
> * tests/prctl-pdeathsig.c:Likewise.
> * tests/prctl-pdeathsig.test: Likewise.
> * tests/prctl-tsc.c: Likewise.
> * tests/prctl-tsc.test: Likewise
Summing up two previous notes, this part of commit message could be
rewritten as follows:
[[
* tests/prctl-name.c: New file.
* tests/prctl-pdeathsig.c:Likewise.
* tests/prctl-tsc.c: Likewise.
* tests/prctl-name.test: New test.
* tests/prctl-pdeathsig.test: Likewise.
* tests/prctl-tsc.test: Likewise
]]
> * tests/.gitignore: Add prctl-name, prctl-pdeathsig and prctl-tsc.
> * tests/Makefile.am (check_PROGRAMS): Likewise.
> (DECODER_TESTS): Add prctl-name.test, prctl-pdeathsig.test and prctl-tsc.test
> ---
> tests/.gitignore | 3 +++
> tests/Makefile.am | 6 +++++
> tests/prctl-name.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++
> tests/prctl-name.test | 6 +++++
> tests/prctl-pdeathsig.c | 61 ++++++++++++++++++++++++++++++++++++++++++++
> tests/prctl-pdeathsig.test | 6 +++++
> tests/prctl-tsc.c | 60 +++++++++++++++++++++++++++++++++++++++++++
> tests/prctl-tsc.test | 6 +++++
> 8 files changed, 211 insertions(+)
> create mode 100644 tests/prctl-name.c
> create mode 100755 tests/prctl-name.test
> create mode 100644 tests/prctl-pdeathsig.c
> create mode 100755 tests/prctl-pdeathsig.test
> create mode 100644 tests/prctl-tsc.c
> create mode 100755 tests/prctl-tsc.test
>
>
> diff --git a/tests/.gitignore b/tests/.gitignore
> index 6fc3cd1..8497dfa 100644
> --- a/tests/.gitignore
> +++ b/tests/.gitignore
> @@ -207,8 +207,11 @@ pkey_free
> pkey_mprotect
> poll
> ppoll
> +prctl-name
> +prctl-pdeathsig
> prctl-seccomp-filter-v
> prctl-seccomp-strict
> +prctl-tsc
> pread64-pwrite64
> preadv
> preadv-pwritev
> diff --git a/tests/Makefile.am b/tests/Makefile.am
> index df5ddb2..744ed25 100644
> --- a/tests/Makefile.am
> +++ b/tests/Makefile.am
> @@ -265,8 +265,11 @@ check_PROGRAMS = \
> pkey_mprotect \
> poll \
> ppoll \
> + prctl-name \
> + prctl-pdeathsig \
> prctl-seccomp-filter-v \
> prctl-seccomp-strict \
> + prctl-tsc \
> pread64-pwrite64 \
> preadv \
> preadv-pwritev \
> @@ -637,8 +640,11 @@ DECODER_TESTS = \
> pkey_mprotect.test \
> poll.test \
> ppoll.test \
> + prctl-name.test \
> + prctl-pdeathsig.test \
> prctl-seccomp-filter-v.test \
> prctl-seccomp-strict.test \
> + prctl-tsc.test \
> pread64-pwrite64.test \
> preadv-pwritev.test \
> preadv2-pwritev2.test \
> diff --git a/tests/prctl-name.c b/tests/prctl-name.c
> new file mode 100644
> index 0000000..a508969
> --- /dev/null
> +++ b/tests/prctl-name.c
> @@ -0,0 +1,63 @@
> +/*
It is recommended to have a brief description of the file in the beginning of
this comment block. For example, "Check decoding of prctl
PR_GET_NAME/PR_SET_NAME operations."
> + * Copyright (c) 2016 JingPiao Chen <chenjingpiao at foxmail.com>
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + * notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + * notice, this list of conditions and the following disclaimer in the
> + * documentation and/or other materials provided with the distribution.
> + * 3. The name of the author may not be used to endorse or promote products
> + * derived from this software without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
> + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
> + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
> + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
> + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
> + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#include "tests.h"
> +#include <asm/unistd.h>
> +
> +#ifdef HAVE_PRCTL
> +# include <sys/prctl.h>
> +#endif
> +
> +#if defined HAVE_PRCTL && defined PR_GET_NAME && defined PR_SET_NAME
> +
> +#include <stdio.h>
> +#include <unistd.h>
> +
> +int
> +main(void)
> +{
> + char setname[16] = "test-set-name";
> + char getname[16];
It is preferred to use tail_alloc()-based allocations in order to check
correctness of behaviour comparing to what kernel does regarding reading
data from process's address space. Please have a look:
https://github.com/strace/strace/blob/master/tests/preadv-pwritev.c#L68
https://github.com/strace/strace/blob/master/tests/perf_event_open.c#L182
https://github.com/strace/strace/blob/master/tests/aio.c#L230
> + long rc;
> +
> + rc = syscall(__NR_prctl, PR_SET_NAME, setname);
> + printf("prctl(PR_SET_NAME, \"%s\\0\\0\\0\") = %s\n",
> + setname, sprintrc(rc));
Note that this behaviour is not what expected judging by prctl(2) and
kernel/sys.c. Please take a look at
https://github.com/strace/strace/commit/43017ef466a8540c09e95da9b602e4e56dca8a94
for a fix.
> +
> + rc = syscall(__NR_prctl, PR_GET_NAME, getname);
> + printf("prctl(PR_GET_NAME, \"%s\") = %s\n",
Traditionally, the alignment produced by -a option is not included in
expected output produced by test; value of -a parameter is set in
accordance with shortest function call output instead.
> + getname, sprintrc(rc));
> +
> + puts("+++ exited with 0 +++");
> + return 0;
> +}
> +
> +#else
> +
> +SKIP_MAIN_UNDEFINED("HAVE_PRCTL && PR_GET_NAME && PR_SET_NAME")
> +
> +#endif
Overall, this test is doesn't check the following corner cases:
* Inaccessibility of data pointed by arg2
* Partial inaccessibility of data pointed by arg2
* Limit on amount of data read by kernel (kernel does not read more than
TASK_COMM_LEN - 1 bytes and termin)
After fixing up the bug this code revealed, Dmitry decided to rewrite it from
scratch:
https://github.com/strace/strace/blob/master/tests/prctl-name.c
> diff --git a/tests/prctl-name.test b/tests/prctl-name.test
> new file mode 100755
> index 0000000..fae18b3
> --- /dev/null
> +++ b/tests/prctl-name.test
> @@ -0,0 +1,6 @@
> +#!/bin/sh
> +
> +# Check prctl PR_GET_NAME PR_SET_NAME decoding.
> +
> +. "${srcdir=.}/init.sh"
> +run_strace_match_diff -a42 -e trace=prctl
> diff --git a/tests/prctl-pdeathsig.c b/tests/prctl-pdeathsig.c
> new file mode 100644
> index 0000000..db2e7b3
> --- /dev/null
> +++ b/tests/prctl-pdeathsig.c
> @@ -0,0 +1,61 @@
> +/*
> + * Copyright (c) 2016 JingPiao Chen <chenjingpiao at foxmail.com>
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + * notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + * notice, this list of conditions and the following disclaimer in the
> + * documentation and/or other materials provided with the distribution.
> + * 3. The name of the author may not be used to endorse or promote products
> + * derived from this software without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
> + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
> + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
> + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
> + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
> + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#include "tests.h"
> +#include <asm/unistd.h>
> +
> +#ifdef HAVE_PRCTL
> +# include <sys/prctl.h>
> +#endif
> +
> +#if defined HAVE_PRCTL && defined PR_GET_PDEATHSIG && defined PR_SET_PDEATHSIG
> +
> +#include <stdio.h>
> +#include <unistd.h>
> +#include <sys/signal.h>
> +
> +int
> +main(void)
> +{
> + int pdeathsig;
> + long rc;
> +
> + rc = syscall(__NR_prctl, PR_SET_PDEATHSIG, SIGINT);
> + printf("prctl(PR_SET_PDEATHSIG, SIGINT) = %s\n", sprintrc(rc));
Excessive whitespace, as noted above.
> +
> + rc = syscall(__NR_prctl, PR_GET_PDEATHSIG, &pdeathsig);
> + printf("prctl(PR_GET_PDEATHSIG, [SIGINT]) = %s\n", sprintrc(rc));
Note that the expected output of this call is depended on success of this and
the previous call (it may fail due to seccomp restrictions, for example).
As a result, it should be checked somehow, for example:
int pdeathsig;
long rc;
- rc = syscall(__NR_prctl, PR_SET_PDEATHSIG, SIGINT);
+ if ((rc = syscall(__NR_prctl, PR_SET_PDEATHSIG, SIGINT)))
+ perror_msg_and_skip("prctl(PR_SET_PDEATHSIG)");
printf("prctl(PR_SET_PDEATHSIG, SIGINT) = %s\n", sprintrc(rc));
- rc = syscall(__NR_prctl, PR_GET_PDEATHSIG, &pdeathsig);
+ if ((rc = syscall(__NR_prctl, PR_GET_PDEATHSIG, &pdeathsig)))
+ perror_msg_and_skip("prctl(PR_GET_PDEATHSIG)");
printf("prctl(PR_GET_PDEATHSIG, [SIGINT]) = %s\n", sprintrc(rc));
puts("+++ exited with 0 +++");
> +
> + puts("+++ exited with 0 +++");
> + return 0;
> +}
> +
> +#else
> +
> +SKIP_MAIN_UNDEFINED("HAVE_PRCTL && PR_GET_PDEATHSIG && PR_SET_PDEATHSIG")
> +
> +#endif
This test also lacks checks for unknown signal value, for argument size (see
https://github.com/strace/strace/commit/aeff861218c14cbc5b5bf2c0f1f4ad497bc70a0b
; this is important due to the fact that long and kernel_ulong_t have different
size on X32/N32 ABIs, and prctl does not implement compat syscall for these
ABIs) and for inaccessibility of pointer. For example:
--- a/tests/prctl-pdeathsig.c
+++ b/tests/prctl-pdeathsig.c
@@ -38,17 +38,32 @@
# include <unistd.h>
# include <sys/signal.h>
+# include "kernel_types.h"
+
int
main(void)
{
- int pdeathsig;
+ static const kernel_ulong_t bogus_signal =
+ (kernel_ulong_t) 0xbadc0deddeadfeedULL;
+
+ int *pdeathsig = tail_alloc(sizeof(*pdeathsig));
long rc;
+ rc = syscall(__NR_prctl, PR_SET_PDEATHSIG, bogus_signal);
+ printf("prctl(PR_SET_PDEATHSIG, %llu) = %s\n",
+ (unsigned long long) bogus_signal, sprintrc(rc));
+
if ((rc = syscall(__NR_prctl, PR_SET_PDEATHSIG, SIGINT)))
perror_msg_and_skip("prctl(PR_SET_PDEATHSIG)");
printf("prctl(PR_SET_PDEATHSIG, SIGINT) = %s\n", sprintrc(rc));
- if ((rc = syscall(__NR_prctl, PR_GET_PDEATHSIG, &pdeathsig)))
+ rc = syscall(__NR_prctl, PR_GET_PDEATHSIG, NULL);
+ printf("prctl(PR_GET_PDEATHSIG, NULL) = %s\n", sprintrc(rc));
+
+ rc = syscall(__NR_prctl, PR_GET_PDEATHSIG, pdeathsig + 1);
+ printf("prctl(PR_GET_PDEATHSIG, %p) = %s\n",
+ pdeathsig + 1, sprintrc(rc));
+
+ if ((rc = syscall(__NR_prctl, PR_GET_PDEATHSIG, pdeathsig)))
perror_msg_and_skip("prctl(PR_GET_PDEATHSIG)");
printf("prctl(PR_GET_PDEATHSIG, [SIGINT]) = %s\n", sprintrc(rc));
> diff --git a/tests/prctl-pdeathsig.test b/tests/prctl-pdeathsig.test
> new file mode 100755
> index 0000000..5e0be13
> --- /dev/null
> +++ b/tests/prctl-pdeathsig.test
> @@ -0,0 +1,6 @@
> +#!/bin/sh
> +
> +# Check prctl PR_GET_PDEATHSIG PR_SET_PDEATHSIG decoding.
> +
> +. "${srcdir=.}/init.sh"
> +run_strace_match_diff -a34 -e trace=prctl
> diff --git a/tests/prctl-tsc.c b/tests/prctl-tsc.c
> new file mode 100644
> index 0000000..ea8bf61
> --- /dev/null
> +++ b/tests/prctl-tsc.c
> @@ -0,0 +1,60 @@
> +/*
> + * Copyright (c) 2016 JingPiao Chen <chenjingpiao at foxmail.com>
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + * notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + * notice, this list of conditions and the following disclaimer in the
> + * documentation and/or other materials provided with the distribution.
> + * 3. The name of the author may not be used to endorse or promote products
> + * derived from this software without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
> + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
> + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
> + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
> + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
> + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#include "tests.h"
> +#include <asm/unistd.h>
> +
> +#ifdef HAVE_PRCTL
> +# include <sys/prctl.h>
> +#endif
> +
> +#if defined HAVE_PRCTL && defined PR_GET_TSC && defined PR_SET_TSC
> +
> +#include <stdio.h>
> +#include <unistd.h>
> +
> +int
> +main(void)
> +{
> + int tsc;
> + long rc;
> +
> + rc = syscall(__NR_prctl, PR_SET_TSC, PR_TSC_SIGSEGV);
> + printf("prctl(PR_SET_TSC, PR_TSC_SIGSEGV) = %s\n", sprintrc(rc));
> +
> + rc = syscall(__NR_prctl, PR_GET_TSC, &tsc);
> + printf("prctl(PR_GET_TSC, [PR_TSC_SIGSEGV]) = %s\n", sprintrc(rc));
Note that this command is arch-specific and would fail on architectures other
than x86 (in addition to other possibilities of tampering call execution by
various security modules).
> +
> + puts("+++ exited with 0 +++");
> + return 0;
> +}
> +
> +#else
> +
> +SKIP_MAIN_UNDEFINED("HAVE_PRCTL && PR_GET_TSC && PR_SET_TSC")
> +
> +#endif
Notes regarding possible corner cases are generally the same as for the previous
test.
> diff --git a/tests/prctl-tsc.test b/tests/prctl-tsc.test
> new file mode 100755
> index 0000000..c6fe65f
> --- /dev/null
> +++ b/tests/prctl-tsc.test
> @@ -0,0 +1,6 @@
> +#!/bin/sh
> +
> +# Check prctl PR_GET_TSC PR_SET_TSC decoding.
> +
> +. "${srcdir=.}/init.sh"
> +run_strace_match_diff -a36 -e trace=prctl
> --
> 2.7.4
> ------------------------------------------------------------------------------
> _______________________________________________
> Strace-devel mailing list
> Strace-devel at lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/strace-devel
More information about the Strace-devel
mailing list