[PATCH] tests: improve test coverage of prctl syscall decoder

Srikavin Ramkumar srikavinramkumar at gmail.com
Tue Mar 23 23:39:45 UTC 2021


* tests/.gitignore: Add new test binaries.
* tests/Makefile.am: Add new tests.
* tests/pure_executables.list: Likewise.
* tests/prctl-cap-ambient.c: New file.
* tests/prctl-cap-ambient.test: Likewise.
* tests/prctl-capbset.c: Likewise.
* tests/prctl-capbset.test: Likewise.
* tests/prctl-fp-mode.c: Likewise.
* tests/prctl-fp-mode.test: Likewise.
* tests/prctl-mce-kill.c: Likewise.
* tests/prctl-mce-kill.test: Likewise.
* tests/prctl-sve.c: Likewise.
* tests/prctl-sve.test: Likewise.
* tests/prctl-unalign.c: Likewise.
* tests/prctl-unalign.test: Likewise.
---

This is part of my GSoC microproject. I plan to add a few more tests, but I
wanted to make sure that I'm on the right track with these tests. These tests
pass the CI, and the coverage results can be found here [1].

[1]: https://codecov.io/gh/srikavin/strace/src/prctl-tests/src/prctl.c

 tests/.gitignore             |  6 +++
 tests/Makefile.am            |  7 +++
 tests/prctl-cap-ambient.c    | 78 +++++++++++++++++++++++++++++
 tests/prctl-cap-ambient.test | 16 ++++++
 tests/prctl-capbset.c        | 48 ++++++++++++++++++
 tests/prctl-capbset.test     | 16 ++++++
 tests/prctl-fp-mode.c        | 96 ++++++++++++++++++++++++++++++++++++
 tests/prctl-fp-mode.test     | 33 +++++++++++++
 tests/prctl-mce-kill.c       | 59 ++++++++++++++++++++++
 tests/prctl-mce-kill.test    | 16 ++++++
 tests/prctl-sve.c            | 53 ++++++++++++++++++++
 tests/prctl-sve.test         | 16 ++++++
 tests/prctl-unalign.c        | 48 ++++++++++++++++++
 tests/prctl-unalign.test     | 16 ++++++
 tests/pure_executables.list  |  5 ++
 15 files changed, 513 insertions(+)
 create mode 100644 tests/prctl-cap-ambient.c
 create mode 100755 tests/prctl-cap-ambient.test
 create mode 100644 tests/prctl-capbset.c
 create mode 100755 tests/prctl-capbset.test
 create mode 100644 tests/prctl-fp-mode.c
 create mode 100755 tests/prctl-fp-mode.test
 create mode 100644 tests/prctl-mce-kill.c
 create mode 100755 tests/prctl-mce-kill.test
 create mode 100644 tests/prctl-sve.c
 create mode 100755 tests/prctl-sve.test
 create mode 100644 tests/prctl-unalign.c
 create mode 100755 tests/prctl-unalign.test

diff --git a/tests/.gitignore b/tests/.gitignore
index a2f3419b..74eca446 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -594,7 +594,11 @@ ppoll
 ppoll-P
 ppoll-v
 prctl-arg2-intptr
+prctl-cap-ambient
+prctl-capbset
 prctl-dumpable
+prctl-fp-mode
+prctl-mce-kill
 prctl-name
 prctl-no-args
 prctl-pdeathsig
@@ -602,8 +606,10 @@ prctl-seccomp-filter-v
 prctl-seccomp-strict
 prctl-securebits
 prctl-spec-inject
+prctl-sve
 prctl-tid_address
 prctl-tsc
+prctl-unalign
 pread64-pwrite64
 preadv
 preadv-pwritev
diff --git a/tests/Makefile.am b/tests/Makefile.am
index b8efce82..27961a39 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -226,6 +226,7 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \
 	ppoll-P \
 	ppoll-v \
 	prlimit64--pidns-translation \
+	prctl-fp-mode \
 	prctl-seccomp-filter-v \
 	prctl-seccomp-strict \
 	prctl-spec-inject \
@@ -409,7 +410,11 @@ DECODER_TESTS = \
 	poll-P.test \
 	poll.test \
 	prctl-arg2-intptr.test \
