/* * Check decoding of prctl PR_SCHED_CORE operation. * * Copyright (c) 2021 Eugene Syromyatnikov <evgsyr@gmail.com>. * All rights reserved. * * SPDX-License-Identifier: GPL-2.0-or-later */ #include "tests.h" #include "scno.h" #include <inttypes.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <linux/prctl.h> #include "pidns.h" struct op_str { unsigned int op; const char *str; }; #ifdef INJECT_RETVAL # define NUM_SKIP 256 # define INJ_STR " (INJECTED)" #else # define NUM_SKIP 1 # define INJ_STR "" #endif int main(int argc, char *argv[]) { PIDNS_TEST_INIT; long rc; unsigned long num_skip = NUM_SKIP; if (argc >= 2) num_skip = strtoul(argv[1], NULL, 0); for (size_t i = 0; i < num_skip; i++) { rc = prctl_marker(); #ifdef PIDNS_TRANSLATION const char *errstr = sprintrc(rc); pidns_print_leader(); printf("prctl(" XLAT_UNKNOWN(0xffffffff, "PR_???") ", 0xfffffffe, 0xfffffffd, 0xfffffffc, 0xfffffffb) = "); if (rc < 0) { puts(errstr); } else { printf("%ld (INJECTED)\n", rc); } #endif if (rc < 0) continue; break; } static const struct { unsigned int decode_ptr:1, valid:1; unsigned int op; const char *str; } ops[] = { { true, true, ARG_STR(PR_SCHED_CORE_GET) }, { false, true, ARG_STR(PR_SCHED_CORE_CREATE) }, { false, true, ARG_STR(PR_SCHED_CORE_SHARE_TO) }, { false, true, ARG_STR(PR_SCHED_CORE_SHARE_FROM) }, { false, false, 4, "PR_SCHED_CORE_???" }, }; static const struct { unsigned int val; const char *str; } pidtypes[] = { { 0, "PIDTYPE_PID" }, { 1, "PIDTYPE_TGID" }, { 2, "PIDTYPE_PGID" }, { 3, "PIDTYPE_SID" }, { 4, "PIDTYPE_???" }, { -1U, "PIDTYPE_???" }, }; int ids[5]; ids[0] = syscall(__NR_gettid); ids[1] = getpid(); ids[2] = getpgid(0); ids[3] = getsid(0); ids[4] = -1; TAIL_ALLOC_OBJECT_VAR_PTR(uint64_t, uptr); uint64_t *uptrs[] = { NULL, uptr + 1, uptr }; for (size_t i = 0; i < ARRAY_SIZE(ops); i++) { for (size_t j = 0; j < ARRAY_SIZE(pidtypes); j++) { for (size_t k = 0; k < ARRAY_SIZE(uptrs); k++) { *uptr = 0xdeadc0debadc0dedULL; rc = syscall(__NR_prctl, PR_SCHED_CORE, ops[i].op | F8ILL_KULONG_MASK, ids[MIN(pidtypes[j].val, 4)] | F8ILL_KULONG_MASK, pidtypes[j].val | F8ILL_KULONG_MASK, uptrs[k]); const char *errstr = sprintrc(rc); pidns_print_leader(); printf("prctl(" XLAT_KNOWN(0x3e, "PR_SCHED_CORE") ", "); if (ops[i].valid) { printf(XLAT_FMT, XLAT_SEL(ops[i].op, ops[i].str)); } else { printf("%#x" NRAW(" /* PR_SCHED_CORE_??? */"), ops[i].op); } printf(", %d%s, %#x" NRAW(" /* %s */") ", ", ids[MIN(pidtypes[j].val, 4)], pidns_pid2str(pidtypes[j].val), pidtypes[j].val #if !XLAT_RAW , pidtypes[j].str #endif ); if (uptrs[k]) { if (uptrs[k] == uptr && ops[i].decode_ptr && rc >= 0) #ifdef INJECT_RETVAL printf("[0xdeadc0debadc0ded]"); #else printf("[%#" PRIx64 "]", *uptr); #endif else printf("%p", uptrs[k]); } else { printf("NULL"); } printf(") = %s" INJ_STR "\n", errstr); } } } pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; }