core: donate the fdset to do_reexecute() to avoid a double free

do_reexecute() freed the FDSet on the switch-root/soft-reboot fallback
but the caller's copy stayed live, so main() freed it again if every
fallback exec then failed. Donate the fdset instead: pass it with
TAKE_PTR() and take ownership via a _cleanup_ local, freeing it exactly
once on every exit path.

Follow-up for 3c7878f94b
This commit is contained in:
Luca Boccassi
2026-07-01 22:46:45 +01:00
parent 0a869d3882
commit b64a44707d
+5 -2
View File
@@ -2123,7 +2123,7 @@ static int do_reexecute(
char* argv[],
const struct rlimit *saved_rlimit_nofile,
const struct rlimit *saved_rlimit_memlock,
FDSet *fds,
FDSet *_fds, /* donated */
const char *switch_root_dir,
const char *switch_root_init,
uint64_t saved_capability_ambient_set,
@@ -2139,6 +2139,9 @@ static int do_reexecute(
assert(saved_rlimit_memlock);
assert(ret_error_message);
/* The fdset is donated to us, take ownership so it is freed on all exit paths. */
_cleanup_fdset_free_ FDSet *fds = TAKE_PTR(_fds);
/* Close and disarm the watchdog, so that the new instance can reinitialize it, but the machine
* doesn't get rebooted while we do that. */
watchdog_close(/* disarm= */ true);
@@ -3848,7 +3851,7 @@ finish:
argc, argv,
&saved_rlimit_nofile,
&saved_rlimit_memlock,
fds,
TAKE_PTR(fds),
switch_root_dir,
switch_root_init,
saved_ambient_set,