+	prctl-capbset.test \
+	prctl-cap-ambient.test \
 	prctl-dumpable.test \
+	prctl-fp-mode.test \
+	prctl-mce-kill.test \
 	prctl-name.test \
 	prctl-no-args.test \
 	prctl-pdeathsig.test \
@@ -417,8 +422,10 @@ DECODER_TESTS = \
 	prctl-seccomp-strict.test \
 	prctl-securebits.test \
 	prctl-spec-inject.test \
+	prctl-sve.test \
 	prctl-tid_address.test \
 	prctl-tsc.test \
+	prctl-unalign.test \
 	qual_fault-exit_group.test \
 	quotactl-success-v.test \
 	quotactl-success.test \
diff --git a/tests/prctl-cap-ambient.c b/tests/prctl-cap-ambient.c
new file mode 100644
index 00000000..4c2b15f3
--- /dev/null
+++ b/tests/prctl-cap-ambient.c
@@ -0,0 +1,78 @@
+/*
+ * Check decoding of prctl PR_CAP_AMBIENT operations.
+ *
+ * Copyright (c) 2021 The strace developers.
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "tests.h"
+#include "scno.h"
+#include <stdio.h>
+#include <unistd.h>
+#include <linux/prctl.h>
+#include <linux/capability.h>
+
+int
+main(void)
+{
+	long rc;
+
+	rc = syscall(__NR_prctl, PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE,
+				 CAP_NET_RAW, 0, 0);
+	printf("prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, CAP_NET_RAW, 0, 0) = %s\n",
+		   sprintrc(rc));
+
+	rc = syscall(__NR_prctl, PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE,
+				 CAP_AUDIT_CONTROL, 0, 0);
+	printf("prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, CAP_AUDIT_CONTROL, 0, 0) = %s\n",
+		   sprintrc(rc));
+
+	rc = syscall(__NR_prctl, PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, 0xff, 0, 0);
+	printf("prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, 0xff /* CAP_??? */, 0, 0) = %s\n",
+		   sprintrc(rc));
+
+	rc = syscall(__NR_prctl, PR_CAP_AMBIENT, PR_CAP_AMBIENT_LOWER,
+				 CAP_NET_RAW, 0, 0);
+	printf("prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_LOWER, CAP_NET_RAW, 0, 0) = %s\n",
+		   sprintrc(rc));
+
+	rc = syscall(__NR_prctl, PR_CAP_AMBIENT, PR_CAP_AMBIENT_LOWER,
+				 CAP_KILL, 0, 0);
+	printf("prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_LOWER, CAP_KILL, 0, 0) = %s\n",
+		   sprintrc(rc));
+
+	rc = syscall(__NR_prctl, PR_CAP_AMBIENT, PR_CAP_AMBIENT_LOWER, 0xff, 0, 0);
+	printf("prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_LOWER, 0xff /* CAP_??? */, 0, 0) = %s\n",
+		   sprintrc(rc));
+
+	rc = syscall(__NR_prctl, PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET,
+				 CAP_NET_RAW, 0, 0);
+	printf("prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_NET_RAW, 0, 0) = %s\n",
+		   sprintrc(rc));
+
+	rc = syscall(__NR_prctl, PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET,
+				 CAP_AUDIT_CONTROL, 0, 0);
+	printf("prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_AUDIT_CONTROL, 0, 0) = %s\n",
+		   sprintrc(rc));
+
+	rc = syscall(__NR_prctl, PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, 0xff, 0, 0);
+	printf("prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, 0xff /* CAP_??? */, 0, 0) = %s\n",
+		   sprintrc(rc));
+
+	rc = syscall(__NR_prctl, PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0);
+	printf("prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0) = %s\n",
+		   sprintrc(rc));
+
+	rc = syscall(__NR_prctl, PR_CAP_AMBIENT, 0xff, 0xaaaa, 0, 0);
+	printf("prctl(PR_CAP_AMBIENT, 0xff /* PR_CAP_AMBIENT_??? */, 0xaaaa, 0, 0) = %s\n",
+		   sprintrc(rc));
+
+	rc = syscall(__NR_prctl, PR_CAP_AMBIENT, 0xff, 0xaaaa, 0xbbbb, 0xcccc);
+	printf("prctl(PR_CAP_AMBIENT, 0xff /* PR_CAP_AMBIENT_??? */, 0xaaaa, 0xbbbb, 0xcccc) = %s\n",
+		   sprintrc(rc));
+
+	puts("+++ exited with 0 +++");
+	return 0;
+}
diff --git a/tests/prctl-cap-ambient.test b/tests/prctl-cap-ambient.test
new file mode 100755
index 00000000..c2955de6
--- /dev/null
+++ b/tests/prctl-cap-ambient.test
@@ -0,0 +1,16 @@
+#!/bin/sh
+#
+# Check decoding of prctl PR_CAP_AMBIENT operations.
+#
+# Copyright (c) 2021 The strace developers.
+# All rights reserved.
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+. "${srcdir=.}/init.sh"
+
+check_prog grep
+run_prog > /dev/null
+run_strace -a21 -eprctl $args > "$EXP"
+grep -v '^prctl(PR_[^C][^A][^P]_[^A][^M]' < "$LOG" > "$OUT"
+match_diff "$OUT" "$EXP"
diff --git a/tests/prctl-capbset.c b/tests/prctl-capbset.c
new file mode 100644
index 00000000..8ca62c8b
--- /dev/null
+++ b/tests/prctl-capbset.c
@@ -0,0 +1,48 @@
+/*
+ * Check decoding of prctl PR_CAPBSET_READ/PR_CAPBSET_DROP operations.
+ *
+ * Copyright (c) 2021 The strace developers.
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "tests.h"
+#include "scno.h"
+#include <stdio.h>
+#include <unistd.h>
+#include <linux/prctl.h>
+#include <linux/capability.h>
+
+int
+main(void)
+{
+	long rc;
+
+	rc = syscall(__NR_prctl, PR_CAPBSET_READ, CAP_AUDIT_CONTROL);
+	printf("prctl(PR_CAPBSET_READ, CAP_AUDIT_CONTROL) = %s\n",
+		   sprintrc(rc));
+
+	rc = syscall(__NR_prctl, PR_CAPBSET_READ, CAP_NET_RAW);
+	printf("prctl(PR_CAPBSET_READ, CAP_NET_RAW) = %s\n",
+		   sprintrc(rc));
+
+	rc = syscall(__NR_prctl, PR_CAPBSET_READ, 0xff);
+	printf("prctl(PR_CAPBSET_READ, 0xff /* CAP_??? */) = %s\n",
+		   sprintrc(rc));
+
+	rc = syscall(__NR_prctl, PR_CAPBSET_DROP, CAP_AUDIT_CONTROL);
+	printf("prctl(PR_CAPBSET_DROP, CAP_AUDIT_CONTROL) = %s\n",
+		   sprintrc(rc));
+
+	rc = syscall(__NR_prctl, PR_CAPBSET_DROP, CAP_NET_RAW);
+	printf("prctl(PR_CAPBSET_DROP, CAP_NET_RAW) = %s\n",
+		   sprintrc(rc));
+
+	rc = syscall(__NR_prctl, PR_CAPBSET_DROP, 0xff);
+	printf("prctl(PR_CAPBSET_DROP, 0xff /* CAP_??? */) = %s\n",
+		   sprintrc(rc));
+
+	puts("+++ exited with 0 +++");
+	return 0;
+}
diff --git a/tests/prctl-capbset.test b/tests/prctl-capbset.test
new file mode 100755
index 00000000..2002bcdd
--- /dev/null
+++ b/tests/prctl-capbset.test
@@ -0,0 +1,16 @@
+#!/bin/sh
+#
+# Check decoding of prctl PR_CAPBSET_READ/PR_CAPBSET_DROP operations.
+#
+# Copyright (c) 2021 The strace developers.
+# All rights reserved.
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+. "${srcdir=.}/init.sh"
+
+check_prog grep
+run_prog > /dev/null
+run_strace -a21 -eprctl $args > "$EXP"
+grep -Ev '^prctl\(PR_[^C][^A][^P][^B][^S][^E][^T]_(DROP|READ)' < "$LOG" > "$OUT"
+match_diff "$OUT" "$EXP"
diff --git a/tests/prctl-fp-mode.c b/tests/prctl-fp-mode.c
new file mode 100644
index 00000000..62c0b070
--- /dev/null
+++ b/tests/prctl-fp-mode.c
@@ -0,0 +1,96 @@
+/*
+ * Check decoding of prctl PR_GET_FP_MODE/PR_SET_FP_MODE operations.
+ *
+ * Copyright (c) 2021 The strace developers.
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "tests.h"
+#include "scno.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <linux/prctl.h>
+
+static long injected_val;
+
+long
+do_prctl(kernel_ulong_t cmd, kernel_ulong_t arg2, kernel_ulong_t arg3)
+{
+	long rc = syscall(__NR_prctl, cmd, arg2, arg3);
+
+	if (rc != injected_val)
+		error_msg_and_fail("Return value (%ld) differs from expected "
+						   "injected value (%ld)",
+						   rc, injected_val);
+
+	return rc;
+}
+
+int
+main(int argc, char **argv)
+{
+	static const kernel_ulong_t bogus_arg2 =
+			(kernel_ulong_t) 0xdecafeedbeefda7eULL;
+	static const kernel_ulong_t bogus_arg3 =
+			(kernel_ulong_t) 0xdecafeedbeefda7eULL;
+
+	static const struct {
+		long arg;
+		const char *str;
+	} get_strs[] = {
+			{-1,       ""},
+			{0,        ""},
+			{1,        " (PR_FP_MODE_FR)"},
+			{2,        " (PR_FP_MODE_FRE)"},
+			{3,        " (PR_FP_MODE_FR|PR_FP_MODE_FRE)"},
+			{0x20,     " (0x20)"},
+			{0x20 | 3, " (PR_FP_MODE_FR|PR_FP_MODE_FRE|0x20)"}
+	};
+	static const struct {
+		kernel_ulong_t arg;
+		const char *str;
+	} set_strs[] = {
+			{0,        "0"},
+			{1,        "PR_FP_MODE_FR"},
+			{2,        "PR_FP_MODE_FRE"},
+			{3,        "PR_FP_MODE_FR|PR_FP_MODE_FRE"},
+			{0x20,     "0x20 /* PR_FP_MODE_??? */"},
+			{0x20 | 3, "PR_FP_MODE_FR|PR_FP_MODE_FRE|0x20"}
+	};
+
+	long rc;
+	const char *str = NULL;
+
+	if (argc < 2)
+		error_msg_and_fail("Usage: %s INJECTED_VAL", argv[0]);
+
+	injected_val = strtol(argv[1], NULL, 0);
+
+	/* PR_GET_FP_MODE */
+	rc = do_prctl(PR_GET_FP_MODE, bogus_arg2, bogus_arg3);
+
+	for (size_t i = 0; i < ARRAY_SIZE(get_strs); i++) {
+		if (get_strs[i].arg == rc) {
+			str = get_strs[i].str;
+			break;
+		}
+	}
+	if (!str)
+		error_msg_and_fail("Unknown return value: %ld", rc);
+
+	printf("prctl(PR_GET_FP_MODE) = %s%s (INJECTED)\n", sprintrc(rc), str);
+
+	/* PR_SET_FP_MODE */
+	for (size_t i = 0; i < ARRAY_SIZE(set_strs); i++) {
+		rc = do_prctl(PR_SET_FP_MODE, set_strs[i].arg, bogus_arg3);
+
+		printf("prctl(PR_SET_FP_MODE, %s) = %s (INJECTED)\n", set_strs[i].str,
+			   sprintrc(rc));
+	}
+
+	puts("+++ exited with 0 +++");
+	return 0;
+}
diff --git a/tests/prctl-fp-mode.test b/tests/prctl-fp-mode.test
new file mode 100755
index 00000000..bcd99675
--- /dev/null
+++ b/tests/prctl-fp-mode.test
@@ -0,0 +1,33 @@
+#!/bin/sh -efu
+#
+# Check decoding of prctl PR_GET_FP_MODE/PR_SET_FP_MODE operations.
+#
+# Copyright (c) 2021 The strace developers.
+# All rights reserved.
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+. "${srcdir=.}/scno_tampering.sh"
+
+fault_args='-a21 -e trace=prctl -e inject=prctl:'
+prog="../$NAME"
+
+test_run_rval()
+{
+	local rval injexpr
+	rval="$1"; shift
+	injexpr="$1"; shift
+
+	run_strace $fault_args$injexpr $prog $rval > "$EXP"
+	LC_ALL=C grep -v '^prctl(PR_[GS]ET_[^F][^P][^_][^M][^O][^D][^E]' \
+		< "$LOG" > "$OUT"
+	match_diff "$OUT" "$EXP"
+}
+
+test_run_rval -1 "error=ENOTTY"
+test_run_rval 0 "retval=0"
+test_run_rval 1 "retval=1"
+test_run_rval 2 "retval=2"
+test_run_rval 3 "retval=3"
+test_run_rval 32 "retval=32"
+test_run_rval 35 "retval=35"
diff --git a/tests/prctl-mce-kill.c b/tests/prctl-mce-kill.c
new file mode 100644
index 00000000..3ff05f24
--- /dev/null
+++ b/tests/prctl-mce-kill.c
@@ -0,0 +1,59 @@
+/*
+ * Check decoding of prctl PR_MCE_KILL/PR_MCE_KILL_GET operations.
+ *
+ * Copyright (c) 2021 The strace developers.
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "tests.h"
+#include "scno.h"
+#include <stdio.h>
+#include <unistd.h>
+#include <linux/prctl.h>
+
+int
+main(void)
+{
+	long rc;
+
+	rc = syscall(__NR_prctl, PR_MCE_KILL, PR_MCE_KILL_CLEAR, 0, 0, 0);
+	printf("prctl(PR_MCE_KILL, PR_MCE_KILL_CLEAR, 0, 0, 0) = %s\n",
+		   sprintrc(rc));
+
+	rc = syscall(__NR_prctl, PR_MCE_KILL, PR_MCE_KILL_SET, PR_MCE_KILL_EARLY, 0, 0);
+	printf("prctl(PR_MCE_KILL, PR_MCE_KILL_SET, PR_MCE_KILL_EARLY, 0, 0) = %s\n",
+		   sprintrc(rc));
+
+	rc = syscall(__NR_prctl, PR_MCE_KILL, PR_MCE_KILL_SET, PR_MCE_KILL_LATE, 0, 0);
+	printf("prctl(PR_MCE_KILL, PR_MCE_KILL_SET, PR_MCE_KILL_LATE, 0, 0) = %s\n",
+		   sprintrc(rc));
+
+	rc = syscall(__NR_prctl, PR_MCE_KILL, PR_MCE_KILL_SET, 0xff, 0, 0);
+	printf("prctl(PR_MCE_KILL, PR_MCE_KILL_SET, 0xff /* PR_MCE_KILL_??? */, 0, 0) = %s\n",
+		   sprintrc(rc));
+
+	rc = syscall(__NR_prctl, PR_MCE_KILL, 0xaaaa, 0xbbbb, 0xcccc, 0xdddd);
+	printf("prctl(PR_MCE_KILL, 0xaaaa /* PR_MCE_KILL_??? */, 0xbbbb, 0xcccc, 0xdddd) = %s\n",
+		   sprintrc(rc));
+
+	rc = syscall(__NR_prctl, PR_MCE_KILL, PR_MCE_KILL_SET, PR_MCE_KILL_DEFAULT, 0, 0);
+	printf("prctl(PR_MCE_KILL, PR_MCE_KILL_SET, PR_MCE_KILL_DEFAULT, 0, 0) = %s\n",
+		   sprintrc(rc));
+
+	rc = syscall(__NR_prctl, PR_MCE_KILL_GET, 0, 0, 0, 0);
+	if (rc)
+		printf("prctl(PR_MCE_KILL_GET, 0, 0, 0, 0) = %s (PR_MCE_KILL_DEFAULT)\n",
+			   sprintrc(rc));
+	else
+		printf("prctl(PR_MCE_KILL_GET, 0, 0, 0, 0) = %s\n",
+			   sprintrc(rc));
+
+	rc = syscall(__NR_prctl, PR_MCE_KILL_GET, 0xaaaa, 0xbbbb, 0xcccc, 0xdddd);
+	printf("prctl(PR_MCE_KILL_GET, 0xaaaa, 0xbbbb, 0xcccc, 0xdddd) = %s\n",
+		   sprintrc(rc));
+
+	puts("+++ exited with 0 +++");
+	return 0;
+}
diff --git a/tests/prctl-mce-kill.test b/tests/prctl-mce-kill.test
new file mode 100755
index 00000000..d22a9a52
--- /dev/null
+++ b/tests/prctl-mce-kill.test
@@ -0,0 +1,16 @@
+#!/bin/sh
+#
+# Check decoding of prctl PR_MCE_KILL/PR_MCE_KILL_GET operations.
+#
+# Copyright (c) 2021 The strace developers.
+# All rights reserved.
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+. "${srcdir=.}/init.sh"
+
+check_prog grep
+run_prog > /dev/null
+run_strace -a21 -eprctl $args > "$EXP"
+grep -v '^prctl(PR_[^M][^C][^E]_[^K][^I][^L][^L]' < "$LOG" > "$OUT"
+match_diff "$OUT" "$EXP"
diff --git a/tests/prctl-sve.c b/tests/prctl-sve.c
new file mode 100644
index 00000000..ea212935
--- /dev/null
+++ b/tests/prctl-sve.c
@@ -0,0 +1,53 @@
+/*
+ * Check decoding of prctl PR_SVE_SET_VL/PR_SVE_GET_VL operations.
+ *
+ * Copyright (c) 2021 The strace developers.
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "tests.h"
+#include "scno.h"
+#include <stdio.h>
+#include <unistd.h>
+#include <linux/prctl.h>
+
+int
+main(void)
+{
+	long rc;
+
+	rc = syscall(__NR_prctl, PR_SVE_SET_VL, 0xf);
+	printf("prctl(PR_SVE_SET_VL, %#lx) = %s\n", (unsigned long) 0xf,
+		   sprintrc(rc));
+
+	rc = syscall(__NR_prctl, PR_SVE_SET_VL, 0xff);
+	printf("prctl(PR_SVE_SET_VL, %#lx) = %s\n", (unsigned long) 0xff,
+		   sprintrc(rc));
+
+	rc = syscall(__NR_prctl, PR_SVE_SET_VL, PR_SVE_SET_VL_ONEXEC | 0xff);
+	printf("prctl(PR_SVE_SET_VL, PR_SVE_SET_VL_ONEXEC|%#lx) = %s\n",
+		   (unsigned long) 0xff, sprintrc(rc));
+
+	rc = syscall(__NR_prctl, PR_SVE_SET_VL, PR_SVE_VL_INHERIT | 0xff);
+	printf("prctl(PR_SVE_SET_VL, PR_SVE_VL_INHERIT|%#lx) = %s\n",
+		   (unsigned long) 0xff, sprintrc(rc));
+
+	rc = syscall(__NR_prctl, PR_SVE_SET_VL,
+				 PR_SVE_SET_VL_ONEXEC | PR_SVE_VL_INHERIT | 0xff);
+	printf("prctl(PR_SVE_SET_VL, "
+		   "PR_SVE_SET_VL_ONEXEC|PR_SVE_VL_INHERIT|%#lx) = %s\n",
+		   (unsigned long) 0xff, sprintrc(rc));
+
+	rc = syscall(__NR_prctl, PR_SVE_GET_VL);
+	printf("prctl(PR_SVE_GET_VL) = %s", sprintrc(rc));
+	if (rc >= 0) {
+		printf(" (PR_SVE_SET_VL_ONEXEC|PR_SVE_VL_INHERIT|%#lx)",
+			   (unsigned long) 0xff);
+	}
+	puts("");
+
+	puts("+++ exited with 0 +++");
+	return 0;
+}
diff --git a/tests/prctl-sve.test b/tests/prctl-sve.test
new file mode 100755
index 00000000..14c2805f
--- /dev/null
+++ b/tests/prctl-sve.test
@@ -0,0 +1,16 @@
+#!/bin/sh
+#
+# Check decoding of prctl PR_SVE_SET_VL/PR_SVE_GET_VL operations.
+#
+# Copyright (c) 2021 The strace developers.
+# All rights reserved.
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+. "${srcdir=.}/init.sh"
+
+check_prog grep
+run_prog > /dev/null
+run_strace -a21 -eprctl $args > "$EXP"
+grep -v '^prctl(PR_[^S][^V][^E]_[GS]ET_[^V][^L]' < "$LOG" > "$OUT"
+match_diff "$OUT" "$EXP"
diff --git a/tests/prctl-unalign.c b/tests/prctl-unalign.c
new file mode 100644
index 00000000..8d919b6f
--- /dev/null
+++ b/tests/prctl-unalign.c
@@ -0,0 +1,48 @@
+/*
+ * Check decoding of prctl PR_GET_UNALIGN/PR_SET_UNALIGN operations.
+ *
+ * Copyright (c) 2021 The strace developers.
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "tests.h"
+#include "scno.h"
+#include <stdio.h>
+#include <unistd.h>
+#include <linux/prctl.h>
+
+int
+main(void)
+{
+	TAIL_ALLOC_OBJECT_CONST_PTR(unsigned int, unalign);
+	long rc;
+
+	rc = syscall(__NR_prctl, PR_SET_UNALIGN, PR_UNALIGN_NOPRINT | PR_UNALIGN_SIGBUS);
+	printf("prctl(PR_SET_UNALIGN, PR_UNALIGN_NOPRINT|PR_UNALIGN_SIGBUS) = %s\n",
+		   sprintrc(rc));
+
+	rc = syscall(__NR_prctl, PR_SET_UNALIGN, 0xff00);
+	printf("prctl(PR_SET_UNALIGN, %#llx /* PR_UNALIGN_??? */) = %s\n",
+		   (unsigned long long) 0xff00, sprintrc(rc));
+
+	rc = syscall(__NR_prctl, PR_SET_UNALIGN, PR_UNALIGN_SIGBUS);
+	printf("prctl(PR_SET_UNALIGN, PR_UNALIGN_SIGBUS) = %s\n", sprintrc(rc));
+
+	rc = syscall(__NR_prctl, PR_GET_UNALIGN, unalign + 1);
+	printf("prctl(PR_GET_UNALIGN, %p) = %s\n", unalign + 1, sprintrc(rc));
+
+	rc = syscall(__NR_prctl, PR_GET_UNALIGN, NULL);
+	printf("prctl(PR_GET_UNALIGN, NULL) = %s\n", sprintrc(rc));
+
+	rc = syscall(__NR_prctl, PR_GET_UNALIGN, unalign);
+	if (rc)
+		printf("prctl(PR_GET_UNALIGN, %p) = %s\n", unalign, sprintrc(rc));
+	else
+		printf("prctl(PR_GET_UNALIGN, [PR_UNALIGN_SIGBUS]) = %s\n",
+			   sprintrc(rc));
+
+	puts("+++ exited with 0 +++");
+	return 0;
+}
diff --git a/tests/prctl-unalign.test b/tests/prctl-unalign.test
new file mode 100755
index 00000000..b03540e5
--- /dev/null
+++ b/tests/prctl-unalign.test
@@ -0,0 +1,16 @@
+#!/bin/sh -efu
+#
+# Check decoding of prctl PR_GET_UNALIGN/PR_SET_UNALIGN operations.
+#
+# Copyright (c) 2021 The strace developers.
+# All rights reserved.
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+. "${srcdir=.}/init.sh"
+
+check_prog grep
+run_prog > /dev/null
+run_strace -a28 -eprctl $args > "$EXP"
+grep -v '^prctl(PR_[GS]ET_[^U][^N][^A][^L][^I][^G][^N]' < "$LOG" > "$OUT"
+match_diff "$OUT" "$EXP"
diff --git a/tests/pure_executables.list b/tests/pure_executables.list
index 9c329c4e..52c849ce 100755
--- a/tests/pure_executables.list
+++ b/tests/pure_executables.list
@@ -449,13 +449,18 @@ poke-sendfile
 poll
 ppoll
 prctl-arg2-intptr
+prctl-cap-ambient
+prctl-capbset
 prctl-dumpable
+prctl-mce-kill
 prctl-name
 prctl-no-args
 prctl-pdeathsig
 prctl-securebits
+prctl-sve
 prctl-tid_address
 prctl-tsc
+prctl-unalign
 pread64-pwrite64
 preadv
 preadv-pwritev
-- 
2.25.1



More information about the Strace-devel mailing list