From 626b62c4145a2c5c18b2411d89043e49a06cb2d4 Mon Sep 17 00:00:00 2001 From: Giuliano Belinassi Date: Wed, 10 Apr 2024 16:56:00 -0300 Subject: [PATCH] Check for ptrace_scope before doing ulp operations YAMA has a security feature that block ptrace of non-child processes. Check for that when the command is issued to make sure everything will work as it should. Signed-off-by: Giuliano Belinassi --- tools/ptrace.c | 35 +++++++++++++++++++++++++++++++++-- tools/ptrace.h | 4 ++++ tools/ulp.c | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 2 deletions(-) diff --git a/tools/ptrace.c b/tools/ptrace.c index ffc6731d..3383f247 100644 --- a/tools/ptrace.c +++ b/tools/ptrace.c @@ -38,6 +38,7 @@ #include #include #include +#include #include "error_common.h" #include "introspection.h" @@ -401,7 +402,7 @@ attach(int pid) if (ulp_ptrace(PTRACE_ATTACH, pid, NULL, NULL)) { DEBUG("PTRACE_ATTACH error: %s.\n", strerror(errno)); - return 1; + return errno; } while (true) { @@ -409,7 +410,7 @@ attach(int pid) if (ret == -1) { DEBUG("waitpid error (pid %d): %s.\n", pid, strerror(errno)); - return 1; + return errno; } else if (ret == pid) { @@ -608,3 +609,33 @@ run_and_redirect(int pid, struct user_regs_struct *regs, ElfW(Addr) routine) return 0; } + + +/** @brief Check ptrace scope security option. + * + * In some systems, ptracing a simbling process is disalowed with a permission + * error. This function will check if we are in such case, which we should + * error out and instruct the user what to do. + * + * @return: true if ptrace of simblings works. + **/ +bool +check_ptrace_scope(void) +{ + if (geteuid() == 0) { + /* Running as root. No problem. */ + return true; + } + + FILE *f = fopen("/proc/sys/kernel/yama/ptrace_scope", "r"); + if (f == NULL) { + /* YAMA is not running. */ + return true; + } + + unsigned char buf[4] = {0}; + size_t n = fread(buf, sizeof(unsigned char), 4, f); + assert(n == 2 && "What is in the ptrace_scope?"); + fclose(f); + return buf[0] == '0' ? true : false; +} diff --git a/tools/ptrace.h b/tools/ptrace.h index 445a3cd6..7330f360 100644 --- a/tools/ptrace.h +++ b/tools/ptrace.h @@ -26,9 +26,13 @@ #include #include #include +#include #include "ulp_common.h" +/* System configuration options. */ +bool check_ptrace_scope(void); + /* Memory read/write helper functions */ int write_bytes_ptrace(const void *buf, size_t n, int pid, Elf64_Addr addr); diff --git a/tools/ulp.c b/tools/ulp.c index d48c8ba2..16b7a445 100644 --- a/tools/ulp.c +++ b/tools/ulp.c @@ -450,6 +450,28 @@ change_color(const char *ansi_escape) } } +static bool +requires_ptrace(command_t command) +{ + switch(command) { + case ULP_NONE: + case ULP_DUMP: + case ULP_POST: + case ULP_EXTRACT: + case ULP_PACKER: + case ULP_LIVEPATCHABLE: + return false; + + case ULP_PATCHES: + case ULP_TRIGGER: + case ULP_CHECK: + case ULP_MESSAGES: + case ULP_SET_PATCHABLE: + return true; + } + return false; +} + int main(int argc, char **argv, char *envp[] __attribute__((unused))) { @@ -476,6 +498,17 @@ main(int argc, char **argv, char *envp[] __attribute__((unused))) argp_parse(&argp, argc, argv, 0, 0, &arguments); + + /* Check if command requires ptrace. */ + if (requires_ptrace(arguments.command) && + check_ptrace_scope() == false) { + WARN("System has 'ptrace_scope' enabled. Please become root or disable it" + "by setting:\n\n" + "$ sudo echo 0 > /proc/sys/kernel/yama/ptrace_scope\n\n" + "and try again."); + return EPERM; + } + switch (arguments.command) { case ULP_NONE: ret = 1;