criu: fix missing umount() in error path#2019
Conversation
Summary of ChangesHello @eriksjolund, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request improves the robustness of the CRIU container restoration process by ensuring that critical cleanup operations, specifically unmounting resources, are consistently performed whenever an error occurs. By modifying various error return paths to jump to a common cleanup label, the changes prevent resource leaks and enhance the stability of container lifecycle management under failure conditions. Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
The pull request correctly addresses missing goto out_umount; statements in various error paths within the libcrun_container_restore_linux_criu function. This is a crucial improvement for robust error handling and ensures that necessary cleanup, such as unmounting resources, is performed consistently before exiting the function. This change significantly enhances the reliability and resource management of the CRIU restore process.
| const int open_flags_for_inherit = O_RDONLY; /* Cannot be O_CLOEXEC as it is passed to the child process. */ | ||
| int value = libcrun_find_namespace (def->linux->namespaces[i]->type); | ||
| if (UNLIKELY (value < 0)) | ||
| return crun_make_error (err, 0, "invalid namespace type: `%s`", def->linux->namespaces[i]->type); |
There was a problem hiding this comment.
| { | ||
| inherit_new_net_fd = open (def->linux->namespaces[i]->path, open_flags_for_inherit); | ||
| if (UNLIKELY (inherit_new_net_fd < 0)) | ||
| return crun_make_error (err, errno, "unable to open(): `%s`", def->linux->namespaces[i]->path); |
There was a problem hiding this comment.
Changing the direct return to a goto out_umount ensures that the umount cleanup routine is executed in case of an error opening the network namespace path. This prevents potential resource leaks.
ret = crun_make_error (err, errno, "unable to open(): `%s`", def->linux->namespaces[i]->path);
goto out_umount;|
|
||
| ret = libcriu_wrapper->criu_add_inherit_fd (inherit_new_net_fd, CRIU_EXT_NETNS); | ||
| if (UNLIKELY (ret < 0)) | ||
| return crun_make_error (err, -ret, "CRIU: failed adding fd"); |
| { | ||
| inherit_new_pid_fd = open (def->linux->namespaces[i]->path, open_flags_for_inherit); | ||
| if (UNLIKELY (inherit_new_pid_fd < 0)) | ||
| return crun_make_error (err, errno, "unable to open(): `%s`", def->linux->namespaces[i]->path); |
|
|
||
| ret = libcriu_wrapper->criu_add_inherit_fd (inherit_new_pid_fd, CRIU_EXT_PIDNS); | ||
| if (UNLIKELY (ret < 0)) | ||
| return crun_make_error (err, -ret, "CRIU: failed adding fd"); |
|
|
||
| ret = libcriu_wrapper->criu_join_ns_add ("uts", def->linux->namespaces[i]->path, NULL); | ||
| if (UNLIKELY (ret < 0)) | ||
| return crun_make_error (err, -ret, "CRIU: failed adding external namespace `%s`", def->linux->namespaces[i]->path); |
| if (libcriu_wrapper->criu_join_ns_add == NULL) | ||
| return crun_make_error (err, 0, "shared ipc namespace restore is supported in CRIU >= 3.16.1"); | ||
| { | ||
| ret = crun_make_error (err, 0, "shared ipc namespace restore is supported in CRIU >= 3.16.1"); | ||
| goto out_umount; | ||
| } | ||
|
|
||
| ret = libcriu_wrapper->criu_join_ns_add ("ipc", def->linux->namespaces[i]->path, NULL); | ||
| if (UNLIKELY (ret < 0)) | ||
| return crun_make_error (err, -ret, "CRIU: failed adding external namespace `%s`", def->linux->namespaces[i]->path); | ||
| { | ||
| ret = crun_make_error (err, -ret, "CRIU: failed adding external namespace `%s`", def->linux->namespaces[i]->path); | ||
| goto out_umount; | ||
| } | ||
| } | ||
|
|
||
| if (value == CLONE_NEWUTS && def->linux->namespaces[i]->path != NULL) | ||
| { | ||
| if (libcriu_wrapper->criu_join_ns_add == NULL) | ||
| return crun_make_error (err, 0, "shared uts namespace restore is supported in CRIU >= 3.16.1"); | ||
| { | ||
| ret = crun_make_error (err, 0, "shared uts namespace restore is supported in CRIU >= 3.16.1"); | ||
| goto out_umount; | ||
| } | ||
|
|
||
| ret = libcriu_wrapper->criu_join_ns_add ("uts", def->linux->namespaces[i]->path, NULL); | ||
| if (UNLIKELY (ret < 0)) | ||
| return crun_make_error (err, -ret, "CRIU: failed adding external namespace `%s`", def->linux->namespaces[i]->path); | ||
| { | ||
| ret = crun_make_error (err, -ret, "CRIU: failed adding external namespace `%s`", def->linux->namespaces[i]->path); | ||
| goto out_umount; | ||
| } | ||
| } | ||
| # endif | ||
| } | ||
|
|
||
| /* Set up CRIU config file */ | ||
| if (UNLIKELY (handle_criu_config_file (container, err))) | ||
| return -1; |
| { | ||
| ret = libcriu_wrapper->criu_add_cg_root (NULL, status->cgroup_path); | ||
| if (UNLIKELY (ret != 0)) | ||
| return crun_make_error (err, 0, "error setting CRIU cgroup root to `%s`", status->cgroup_path); |
| { | ||
| ret = libcriu_wrapper->criu_set_network_lock (cr_options->network_lock_method); | ||
| if (UNLIKELY (ret < 0)) | ||
| return crun_make_error (err, 0, "CRIU: failed setting network lock"); |
| libcriu_wrapper->criu_set_log_level (4); | ||
| ret = libcriu_wrapper->criu_set_log_file (CRIU_RESTORE_LOG_FILE); | ||
| if (UNLIKELY (ret < 0)) | ||
| return crun_make_error (err, -ret, "error setting CRIU log file to `%s`", CRIU_RESTORE_LOG_FILE); |
|
Okay, |
|
That's great to hear, @eriksjolund! I'm glad the summary was helpful. I'll be proceeding with a more detailed review of the changes shortly. Thanks for removing the draft status! |
|
TMT tests failed. @containers/packit-build please check. |
|
I guess the PR is not correct because there are errors in CI. Copy-paste from |
do we just need to store errno before calling rmdir? int saved_errno = errno;
rmdir (root);
return crun_make_error (err, saved_errno, "error unmounting restore directory `%s`", root); |
02fdb36 to
2d202bf
Compare
Yes, I think so. I pushed a new version where I tried to fix #2020 at the same time. I just want to see what happens with the CI tests. |
Fix possible error leak. Closes: containers#2020 Signed-off-by: Erik Sjölund <erik.sjolund@gmail.com>
2d202bf to
11701f4
Compare
|
@eriksjolund Thank you for fixing this! |
Fix missing
umount()in error path.Fix possible error leak.
Closes: #2020