diff options
author | Dmitry V. Levin <ldv@strace.io> | 2022-01-30 08:00:00 +0000 |
---|---|---|
committer | Dmitry V. Levin <ldv@strace.io> | 2022-01-30 08:00:00 +0000 |
commit | 8852bfb4a0fb9cb53b4f24b5d293f36667882a95 (patch) | |
tree | 7bf0daec818e60834ed08abb69f2b3355fcfd2f7 | |
parent | 46929b48711a69569420f98c0fc92a7614314f06 (diff) | |
download | strace-8852bfb4a0fb9cb53b4f24b5d293f36667882a95.tar.gz |
prctl: implement PR_SET_VMA decoding for non-Android platforms
PR_SET_VMA used to be specific to Android until Linux kernel commit
v5.17-rc1~79^2~89.
* NEWS: Mention this change.
* src/xlat/prctl_options.in (PR_SET_VMA): Remove __ANDROID__ guard.
* src/xlat/pr_set_vma.in: New file.
* src/prctl.c [__ANDROID__ && !PR_SET_VMA]: Remove.
[__ANDROID__ && !PR_SET_VMA_ANON_NAME]: Likewise.
(SYS_FUNC(prctl)) <PR_SET_VMA>: Remove __ANDROID__ guard, enhance
decoding.
* tests/prctl-set_vma.c: New file.
* tests/gen_tests.in (prctl-set_vma): New test.
* tests/pure_executables.list: Add prctl-set_vma.
* tests/.gitignore: Likewise.
-rw-r--r-- | NEWS | 1 | ||||
-rw-r--r-- | src/prctl.c | 23 | ||||
-rw-r--r-- | src/xlat/pr_set_vma.in | 3 | ||||
-rw-r--r-- | src/xlat/prctl_options.in | 2 | ||||
-rw-r--r-- | tests/.gitignore | 1 | ||||
-rw-r--r-- | tests/gen_tests.in | 1 | ||||
-rw-r--r-- | tests/prctl-set_vma.c | 82 | ||||
-rwxr-xr-x | tests/pure_executables.list | 1 |
8 files changed, 95 insertions, 19 deletions
@@ -9,6 +9,7 @@ Noteworthy changes in release ?.?? (????-??-??) expressions. * Implemented decoding of IFLA_GRO_MAX_SIZE and TCA_ACT_IN_HW_COUNT netlink attributes. + * Implemented decoding of PR_SET_VMA operation of prctl syscall. * Updated lists of FAN_*, IORING_*, IOSQE_*, KVM_*, MODULE_INIT_*, TCA_ACT_*, and *_MAGIC constants. diff --git a/src/prctl.c b/src/prctl.c index 4275e5f70..d4b0ca622 100644 --- a/src/prctl.c +++ b/src/prctl.c @@ -10,17 +10,10 @@ */ #include "defs.h" +#include "xstring.h" #include <linux/prctl.h> -#ifdef __ANDROID__ -# ifndef PR_SET_VMA -# define PR_SET_VMA 0x53564d41 /* "SVMA" */ -# endif -#endif - -#include "xstring.h" - #include "xlat/prctl_options.h" #include "xlat/pr_cap_ambient.h" #include "xlat/pr_dumpable.h" @@ -32,6 +25,7 @@ #include "xlat/pr_sched_core_cmds.h" #include "xlat/pr_sched_core_pidtypes.h" #include "xlat/pr_set_mm.h" +#include "xlat/pr_set_vma.h" #include "xlat/pr_spec_cmds.h" #include "xlat/pr_spec_get_store_bypass_flags.h" #include "xlat/pr_spec_set_store_bypass_flags.h" @@ -353,16 +347,12 @@ SYS_FUNC(prctl) QUOTE_0_TERMINATED); return RVAL_DECODED; -#ifdef __ANDROID__ -# ifndef PR_SET_VMA_ANON_NAME -# define PR_SET_VMA_ANON_NAME 0 -# endif case PR_SET_VMA: + tprint_arg_next(); + printxval64(pr_set_vma, arg2, "PR_SET_VMA_???"); if (arg2 == PR_SET_VMA_ANON_NAME) { tprint_arg_next(); - print_xlat(PR_SET_VMA_ANON_NAME); - tprint_arg_next(); - PRINT_VAL_X(arg3); + printaddr(arg3); tprint_arg_next(); PRINT_VAL_U(arg4); tprint_arg_next(); @@ -370,10 +360,9 @@ SYS_FUNC(prctl) } else { /* There are no other sub-options now, but there * might be in future... */ - print_prctl_args(tcp, 1); + print_prctl_args(tcp, 2); } return RVAL_DECODED; -#endif case PR_SET_MM: tprint_arg_next(); diff --git a/src/xlat/pr_set_vma.in b/src/xlat/pr_set_vma.in new file mode 100644 index 000000000..5936351fd --- /dev/null +++ b/src/xlat/pr_set_vma.in @@ -0,0 +1,3 @@ +#unconditional +#value_indexed +PR_SET_VMA_ANON_NAME diff --git a/src/xlat/prctl_options.in b/src/xlat/prctl_options.in index 38823d51b..dffff49b2 100644 --- a/src/xlat/prctl_options.in +++ b/src/xlat/prctl_options.in @@ -58,7 +58,5 @@ PR_SET_SYSCALL_USER_DISPATCH PR_PAC_SET_ENABLED_KEYS PR_PAC_GET_ENABLED_KEYS PR_SCHED_CORE -#ifdef __ANDROID__ PR_SET_VMA -#endif PR_SET_PTRACER diff --git a/tests/.gitignore b/tests/.gitignore index 128d9a076..a636eceb3 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -724,6 +724,7 @@ prctl-set-ptracer-success-Xraw prctl-set-ptracer-success-Xraw--pidns-translation prctl-set-ptracer-success-Xverbose prctl-set-ptracer-success-Xverbose--pidns-translation +prctl-set_vma prctl-spec-inject prctl-sve prctl-syscall-user-dispatch diff --git a/tests/gen_tests.in b/tests/gen_tests.in index 4b16f9bff..23b9bce1d 100644 --- a/tests/gen_tests.in +++ b/tests/gen_tests.in @@ -719,6 +719,7 @@ prctl-set-ptracer-success-Xraw +prctl-success.sh PRCTL_INJECT_RETVALS=0 -a20 -X prctl-set-ptracer-success-Xraw--pidns-translation check_scno_tampering; test_pidns -einject=prctl:when=256+:retval=0 -etrace=prctl -a27 "QUIRK:START-OF-TEST-OUTPUT:prctl(0xffffffff, 0xfffffffe, 0xfffffffd, 0xfffffffc, 0xfffffffb)" -Xraw prctl-set-ptracer-success-Xverbose +prctl-success.sh PRCTL_INJECT_RETVALS=0 -a42 -Xverbose prctl-set-ptracer-success-Xverbose--pidns-translation check_scno_tampering; test_pidns -einject=prctl:when=256+:retval=0 -etrace=prctl -a48 "QUIRK:START-OF-TEST-OUTPUT:prctl(0xffffffff /* PR_??? */, 0xfffffffe, 0xfffffffd, 0xfffffffc, 0xfffffffb)" -Xverbose +prctl-set_vma +prctl.sh prctl-spec-inject +prctl-success.sh PRCTL_INJECT_RETVALS="error=ENOTTY 0 1 3 8 16 32 42" -a50 prctl-sve +prctl.sh -a21 prctl-syscall-user-dispatch +prctl.sh -a68 diff --git a/tests/prctl-set_vma.c b/tests/prctl-set_vma.c new file mode 100644 index 000000000..0929565f9 --- /dev/null +++ b/tests/prctl-set_vma.c @@ -0,0 +1,82 @@ +/* + * Check decoding of prctl PR_SET_VMA operation. + * + * Copyright (c) 2019-2022 Dmitry V. Levin <ldv@strace.io> + * 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> + +static const kernel_ulong_t fill = (kernel_ulong_t) 0xdefaced00000000ULL; +static const char *errstr; + +static long +pr_set_vma(const kernel_ulong_t op, const void *const addr, + const kernel_ulong_t size, const void *const arg) +{ + const kernel_ulong_t bad = (kernel_ulong_t) 0xbadc0dedbadc0dedULL; + const kernel_ulong_t arg1 = fill | PR_SET_VMA; + const kernel_ulong_t arg2 = op; + const kernel_ulong_t arg3 = (uintptr_t) addr; + const kernel_ulong_t arg4 = size; + const kernel_ulong_t arg5 = (uintptr_t) arg; + const long rc = syscall(__NR_prctl, arg1, arg2, arg3, arg4, arg5, bad); + errstr = sprintrc(rc); + return rc; +} + +int +main(void) +{ + prctl_marker(); + + char *const name1 = tail_alloc(DEFAULT_STRLEN + 2); + char *const name = name1 + 1; + const void *const efault = name + DEFAULT_STRLEN + 1; + const char *const empty = efault - 1; + fill_memory_ex(name1, DEFAULT_STRLEN + 1, '0', 10); + name1[DEFAULT_STRLEN + 1] = '\0'; + + pr_set_vma(0, 0, 1, name); + printf("prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, NULL, 1, \"%s\")" + " = %s\n", + name, errstr); + + pr_set_vma(0, empty, 2, name1); + printf("prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, %p, 2, \"%.*s\"...)" + " = %s\n", + empty, DEFAULT_STRLEN, name1, errstr); + + pr_set_vma(0, empty, 3, efault); + printf("prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, %p, 3, %p)" + " = %s\n", + empty, efault, errstr); + + pr_set_vma(0, empty, 4, 0); + printf("prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, %p, 4, NULL)" + " = %s\n", + empty, errstr); + + pr_set_vma(0, efault, 5, empty); + printf("prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, %p, 5, \"\")" + " = %s\n", + efault, errstr); + + const kernel_ulong_t bad_op = fill | 0xface1fed; + const kernel_ulong_t bad_size = fill | 0xface2fed; + + pr_set_vma(bad_op, efault, bad_size, empty); + printf("prctl(PR_SET_VMA, %#llx /* PR_SET_VMA_??? */, %p, %#llx, %p)" + " = %s\n", + (unsigned long long) bad_op, efault, + (unsigned long long) bad_size, empty, errstr); + + puts("+++ exited with 0 +++"); + return 0; +} diff --git a/tests/pure_executables.list b/tests/pure_executables.list index 296e22359..4ee581692 100755 --- a/tests/pure_executables.list +++ b/tests/pure_executables.list @@ -514,6 +514,7 @@ prctl-sched-core-Xabbrev prctl-sched-core-Xraw prctl-sched-core-Xverbose prctl-securebits +prctl-set_vma prctl-sve prctl-syscall-user-dispatch prctl-tagged-addr |