From 45cae1542f07deb04dc90e4186d3bb7b61a5b516 Mon Sep 17 00:00:00 2001 From: Eugene Syromyatnikov Date: Fri, 28 Apr 2023 18:24:59 +0200 Subject: prctl: implement PR_[GS]ET_MDWE decoding 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)) : 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. --- NEWS | 6 +- src/prctl.c | 21 ++++++- src/xlat/pr_mdwe_flags.in | 1 + tests/.gitignore | 1 + tests/Makefile.am | 1 + tests/gen_tests.in | 1 + tests/prctl-mdwe.c | 149 ++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 176 insertions(+), 4 deletions(-) create mode 100644 src/xlat/pr_mdwe_flags.in create mode 100644 tests/prctl-mdwe.c 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 +#include +#include +#include +#include + +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; +} -- cgit v1.2.1