From 15009a6bf90a684240511135603138483236d2d4 Mon Sep 17 00:00:00 2001 From: BhuvanB404 Date: Sat, 3 Jan 2026 19:34:41 +0530 Subject: [PATCH 1/2] files: add og_fd[N] syntax for --inherit-fd option Add support for og_fd[N] syntax in --inherit-fd option to allow referencing file descriptors by their original fd number in the dumped process. This eliminates the need to manually extract pipe inodes or file paths using stat commands. The implementation stores og_fd[N] as literal strings in inh_id and parses them on-demand during matching. This keeps the inherit_fd structure unchanged and maintains backward compatibility. Example usage: criu restore -D img --inherit-fd 'fd[5]:og_fd[3]' 5>output.txt This redirects original fd 3 to fd 5 in the restored process. Fixes: #2837 Signed-off-by: BhuvanB404 --- criu/crtools.c | 1 + criu/files.c | 119 ++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 114 insertions(+), 6 deletions(-) diff --git a/criu/crtools.c b/criu/crtools.c index 4dc55a065..03eeab5e4 100644 --- a/criu/crtools.c +++ b/criu/crtools.c @@ -508,6 +508,7 @@ usage: " file[mnt_id:inode]\n" " /memfd:name\n" " path/to/file\n" + " og_fd[N] (match fd by its original fd number)\n" " --empty-ns net Create a namespace, but don't restore its properties\n" " (assuming it will be restored by action scripts)\n" " -J|--join-ns NS:{PID|NS_FILE}[,OPTIONS]\n" diff --git a/criu/files.c b/criu/files.c index af4b8aeac..1a9e69d96 100644 --- a/criu/files.c +++ b/criu/files.c @@ -1539,8 +1539,8 @@ int shared_fdt_prepare(struct pstree_item *item) struct inherit_fd { struct list_head inh_list; - char *inh_id; /* file identifier */ - int inh_fd; /* criu's descriptor to inherit */ + char *inh_id; /* file identifier (or "og_fd[N]" ) */ + int inh_fd; /* criu's descriptor to inherit */ int inh_fd_id; }; @@ -1555,6 +1555,9 @@ int inherit_fd_parse(char *optarg) /* * Parse the argument. + * Formats supported: + * fd[N]:identifier + * fd[N]:og_fd[M] */ if (!strncmp(optarg, "fd", 2)) cp = &optarg[2]; @@ -1585,6 +1588,20 @@ int inherit_fd_parse(char *optarg) return 0; } + /* + * Check for og_fd[M] in cmd argument + */ + if (!strncmp(cp, "og_fd[", 8)) { + int og_fd = -1; + + n = sscanf(cp, "og_fd[%d]", &og_fd); + if (n != 1 || og_fd < 0) { + pr_err("Invalid og_fd syntax in inherit fd argument: %s\n", optarg); + return -1; + } + + } + return inherit_fd_add(fd, cp); } @@ -1613,6 +1630,12 @@ int inherit_fd_add(int fd, char *key) inh->inh_fd = fd; list_add_tail(&inh->inh_list, &opts.inherit_fds); + + if (!strncmp(key, "og_fd[", 8)) { + int og_fd = -1; + sscanf(key, "og_fd[%d]", &og_fd); + pr_info("Inherit fd %d will replace original fd %d\n", fd, og_fd); + } return 0; } @@ -1625,7 +1648,16 @@ void inherit_fd_log(void) struct inherit_fd *inh; list_for_each_entry(inh, &opts.inherit_fds, inh_list) { - pr_info("File %s will be restored from inherit fd %d\n", inh->inh_id, inh->inh_fd); + + if (!strncmp(inh->inh_id, "og_fd[", 8)) { + int og_fd = -1; + sscanf(inh->inh_id, "og_fd[%d]", &og_fd); + pr_info("Original fd %d will be restored from inherit fd %d\n", + og_fd, inh->inh_fd); + } else { + pr_info("File %s will be restored from inherit fd %d\n", + inh->inh_id, inh->inh_fd); + } } } @@ -1653,6 +1685,9 @@ int inherit_fd_lookup_id(char *id) ret = -1; list_for_each_entry(inh, &opts.inherit_fds, inh_list) { + + if (!strncmp(inh->inh_id, "og_fd[", 8)) + continue; if (!strcmp(inh->inh_id, id)) { ret = fdstore_get(inh->inh_fd_id); pr_debug("Found id %s (fd %d) in inherit fd list\n", id, ret); @@ -1662,11 +1697,77 @@ int inherit_fd_lookup_id(char *id) return ret; } -bool inherited_fd(struct file_desc *d, int *fd_p) +/* + * Look up the inherit fd list by original fd number. + * --inherit-fd 'fd[N]:og_fd[M]' . + * Pases he FD number from the "og_fd[N]" string in inh_id back to fd[N] + * + * This parses and passes the file descipters from memory in fdinfo-*.img to fd[N] + * during restore , making the file descripter restoration flexible and automatic. + */ + +static int inherit_fd_lookup_by_og_fd(int og_fd) { - char buf[PATH_MAX], *id_str; + int ret; + struct inherit_fd *inher; + + ret = -1; + list_for_each_entry(inher, &opts.inherit_fds, inh_list) { + int stored_og_fd; + + if (strncmp(inher->inh_id, "og_fd[", 8) != 0) + continue; + + + if (sscanf(inher->inh_id, "og_fd[%d]", &stored_og_fd) != 1) + continue; + + if (stored_og_fd == og_fd) { + ret = fdstore_get(inher->inh_fd_id); + pr_debug("Found og_fd %d (fd %d) in inherit fd list\n", + og_fd, ret); + break; + } + } + return ret; +} + +/* + * Check if any file in file_desc's list matches an og_fd inherit entry. + * Returns the inherited fd if found, else -1 . + * Prevents overwriting file descripters allocated for preserving during restore. + */ +static int inherit_fd_check_og_fd(struct file_desc *d) +{ + struct fdinfo_list_entry *file; int i_fd; + list_for_each_entry(file, &d->fd_info_head, desc_list) { + i_fd = inherit_fd_lookup_by_og_fd(file->fe->fd); + if (i_fd >= 0) { + pr_debug("File descipter id %#x has file with og_fd %d matching inherit\n", + d->id, file->fe->fd); + return i_fd; + } + } + return -1; +} + +/* Check for og_fd , by iteratiing though file desciptiers +* if found goto found else use normal id matching +* if --inherit-fd 'fd[N]:og_fd[M]' entry. +* else fd[N] identifier matching +*/ +bool inherited_fd(struct file_desc *d, int *fd_p) +{ + char buf[PATH_MAX], *id_str = NULL; + int i_fd; + + i_fd = inherit_fd_check_og_fd(d); + if (i_fd >= 0) + goto found; + + if (!d->ops->name) return false; @@ -1675,13 +1776,19 @@ bool inherited_fd(struct file_desc *d, int *fd_p) if (i_fd < 0) return false; +found: if (fd_p == NULL) return true; *fd_p = i_fd; + + /* Get the name string if we don't have it yet */ + if (id_str == NULL && d->ops->name) + id_str = d->ops->name(d, buf, sizeof(buf)); + pr_info("File %s will be restored from fd %d dumped " "from inherit fd %d\n", - id_str, *fd_p, i_fd); + id_str ? id_str : "", *fd_p, i_fd); return true; } From 5544035077247d76c16c0d6413c23853e4025003 Mon Sep 17 00:00:00 2001 From: BhuvanB404 Date: Sat, 10 Jan 2026 02:10:30 +0530 Subject: [PATCH 2/2] files: fix code quality issues from review - Fixed strncmp length from 8 to 6 for og_fd prefix comparison - Fixed spelling errors in comments (desciptiers->descriptors, iteratiing->iterating, descipter->descriptor) - Removed unused og_fd validation block that had no effect - Improved comment clarity and grammar Signed-off-by: BhuvanB404 --- criu/files.c | 36 +++++++++--------------------------- 1 file changed, 9 insertions(+), 27 deletions(-) diff --git a/criu/files.c b/criu/files.c index 1a9e69d96..0e993fca3 100644 --- a/criu/files.c +++ b/criu/files.c @@ -1588,20 +1588,6 @@ int inherit_fd_parse(char *optarg) return 0; } - /* - * Check for og_fd[M] in cmd argument - */ - if (!strncmp(cp, "og_fd[", 8)) { - int og_fd = -1; - - n = sscanf(cp, "og_fd[%d]", &og_fd); - if (n != 1 || og_fd < 0) { - pr_err("Invalid og_fd syntax in inherit fd argument: %s\n", optarg); - return -1; - } - - } - return inherit_fd_add(fd, cp); } @@ -1649,7 +1635,7 @@ void inherit_fd_log(void) list_for_each_entry(inh, &opts.inherit_fds, inh_list) { - if (!strncmp(inh->inh_id, "og_fd[", 8)) { + if (!strncmp(inh->inh_id, "og_fd[", 6)) { int og_fd = -1; sscanf(inh->inh_id, "og_fd[%d]", &og_fd); pr_info("Original fd %d will be restored from inherit fd %d\n", @@ -1686,7 +1672,7 @@ int inherit_fd_lookup_id(char *id) ret = -1; list_for_each_entry(inh, &opts.inherit_fds, inh_list) { - if (!strncmp(inh->inh_id, "og_fd[", 8)) + if (!strncmp(inh->inh_id, "og_fd[", 6)) continue; if (!strcmp(inh->inh_id, id)) { ret = fdstore_get(inh->inh_fd_id); @@ -1699,11 +1685,8 @@ int inherit_fd_lookup_id(char *id) /* * Look up the inherit fd list by original fd number. - * --inherit-fd 'fd[N]:og_fd[M]' . - * Pases he FD number from the "og_fd[N]" string in inh_id back to fd[N] - * - * This parses and passes the file descipters from memory in fdinfo-*.img to fd[N] - * during restore , making the file descripter restoration flexible and automatic. + * For --inherit-fd 'fd[N]:og_fd[M]', parse the og_fd number from inh_id + * and return the inherited fd that will replace it during restore. */ static int inherit_fd_lookup_by_og_fd(int og_fd) @@ -1715,7 +1698,7 @@ static int inherit_fd_lookup_by_og_fd(int og_fd) list_for_each_entry(inher, &opts.inherit_fds, inh_list) { int stored_og_fd; - if (strncmp(inher->inh_id, "og_fd[", 8) != 0) + if (strncmp(inher->inh_id, "og_fd[", 6) != 0) continue; @@ -1734,8 +1717,7 @@ static int inherit_fd_lookup_by_og_fd(int og_fd) /* * Check if any file in file_desc's list matches an og_fd inherit entry. - * Returns the inherited fd if found, else -1 . - * Prevents overwriting file descripters allocated for preserving during restore. + * Returns the inherited fd if found, else -1. */ static int inherit_fd_check_og_fd(struct file_desc *d) { @@ -1745,7 +1727,7 @@ static int inherit_fd_check_og_fd(struct file_desc *d) list_for_each_entry(file, &d->fd_info_head, desc_list) { i_fd = inherit_fd_lookup_by_og_fd(file->fe->fd); if (i_fd >= 0) { - pr_debug("File descipter id %#x has file with og_fd %d matching inherit\n", + pr_debug("File descriptor id %#x has file with og_fd %d matching inherit\n", d->id, file->fe->fd); return i_fd; } @@ -1753,9 +1735,9 @@ static int inherit_fd_check_og_fd(struct file_desc *d) return -1; } -/* Check for og_fd , by iteratiing though file desciptiers +/* Check for og_fd by iterating through file descriptors * if found goto found else use normal id matching -* if --inherit-fd 'fd[N]:og_fd[M]' entry. +* if --inherit-fd 'fd[N]:og_fd[M]' entry. * else fd[N] identifier matching */ bool inherited_fd(struct file_desc *d, int *fd_p)