From e34733b09ceaead84dcdca6e66f40e4991fe8507 Mon Sep 17 00:00:00 2001 From: Adrian Muzyka Date: Wed, 5 Jun 2024 07:52:36 +0000 Subject: [PATCH] Support cmd execution timeout in service mode --- memcr.c | 116 ++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 88 insertions(+), 28 deletions(-) diff --git a/memcr.c b/memcr.c index 6009b03..ae557a6 100644 --- a/memcr.c +++ b/memcr.c @@ -119,6 +119,7 @@ static int rss_file; static int compress; static int checksum; static int service; +static unsigned int timeout; #define BIT(x) (1ULL << x) @@ -495,6 +496,7 @@ static int seize_pid(pid_t pid) } try_again: + ret = ptrace(PTRACE_INTERRUPT, pid, NULL, NULL); if (ret) { fprintf(stderr, "ptrace(PTRACE_INTERRUPT) pid %d: %m\n", pid); @@ -535,6 +537,7 @@ static int seize_pid(pid_t pid) return 1; } + printf("[i] delivered signal %d to pid %d\n", si.si_signo, pid); goto try_again; } @@ -549,6 +552,25 @@ static int seize_pid(pid_t pid) return 0; } +static int unseize_pid(pid_t pid) +{ + return ptrace(PTRACE_DETACH, pid, NULL, 0); +} + +static int unseize_target(void) +{ + int ret = 0; + int i; + + printf("[+] unseizing target\n"); + + for (i = 0; i < nr_threads; i++) + ret |= unseize_pid(tids[i]); + nr_threads = 0; + + return ret; +} + static int seize_target(pid_t pid) { int ret; @@ -573,25 +595,6 @@ static int seize_target(pid_t pid) return 0; } -static int unseize_pid(pid_t pid) -{ - return ptrace(PTRACE_DETACH, pid, NULL, 0); -} - -static int unseize_target(void) -{ - int ret = 0; - int i; - - printf("[+] unseizing target\n"); - - for (i = 0; i < nr_threads; i++) - ret |= unseize_pid(tids[i]); - nr_threads = 0; - - return ret; -} - static int parasite_socket_create(pid_t pid) { int pid_netns = -1; @@ -688,6 +691,8 @@ static int __read(int fd, void *buf, size_t count, int (*check_peer_ok)(void), i continue; break; + } else if (errno == EINTR) { + continue; } if (silent == FALSE) @@ -923,6 +928,20 @@ static void clear_pid_on_worker_exit_non_blocking(pid_t worker) } } +static int get_pid_worker(pid_t pid) +{ + int worker = PID_INVALID; + pthread_mutex_lock(&checkpoint_service_data_lock); + for (int i=0; i 0) { close(checkpoint_resp_sockets[1]); set_pid_checkpointing(svc_ctx.svc_cmd.pid, checkpoint_resp_sockets[0]); - checkpoint_procedure_service(checkpoint_resp_sockets[0], svc_ctx.cd); - set_pid_checkpointed(svc_ctx.svc_cmd.pid, forkpid); + if (checkpoint_procedure_service(checkpoint_resp_sockets[0], svc_ctx.cd, + svc_ctx.svc_cmd.pid, forkpid)) + clear_pid_checkpoint_data(svc_ctx.svc_cmd.pid); + else + set_pid_checkpointed(svc_ctx.svc_cmd.pid, forkpid); + close(checkpoint_resp_sockets[0]); } else { fprintf(stderr, "%s(): Fork error!\n", __func__); + clear_pid_checkpoint_data(svc_ctx.svc_cmd.pid); } break; } case MEMCR_RESTORE: { fprintf(stdout, "[+] handling MEMCR_RESTORE for %d.\n", svc_ctx.svc_cmd.pid); - restore_procedure_service(svc_ctx.cd, svc_ctx.svc_cmd); + int worker_pid = get_pid_worker(svc_ctx.svc_cmd.pid); + if (worker_pid == PID_INVALID) { + fprintf(stderr, "%s(): Error, worker pid not found for %d!\n", __func__, svc_ctx.svc_cmd.pid); + send_response_to_client(svc_ctx.cd, MEMCR_ERROR_GENERAL); + close(svc_ctx.cd); + break; + } + restore_procedure_service(svc_ctx.cd, svc_ctx.svc_cmd, worker_pid); clear_pid_checkpoint_data(svc_ctx.svc_cmd.pid); break; } @@ -2800,7 +2855,8 @@ static void usage(const char *name, int status) " -f --rss-file include file mapped memory\n" \ " -z --compress compress memory dump\n" \ " -c --checksum enable md5 checksum for memory dump\n" \ - " -e --encrypt enable encryption of memory dump\n", + " -e --encrypt enable encryption of memory dump\n" \ + " -t --timeout timeout in seconds for checkpoint/restore execution in service mode\n", name); exit(status); @@ -2840,6 +2896,7 @@ int main(int argc, char *argv[]) { "compress", 0, NULL, 'z'}, { "checksum", 0, NULL, 'c'}, { "encrypt", 2, 0, 'e'}, + { "timeout", 1, 0, 't'}, { NULL, 0, NULL, 0 } }; @@ -2847,7 +2904,7 @@ int main(int argc, char *argv[]) parasite_socket_dir = NULL; parasite_socket_use_netns = 0; - while ((opt = getopt_long(argc, argv, "hp:d:S:Nl:nmfzce::", long_options, &option_index)) != -1) { + while ((opt = getopt_long(argc, argv, "hp:d:S:Nl:nmfzce::t:", long_options, &option_index)) != -1) { switch (opt) { case 'h': usage(argv[0], 0); @@ -2896,6 +2953,9 @@ int main(int argc, char *argv[]) else if (optind < argc && argv[optind][0] != '-') encrypt_arg = argv[optind++]; break; + case 't': + timeout = atoi(optarg); + break; default: /* '?' */ usage(argv[0], 1); }