summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugene Syromyatnikov <evgsyr@gmail.com>2023-04-28 18:24:59 +0200
committerEugene Syromyatnikov <evgsyr@gmail.com>2023-04-28 18:27:45 +0200
commit45cae1542f07deb04dc90e4186d3bb7b61a5b516 (patch)
treed3590d99c2eda48117ac9c93c10f6c9d3fd1a2fa
parent65ecda71587add30414c373f6f3716461aeaaf2c (diff)
downloadstrace-esyr/prctl-mdwe.tar.gz
prctl: implement PR_[GS]ET_MDWE decodingesyr/prctl-mdwe
Introduced by Linux commit v6.3-rc1~113^2~215. * src/xlat/pr_mdwe_flags.in: New file. * src/prctl.c: Include "xlat/pr_mdwe_flags.h". (SYS_FUNC(prctl)) <case PR_SET_MDWE, case PR_GET_MDWE>: Implement command decoders. * tests/.gitignore: Add prctl-mdwe. * tests/Makefile.am (check_PROGRAMS): Add prctl-mdwe. * tests/gen_tests.in (prctl-mdwe): New test. * tests/prctl-mdwe.c: New file. * NEWS: Mention it.
-rw-r--r--NEWS6
-rw-r--r--src/prctl.c21
-rw-r--r--src/xlat/pr_mdwe_flags.in1
-rw-r--r--tests/.gitignore1
-rw-r--r--tests/Makefile.am1
-rw-r--r--tests/gen_tests.in1
-rw-r--r--tests/prctl-mdwe.c149
7 files changed, 176 insertions, 4 deletions
diff --git a/NEWS b/NEWS
index c614cd0ab..964b868e6 100644
--- a/NEWS
+++ b/NEWS
@@ -6,11 +6,13 @@ Noteworthy changes in release ?.? (????-??-??)
that operate on the specified set of file descriptors.
* Implemented -l/--syscall-limit option to automatically detach tracees
after capturing the specified number of syscalls.
+ * Implemented decoding of PR_GET_MDWE and PR_SET_MDWE operations of prctl
+ syscall.
* Implemented decoding of IFLA_BRPORT_MCAST_N_GROUPS,
IFLA_BRPORT_MCAST_MAX_GROUPS, IFLA_GSO_IPV4_MAX_SIZE,
IFLA_GRO_IPV4_MAX_SIZE, and TCA_EXT_WARN_MSG netlink attributes.
- * Updated lists of F_SEAL_*, IFLA_*, IORING_*, IP_*, MFD_*, NFT_*, PR_*,
- TCA_*, and V4L2_PIX_FMT_* constants.
+ * Updated lists of F_SEAL_*, IFLA_*, IORING_*, IP_*, MFD_*, NFT_*, TCA_*,
+ and V4L2_PIX_FMT_* constants.
* Updated lists of ioctl commands from Linux 6.3.
Noteworthy changes in release 6.2 (2023-02-26)
diff --git a/src/prctl.c b/src/prctl.c
index 6c1776522..2396c6bc6 100644
--- a/src/prctl.c
+++ b/src/prctl.c
@@ -20,6 +20,7 @@
#include "xlat/pr_fp_mode.h"
#include "xlat/pr_mce_kill.h"
#include "xlat/pr_mce_kill_policy.h"
+#include "xlat/pr_mdwe_flags.h"
#include "xlat/pr_pac_enabled_keys.h"
#include "xlat/pr_pac_keys.h"
#include "xlat/pr_sched_core_cmds.h"
@@ -360,6 +361,18 @@ SYS_FUNC(prctl)
return RVAL_HEX | RVAL_STR;
+ case PR_GET_MDWE:
+ if (entering(tcp)) {
+ print_prctl_args(tcp, 1);
+ break;
+ }
+ if (syserror(tcp))
+ return 0;
+ tcp->auxstr = sprintflags_ex("", pr_mdwe_flags,
+ (kernel_ulong_t) tcp->u_rval, '\0',
+ XLAT_STYLE_DEFAULT | SPFF_AUXSTR_MODE);
+ return RVAL_HEX | RVAL_STR;
+
/* PR_TASK_PERF_EVENTS_* take no arguments. */
case PR_TASK_PERF_EVENTS_DISABLE:
case PR_TASK_PERF_EVENTS_ENABLE:
@@ -497,10 +510,15 @@ SYS_FUNC(prctl)
printflags(pr_unalign_flags, arg2, "PR_UNALIGN_???");
return RVAL_DECODED;
+ case PR_SET_MDWE:
+ tprint_arg_next();
+ printflags(pr_mdwe_flags, arg2, "PR_MDWE_???");
+ print_prctl_args(tcp, 2);
+ return RVAL_DECODED;
+
case PR_SET_NO_NEW_PRIVS:
case PR_SET_THP_DISABLE:
case PR_SET_IO_FLUSHER:
- case PR_SET_MDWE:
tprint_arg_next();
PRINT_VAL_U(arg2);
print_prctl_args(tcp, 2);
@@ -629,7 +647,6 @@ SYS_FUNC(prctl)
case PR_MPX_DISABLE_MANAGEMENT:
case PR_MPX_ENABLE_MANAGEMENT:
case PR_GET_IO_FLUSHER:
- case PR_GET_MDWE:
default:
print_prctl_args(tcp, 1);
return RVAL_DECODED;
diff --git a/src/xlat/pr_mdwe_flags.in b/src/xlat/pr_mdwe_flags.in
new file mode 100644
index 000000000..581da1fd2
--- /dev/null
+++ b/src/xlat/pr_mdwe_flags.in
@@ -0,0 +1 @@
+PR_MDWE_REFUSE_EXEC_GAIN 1
diff --git a/tests/.gitignore b/tests/.gitignore
index 62f1fd0f4..a39408627 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -718,6 +718,7 @@ prctl-capbset
prctl-dumpable
prctl-fp-mode
prctl-mce-kill
+prctl-mdwe
prctl-name
prctl-no-args
prctl-pac-enabled-keys
diff --git a/tests/Makefile.am b/tests/Makefile.am
index b2734b77b..170876eed 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -286,6 +286,7 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \
ppoll-e-trace-fds-not-9-42-P \
ppoll-v \
prctl-fp-mode \
+ prctl-mdwe \
prctl-pac-enabled-keys-success \
prctl-pac-enabled-keys-success-Xabbrev \
prctl-pac-enabled-keys-success-Xraw \
diff --git a/tests/gen_tests.in b/tests/gen_tests.in
index e4686ea40..db70ee1b4 100644
--- a/tests/gen_tests.in
+++ b/tests/gen_tests.in
@@ -718,6 +718,7 @@ prctl-capbset +prctl.sh -a21
prctl-dumpable +prctl.sh -a23
prctl-fp-mode +prctl-success.sh PRCTL_INJECT_RETVALS="error=ENOTTY 0 1 2 3 32 35" -a21
prctl-mce-kill +prctl.sh -a21
+prctl-mdwe +prctl-success.sh PRCTL_INJECT_RETVALS="error=ENOTTY 0 1 2 3 2124532478" -a31
prctl-name +prctl.sh -a23
prctl-no-args +prctl.sh -a21
prctl-pac-enabled-keys +prctl.sh -a43
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;
+}