diff --git a/recipes-extended/memcr/files/0001-RDK-47153-Option-to-set-dump-dir-and-compression-per.patch b/recipes-extended/memcr/files/0001-RDK-47153-Option-to-set-dump-dir-and-compression-per.patch index 799c0f51..cfdb07ab 100644 --- a/recipes-extended/memcr/files/0001-RDK-47153-Option-to-set-dump-dir-and-compression-per.patch +++ b/recipes-extended/memcr/files/0001-RDK-47153-Option-to-set-dump-dir-and-compression-per.patch @@ -1,18 +1,18 @@ -From 4f95172d70777357a4b90dd356372ae36be3cb07 Mon Sep 17 00:00:00 2001 +From 39e7c5c9c57fe47f8efe30a809df19011b6c4c10 Mon Sep 17 00:00:00 2001 From: Adrian Muzyka -Date: Wed, 30 Jul 2025 08:26:52 +0200 +Date: Tue, 13 Jan 2026 12:56:55 +0100 Subject: [PATCH] RDK-47153: Option to set dump dir and compression per PID --- - memcr.c | 309 +++++++++++++++++++++++++++++++++++++++++--- + memcr.c | 311 +++++++++++++++++++++++++++++++++++++++++--- memcrclient_proto.h | 23 +++- - 2 files changed, 312 insertions(+), 20 deletions(-) + 2 files changed, 314 insertions(+), 20 deletions(-) diff --git a/memcr.c b/memcr.c -index 264ffa3..c12ef3c 100644 +index 94474b5..08f1c4b 100644 --- a/memcr.c +++ b/memcr.c -@@ -118,7 +118,15 @@ struct vm_area { +@@ -155,7 +155,15 @@ struct vm_area { unsigned long flags; }; @@ -29,7 +29,7 @@ index 264ffa3..c12ef3c 100644 static char *parasite_socket_dir; static int parasite_socket_gid = -1; static int parasite_socket_use_netns; -@@ -150,6 +158,7 @@ static pid_t tids[MAX_THREADS]; +@@ -187,6 +195,7 @@ static pid_t tids[MAX_THREADS]; static int nr_threads; #define SERVICE_MODE_SELECT_TIMEOUT_MS 100 @@ -37,7 +37,7 @@ index 264ffa3..c12ef3c 100644 #define MAX_VMAS (3*4096) static struct vm_area vmas[MAX_VMAS]; -@@ -206,6 +215,7 @@ static struct { +@@ -243,6 +252,7 @@ static struct { int state; int checkpoint_abort; int checkpoint_cmd_sd; @@ -45,7 +45,7 @@ index 264ffa3..c12ef3c 100644 } checkpoint_service_data[CHECKPOINTED_PIDS_LIMIT]; #define SOCKET_INVALID (-1) -@@ -430,7 +440,7 @@ static void parasite_socket_init(struct sockaddr_un *addr, pid_t pid) +@@ -468,7 +478,7 @@ static void parasite_socket_init(struct sockaddr_un *addr, pid_t pid) } } @@ -54,7 +54,7 @@ index 264ffa3..c12ef3c 100644 { char path[PATH_MAX]; -@@ -826,7 +836,15 @@ static int dump_write(int fd, const void *buf, size_t count) +@@ -876,7 +886,15 @@ static int dump_write(int fd, const void *buf, size_t count) return ret; } @@ -71,7 +71,7 @@ index 264ffa3..c12ef3c 100644 { pthread_mutex_lock(&checkpoint_service_data_lock); for (int i=0; isi_pid); +@@ -2430,6 +2464,104 @@ static void sigpipe_handler(int sig, siginfo_t *sip, void *notused) + err("program received SIGPIPE from %d.\n", sip->si_pid); } +static void set_dump_dirs(const char *dirs) @@ -173,14 +173,14 @@ index 264ffa3..c12ef3c 100644 + } + + if (dirs == NULL) { -+ fprintf(stderr, "[!] %s(): Error dump dir cannot be empty!\n", __func__); ++ err("%s(): Error dump dir cannot be empty!\n", __func__); + exit(EXIT_FAILURE); + } + + // Create a mutable copy of dirs + char *dirs_copy = strdup(dirs); + if (!dirs_copy) { -+ fprintf(stderr, "[!] %s(): Memory allocation error!\n", __func__); ++ err("%s(): Memory allocation error!\n", __func__); + exit(EXIT_FAILURE); + } + @@ -190,16 +190,16 @@ index 264ffa3..c12ef3c 100644 + if (realpath(dir, real_dir)) { + struct dump_dir_list *new_dump_dir = malloc(sizeof(struct dump_dir_list)); + if (!new_dump_dir) { -+ fprintf(stderr, "[!] %s(): Memory allocation error!\n", __func__); ++ err("%s(): Memory allocation error!\n", __func__); + exit(EXIT_FAILURE); + } + + new_dump_dir->dir = strdup(real_dir); + if (!new_dump_dir->dir) { -+ fprintf(stderr, "[!] %s(): Memory allocation error!\n", __func__); ++ err("%s(): Memory allocation error!\n", __func__); + exit(EXIT_FAILURE); + } -+ fprintf(stdout, "[+] Allowed dump directory: %s\n", new_dump_dir->dir); ++ msg("Allowed dump directory: %s\n", new_dump_dir->dir); + + new_dump_dir->next = NULL; + @@ -212,7 +212,7 @@ index 264ffa3..c12ef3c 100644 + } + + } else { -+ fprintf(stderr, "[!] %s(): Unable to resolve allowed directory: %s\n", __func__, dir); ++ err("%s(): Unable to resolve allowed directory: %s\n", __func__, dir); + exit(EXIT_FAILURE); + } + @@ -222,13 +222,13 @@ index 264ffa3..c12ef3c 100644 + free(dirs_copy); + + if (!allowed_dump_dirs) { -+ fprintf(stderr, "[!] %s(): No allowed dump directories!\n", __func__); ++ err("%s(): No allowed dump directories!\n", __func__); + exit(EXIT_FAILURE); + } + + // Default dump dir is the first allowed one + dfl_dump_dir = allowed_dump_dirs->dir; -+ fprintf(stdout, "[+] %s(): Allowed dump directories set.\n", __func__); ++ msg("%s(): Allowed dump directories set.\n", __func__); +} + + @@ -237,11 +237,11 @@ index 264ffa3..c12ef3c 100644 + + // Resolve the real path + if (!realpath(dump_dir_path, real_dir_path)) { -+ fprintf(stderr, "[-] %s(): Unable to resolve dump dir path: %s\n", __func__, dump_dir_path); ++ err("%s(): Unable to resolve dump dir path: %s\n", __func__, dump_dir_path); + return 0; + } + -+ fprintf(stdout, "[+] %s(): Real dir path to check: %s\n", __func__, real_dir_path); ++ msg("%s(): Real dir path to check: %s\n", __func__, real_dir_path); + + // iterate over allowed dump dirs and do an exact match + struct dump_dir_list *curr = allowed_dump_dirs; @@ -252,14 +252,14 @@ index 264ffa3..c12ef3c 100644 + curr = curr->next; + } + -+ fprintf(stderr, "[-] %s(): Dump dir path is not allowed: %s\n", __func__, dump_dir_path); ++ err("%s(): Dump dir path is not allowed: %s\n", __func__, dump_dir_path); + return 0; +} + static int read_command(int cd, struct service_command *svc_cmd) { int ret; -@@ -2374,6 +2506,124 @@ static int read_command(int cd, struct service_command *svc_cmd) +@@ -2443,6 +2575,126 @@ static int read_command(int cd, struct service_command *svc_cmd) return ret; } @@ -267,13 +267,13 @@ index 264ffa3..c12ef3c 100644 +{ + /* There must be at least service_command that can be followed by service_checkpoint_options */ + if (len < sizeof(struct service_command)) { -+ fprintf(stderr, "[-] %s(): cmds len to short: %d\n", __func__, (unsigned int)len); ++ err("%s(): cmds len to short: %d\n", __func__, (unsigned int)len); + return -1; + } + + int ret = read_command(cd, svc_cmd); + if (ret < 0) { -+ fprintf(stderr, "%s(): Error reading a command!\n", __func__); ++ err("%s(): Error reading a command!\n", __func__); + return ret; + } + @@ -281,7 +281,7 @@ index 264ffa3..c12ef3c 100644 + + switch (svc_cmd->cmd) { + case MEMCR_CHECKPOINT: { -+ fprintf(stdout, "[+] read MEMCR_CHECKPOINT for %d\n", svc_cmd->pid); ++ msg("read MEMCR_CHECKPOINT for %d\n", svc_cmd->pid); + /* try to read checkpoint options */ + memcr_svc_checkpoint_options option; + while (len >= sizeof(option) && _read(cd, &option, sizeof(option)) > 0 ) { @@ -295,15 +295,15 @@ index 264ffa3..c12ef3c 100644 + (options->dump_dir[pos] != 0) && (++pos < MEMCR_DUMPDIR_LEN_MAX)); + + if (pos >= MEMCR_DUMPDIR_LEN_MAX || options->dump_dir[pos] != 0) { -+ fprintf(stderr, "[-] %s(): dump dir path too long or not terminated with NULL\n", __func__); ++ err("%s(): dump dir path too long or not terminated with NULL\n", __func__); + return -1; + } + + if (is_dump_dir_path_allowed(options->dump_dir)) { + options->is_dump_dir = TRUE; -+ fprintf(stdout, "[+] read dump dir path for this checkpoint: %s\n", options->dump_dir); ++ msg("read dump dir path for this checkpoint: %s\n", options->dump_dir); + } else { -+ fprintf(stderr, "[i] dump dir path incorrect, using default\n"); ++ log("dump dir path incorrect, using default\n"); + } + break; + } @@ -311,7 +311,7 @@ index 264ffa3..c12ef3c 100644 + { + if (len < sizeof(options->compress_alg) || + _read(cd, &options->compress_alg, sizeof(options->compress_alg)) != sizeof(options->compress_alg)) { -+ fprintf(stderr, "[-] %s(): compression algorithm invalid\n", __func__); ++ err("%s(): compression algorithm invalid\n", __func__); + return -1; + } + @@ -322,31 +322,33 @@ index 264ffa3..c12ef3c 100644 + && options->compress_alg != MEMCR_COMPRESS_ZSTD + ) { + /* skip if not support */ -+ fprintf(stderr, "[-] %s(): compression algorithm not supported: %d\n", __func__, options->compress_alg); ++ err("%s(): compression algorithm not supported: %d\n", __func__, options->compress_alg); + break; + } + + options->is_compress_alg = TRUE; ++ #if LOG_LEVEL >= 3 + const char *caToS[] = { + [MEMCR_COMPRESS_NONE] = "none", + [MEMCR_COMPRESS_LZ4] = "lz4", + [MEMCR_COMPRESS_ZSTD] = "zstd"}; -+ fprintf(stdout, "[+] read compress alg for this checkpoint: %s\n", caToS[options->compress_alg]); ++ msg("read compress alg for this checkpoint: %s\n", caToS[options->compress_alg]); ++ #endif + break; + } + default: -+ fprintf(stderr, "[-] %s(): checkpoint option invalid: %d\n", __func__, option); ++ err("%s(): checkpoint option invalid: %d\n", __func__, option); + } + } + break; + } + case MEMCR_RESTORE: { + /* nothing more to read for RESTORE*/ -+ fprintf(stdout, "[+] read MEMCR_RESTORE for %d\n", svc_cmd->pid); ++ msg("read MEMCR_RESTORE for %d\n", svc_cmd->pid); + break; + } + default: -+ fprintf(stderr, "%s(): Error command not expected or invalid: %d!\n", __func__, svc_cmd->cmd); ++ err("%s(): Error command not expected or invalid: %d!\n", __func__, svc_cmd->cmd); + return -1; + } + @@ -363,15 +365,15 @@ index 264ffa3..c12ef3c 100644 + if (checkpoint_service_data[i].options.is_compress_alg) + switch (checkpoint_service_data[i].options.compress_alg) { + case MEMCR_COMPRESS_NONE: -+ fprintf(stdout, "[+] Default compress algorithm set to NONE.\n"); ++ msg("Default compress algorithm set to NONE.\n"); + compress_init(NULL, MAX_VM_REGION_SIZE); + break; + case MEMCR_COMPRESS_LZ4: -+ fprintf(stdout, "[+] Default compress algorithm set to LZ4.\n"); ++ msg("Default compress algorithm set to LZ4.\n"); + compress_init("lz4", MAX_VM_REGION_SIZE); + break; + case MEMCR_COMPRESS_ZSTD: -+ fprintf(stdout, "[+] Default compress algorithm set to ZSTD.\n"); ++ msg("Default compress algorithm set to ZSTD.\n"); + compress_init("zstd", MAX_VM_REGION_SIZE); + break; + } @@ -384,16 +386,16 @@ index 264ffa3..c12ef3c 100644 static int send_response_to_client(int cd, memcr_svc_response resp_code) { struct service_response svc_resp = { .resp_code = resp_code }; -@@ -2505,7 +2755,7 @@ out: +@@ -2574,7 +2826,7 @@ out: if (ret) { - fprintf(stderr, "[%d] %s() Checkpoint failed! Killing the target PID %d...\n", getpid(), __func__, pid); + err("[%d] %s() Checkpoint failed! Killing the target PID %d...\n", getpid(), __func__, pid); kill(pid, SIGKILL); - cleanup_pid(pid); + cleanup_pid(pid, dfl_dump_dir); return ret; } -@@ -2536,7 +2786,7 @@ out: +@@ -2605,7 +2857,7 @@ out: kill(post_checkpoint_cmd.pid, SIGKILL); } unseize_target(); @@ -402,7 +404,7 @@ index 264ffa3..c12ef3c 100644 return ret; } -@@ -2552,6 +2802,7 @@ static int application_worker(pid_t pid, int checkpoint_resp_socket) +@@ -2621,6 +2873,7 @@ static int application_worker(pid_t pid, int checkpoint_resp_socket) ret |= rsd; register_socket_for_checkpoint_service_cmds(checkpoint_resp_socket); @@ -410,7 +412,7 @@ index 264ffa3..c12ef3c 100644 if (0 == ret) { ret |= checkpoint_worker(pid); -@@ -2637,7 +2888,7 @@ static int checkpoint_procedure_service(int checkpointSocket, int cd, int pid, i +@@ -2706,7 +2959,7 @@ static int checkpoint_procedure_service(int checkpointSocket, int cd, int pid, i // unable to read response from worker, kill both kill(pid, SIGKILL); kill(worker_pid, SIGKILL); @@ -419,7 +421,7 @@ index 264ffa3..c12ef3c 100644 send_response_to_client(cd, MEMCR_ERROR_GENERAL); return MEMCR_ERROR_GENERAL; } -@@ -2677,7 +2928,7 @@ static void restore_procedure_service(int cd, struct service_command svc_cmd, in +@@ -2746,7 +2999,7 @@ static void restore_procedure_service(int cd, struct service_command svc_cmd, in // unable to read response from worker, kill both kill(svc_cmd.pid, SIGKILL); kill(worker_pid, SIGKILL); @@ -428,7 +430,7 @@ index 264ffa3..c12ef3c 100644 ret = -1; } -@@ -2781,7 +3032,7 @@ retry: +@@ -2850,7 +3103,7 @@ retry: goto retry; } @@ -437,7 +439,7 @@ index 264ffa3..c12ef3c 100644 { int ret = MEMCR_OK; switch (svc_ctx->svc_cmd.cmd) -@@ -2798,7 +3049,7 @@ static void service_command(struct service_command_ctx *svc_ctx) +@@ -2867,7 +3120,7 @@ static void service_command(struct service_command_ctx *svc_ctx) break; } @@ -445,8 +447,8 @@ index 264ffa3..c12ef3c 100644 + init_pid_checkpoint_data(svc_ctx->svc_cmd.pid, checkpoint_options); ret = service_cmds_push_back(svc_ctx); if (!ret) - fprintf(stdout, "[+] Checkpoint request scheduled...\n"); -@@ -2851,6 +3102,7 @@ static int service_mode(const char *listen_location, const int gid) + msg("Checkpoint request scheduled...\n"); +@@ -2920,6 +3173,7 @@ static int service_mode(const char *listen_location, const int gid) struct timeval tv; int errsv; pthread_t svc_cmd_thread_id; @@ -454,7 +456,7 @@ index 264ffa3..c12ef3c 100644 if (listen_port > 0) csd = setup_listen_tcp_socket(listen_port); -@@ -2891,6 +3143,13 @@ static int service_mode(const char *listen_location, const int gid) +@@ -2960,6 +3214,13 @@ static int service_mode(const char *listen_location, const int gid) cd = accept(csd, NULL, NULL); if (cd >= 0) { struct service_command_ctx svc_ctx = { .cd = cd }; @@ -467,8 +469,8 @@ index 264ffa3..c12ef3c 100644 + ret = read_command(cd, &svc_ctx.svc_cmd); if (ret < 0) { - fprintf(stderr, "%s(): Error reading a command!\n", __func__); -@@ -2898,7 +3157,19 @@ static int service_mode(const char *listen_location, const int gid) + err("%s(): Error reading a command!\n", __func__); +@@ -2967,7 +3228,19 @@ static int service_mode(const char *listen_location, const int gid) continue; } @@ -479,7 +481,7 @@ index 264ffa3..c12ef3c 100644 + size_t cmds_len = svc_ctx.svc_cmd.pid; + ret = read_command_v2(cd, &svc_ctx.svc_cmd, &checkpoint_options, cmds_len); + if (ret < 0) { -+ fprintf(stderr, "%s(): Error reading a command!\n", __func__); ++ err("%s(): Error reading a command!\n", __func__); + close(cd); + continue; + } @@ -489,7 +491,7 @@ index 264ffa3..c12ef3c 100644 continue; } -@@ -2968,7 +3239,7 @@ out: +@@ -3041,7 +3314,7 @@ out: } unseize_target(); @@ -498,7 +500,7 @@ index 264ffa3..c12ef3c 100644 return ret; } -@@ -2993,7 +3264,7 @@ static void usage(const char *name, int status) +@@ -3066,7 +3339,7 @@ static void usage(const char *name, int status) "options:\n" \ " -h --help help\n" \ " -p --pid target process pid\n" \ @@ -507,7 +509,7 @@ index 264ffa3..c12ef3c 100644 " -S --parasite-socket-dir dir where socket to communicate with parasite is created\n" \ " (abstract socket will be used if no path specified)\n" \ " -G --parasite-socket-gid group ID for parasite UNIX domain socket file, valid only for if --parasite-socket-dir provided\n" \ -@@ -3059,7 +3330,7 @@ int main(int argc, char *argv[]) +@@ -3132,7 +3405,7 @@ int main(int argc, char *argv[]) { NULL, 0, NULL, 0 } }; @@ -516,7 +518,7 @@ index 264ffa3..c12ef3c 100644 parasite_socket_dir = NULL; parasite_socket_use_netns = 0; -@@ -3072,7 +3343,7 @@ int main(int argc, char *argv[]) +@@ -3145,7 +3418,7 @@ int main(int argc, char *argv[]) pid = atoi(optarg); break; case 'd': diff --git a/recipes-extended/memcr/files/0001-RDK-54059-retry-ptrace-seize-on-EPERM.patch b/recipes-extended/memcr/files/0001-RDK-54059-retry-ptrace-seize-on-EPERM.patch index 0c206f4e..885e0595 100644 --- a/recipes-extended/memcr/files/0001-RDK-54059-retry-ptrace-seize-on-EPERM.patch +++ b/recipes-extended/memcr/files/0001-RDK-54059-retry-ptrace-seize-on-EPERM.patch @@ -1,6 +1,6 @@ -From ac085fc2825d6b89b23d6f6ea4f0aa84fd439f27 Mon Sep 17 00:00:00 2001 -From: Adrian Muzyka -Date: Wed, 11 Dec 2024 08:44:27 +0000 +From a225beca6ffca0fe455ed9422e26bff5ee36c651 Mon Sep 17 00:00:00 2001 +From: Adrian Muzyka +Date: Tue, 13 Jan 2026 11:50:07 +0100 Subject: [PATCH] RDK-54059: retry ptrace seize on EPERM --- @@ -8,10 +8,10 @@ Subject: [PATCH] RDK-54059: retry ptrace seize on EPERM 1 file changed, 10 insertions(+) diff --git a/memcr.c b/memcr.c -index 3dc4b15..5c38429 100644 +index 526164f..94474b5 100644 --- a/memcr.c +++ b/memcr.c -@@ -212,6 +212,7 @@ static int checkpoint_service_socket = SOCKET_INVALID; +@@ -252,6 +252,7 @@ static int checkpoint_service_socket = SOCKET_INVALID; #define FALSE 0 #define MAX_CLIENT_CONNECTIONS 8 @@ -19,7 +19,7 @@ index 3dc4b15..5c38429 100644 struct service_command_ctx { struct service_command svc_cmd; -@@ -488,13 +489,22 @@ static int seize_pid(pid_t pid) +@@ -534,13 +535,22 @@ static int seize_pid(pid_t pid) int ret; int status; siginfo_t si; @@ -29,18 +29,18 @@ index 3dc4b15..5c38429 100644 ret = ptrace(PTRACE_SEIZE, pid, NULL, 0); if (ret) { if (errno == ESRCH) { - fprintf(stderr, "ptrace(PTRACE_SEIZE) pid %d: %m, ignoring\n", pid); + err("ptrace(PTRACE_SEIZE) pid %d: %m, ignoring\n", pid); return 0; } + else if (errno == EPERM) { + if (cnt++ < PTRACE_SEIZE_RETRY_MAX) { -+ fprintf(stderr, "ptrace(PTRACE_SEIZE) errno %d retry %d pid %d: %m\n", errno, cnt, pid); ++ err("ptrace(PTRACE_SEIZE) errno %d retry %d pid %d: %m\n", errno, cnt, pid); + usleep(100 * 1000); // 100 milliseconds + goto ptrace_seize_retry; + } + } - fprintf(stderr, "ptrace(PTRACE_SEIZE) %d pid %d: %m\n", errno, pid); + err("ptrace(PTRACE_SEIZE) %d pid %d: %m\n", errno, pid); return 1; -- 2.43.0 diff --git a/recipes-extended/memcr/memcr_git.bb b/recipes-extended/memcr/memcr_git.bb index be66fffb..f84a5be8 100644 --- a/recipes-extended/memcr/memcr_git.bb +++ b/recipes-extended/memcr/memcr_git.bb @@ -15,8 +15,8 @@ INSANE_SKIP:${PN} += "ldflags" PV = "1.0.2" PR = "r0" -# Code base from 22.07.2025 -SRCREV = "f46af4008d19cb527d5cede22bf0a3d0c7a8ed02" +# Code base from 14.01.2026 +SRCREV = "82f4d70a58789068453adbdd5ef039f2570d349a" PACKAGE_ARCH = "${MIDDLEWARE_ARCH}" @@ -31,7 +31,8 @@ SYSTEMD_SERVICE:${PN} = "memcr.service" SYSTEMD_AUTO_ENABLE = "enable" do_compile () { - oe_runmake COMPRESS_LZ4=1 COMPRESS_ZSTD=1 CHECKSUM_MD5=1 ENCRYPT=1 + LOG_LEVEL="${@bb.utils.contains('BUILD_VARIANT', 'prod', '1', '3', d)}" + oe_runmake COMPRESS_LZ4=1 COMPRESS_ZSTD=1 CHECKSUM_MD5=1 ENCRYPT=1 LOG_LEVEL=${LOG_LEVEL} } do_install () {