Skip to content

Commit

Permalink
prctl: implement PR_SET_VMA decoding for non-Android platforms
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
ldv-alt committed Jan 30, 2022
1 parent 46929b4 commit 8852bfb
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 19 deletions.
1 change: 1 addition & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
23 changes: 6 additions & 17 deletions src/prctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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"
Expand Down Expand Up @@ -353,27 +347,22 @@ 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();
printstr(tcp, arg5);
} 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();
Expand Down
3 changes: 3 additions & 0 deletions src/xlat/pr_set_vma.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#unconditional
#value_indexed
PR_SET_VMA_ANON_NAME
2 changes: 0 additions & 2 deletions src/xlat/prctl_options.in
Original file line number Diff line number Diff line change
Expand Up @@ -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
1 change: 1 addition & 0 deletions tests/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions tests/gen_tests.in
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
82 changes: 82 additions & 0 deletions tests/prctl-set_vma.c
Original file line number Diff line number Diff line change
@@ -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;
}
1 change: 1 addition & 0 deletions tests/pure_executables.list
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 8852bfb

Please sign in to comment.