summaryrefslogtreecommitdiff
path: root/tests/prctl-mdwe.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/prctl-mdwe.c')
-rw-r--r--tests/prctl-mdwe.c149
1 files changed, 149 insertions, 0 deletions
diff --git a/tests/prctl-mdwe.c b/tests/prctl-mdwe.c
new file mode 100644
index 000000000..00c30e9a3
--- /dev/null
+++ b/tests/prctl-mdwe.c
@@ -0,0 +1,149 @@
+/*
+ * Check decoding of prctl PR_GET_MDWE/PR_SET_MDWE operations.
+ *
+ * Copyright (c) 2021-2023 The strace developers.
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "tests.h"
+#include "scno.h"
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <linux/prctl.h>
+
+static long injected_val;
+
+static long
+do_prctl(kernel_ulong_t cmd, kernel_ulong_t arg2, kernel_ulong_t arg3,
+ kernel_ulong_t arg4, kernel_ulong_t arg5)
+{
+ long rc = syscall(__NR_prctl, cmd, arg2, arg3, arg4, arg5);
+
+ 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) 0xbadc0dedfacef00dULL;
+ static const kernel_ulong_t bogus_arg4 =
+ (kernel_ulong_t) 0xcafeda7efeedbeefULL;
+ static const kernel_ulong_t bogus_arg5 =
+ (kernel_ulong_t) 0xfa57beeffacefeedULL;
+
+ static const struct {
+ long arg;
+ const char *str;
+ } get_strs[] = {
+ {-1, ""},
+ {0, ""},
+ {1, " (PR_MDWE_REFUSE_EXEC_GAIN)"},
+ {2, ""},
+ {3, " (PR_MDWE_REFUSE_EXEC_GAIN|0x2)"},
+ {0x7ea1cafe, ""},
+ };
+ static const struct {
+ kernel_ulong_t arg;
+ const char *str;
+ } set_strs[] = {
+ {0, "0"},
+ {1, "PR_MDWE_REFUSE_EXEC_GAIN"},
+ {2, "0x2 /* PR_MDWE_??? */"},
+ {3, "PR_MDWE_REFUSE_EXEC_GAIN|0x2"},
+ {0x7ea1cafe, "0x7ea1cafe /* PR_MDWE_??? */"}
+ };
+
+ long rc;
+ unsigned long num_skip;
+ const char *str = NULL;
+ bool locked = false;
+
+ if (argc < 3)
+ error_msg_and_fail("Usage: %s NUM_SKIP INJECT_RETVAL", argv[0]);
+
+ num_skip = strtoul(argv[1], NULL, 0);
+ injected_val = strtol(argv[2], NULL, 0);
+
+ for (size_t i = 0; i < num_skip; i++) {
+ if ((prctl_marker() != injected_val) ||
+ ((injected_val == -1) && (errno != ENOTTY)))
+ continue;
+
+ locked = true;
+ break;
+ }
+
+ if (!locked)
+ error_msg_and_fail("Have not locked on prctl(-1, -2, -3, -4"
+ ", -5) returning %ld", injected_val);
+
+ /* PR_GET_MDWE */
+ for (unsigned int j = 0; j < 2; j++) {
+ if (j) {
+ rc = do_prctl(PR_GET_MDWE, bogus_arg2, bogus_arg3,
+ bogus_arg4, bogus_arg5);
+ } else {
+ rc = do_prctl(PR_GET_MDWE, 0, 0, 0, 0);
+ }
+
+ const char *errstr = sprintrc(rc);
+
+ 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_MDWE, %s) = ", j ?
+#if SIZEOF_KERNEL_LONG_T > 4
+ "0xdecafeedbeefda7e, 0xbadc0dedfacef00d"
+ ", 0xcafeda7efeedbeef, 0xfa57beeffacefeed"
+#else
+ "0xbeefda7e, 0xfacef00d, 0xfeedbeef, 0xfacefeed"
+#endif
+ : "0, 0, 0, 0");
+ if (rc < 0)
+ printf("%s", errstr);
+ else
+ printf("%#lx", rc);
+ printf("%s (INJECTED)\n", str);
+ }
+
+ /* PR_SET_FP_MODE */
+ for (size_t i = 0; i < ARRAY_SIZE(set_strs); i++) {
+ rc = do_prctl(PR_SET_MDWE, set_strs[i].arg, 0, 0, 0);
+ printf("prctl(PR_SET_MDWE, %s, 0, 0, 0) = %s (INJECTED)\n",
+ set_strs[i].str, sprintrc(rc));
+
+ rc = do_prctl(PR_SET_MDWE, set_strs[i].arg,
+ bogus_arg3, bogus_arg4, bogus_arg5);
+ printf("prctl(PR_SET_MDWE, %s, %s) = %s (INJECTED)\n",
+ set_strs[i].str,
+#if SIZEOF_KERNEL_LONG_T > 4
+ "0xbadc0dedfacef00d, 0xcafeda7efeedbeef"
+ ", 0xfa57beeffacefeed"
+#else
+ "0xfacef00d, 0xfeedbeef, 0xfacefeed"
+#endif
+ , sprintrc(rc));
+ }
+
+ puts("+++ exited with 0 +++");
+ return 0;
+}