Skip to content

Fix potential use-after-free and double-free#4044

Merged
clumens merged 1 commit intoClusterLabs:mainfrom
dyupina:main__fix_use_after_free_and_double_free
Feb 5, 2026
Merged

Fix potential use-after-free and double-free#4044
clumens merged 1 commit intoClusterLabs:mainfrom
dyupina:main__fix_use_after_free_and_double_free

Conversation

@dyupina
Copy link

@dyupina dyupina commented Feb 2, 2026

In pcmk__output_new() -> pcmk__bare_output_new(), when the condition if ((*out)->init(*out) == false) is met, pcmk__output_free(*out) is called and the function returns with rc = ENOMEM.
The *_init() functions return false when memory allocation via calloc() fails - an unlikely but possible scenario.

Since rc != pcmk_rc_ok, execution jumps to the done label after pcmk__output_new() returns.

The codebase contains numerous functions that follow the same cleanup pattern: they check if (out != NULL) at the done label before invoking out->finish() and pcmk__output_free(out). Because *out is freed but not set to NULL on initialization failure, this check evaluates to true.
This leads to:

  • Use-after-free: dereferencing the dangling pointer when calling out->finish(...);
  • Double-free: attempting to free the same memory again via pcmk__output_free(out).

To resolve this, set *out = NULL immediately after calling pcmk__output_free(*out) within pcmk__bare_output_new(). This ensures that if (out != NULL) check at the done label is false, thereby preventing both the use-after-free and the double-free.

@knet-jenkins
Copy link

knet-jenkins bot commented Feb 2, 2026

Can one of the project admins check and authorise this run please: https://ci.kronosnet.org/job/pacemaker/job/pacemaker-pipeline/job/PR-4044/1/input

In pcmk__output_new() -> pcmk__bare_output_new(), when the condition
if ((*out)->init(*out) == false) is met, pcmk__output_free(*out) is
called and the function returns with rc = ENOMEM.
The *_init() functions return false when memory allocation via calloc()
fails - an unlikely but possible scenario.

Since rc != pcmk_rc_ok, execution jumps to the done label after
pcmk__output_new() returns.

The codebase contains numerous functions that follow the same
cleanup pattern: they check if (out != NULL) at the done label
before invoking out->finish() and pcmk__output_free(out).
Because *out is freed but not set to NULL on initialization failure,
this check evaluates to true.
This leads to:
- Use-after-free: dereferencing the dangling pointer when
calling out->finish(...);
- Double-free: attempting to free the same memory again
via pcmk__output_free(out).

To resolve this, use g_clear_pointer(out, pcmk__output_free)
within pcmk__bare_output_new(). This ensures that
if (out != NULL) check at the done label is false, thereby
preventing both the use-after-free and the double-free.

Also update the copyright date.

Signed-off-by: Alexandra Diupina <dyupina99999@gmail.com>
@dyupina dyupina force-pushed the main__fix_use_after_free_and_double_free branch from bf8dc11 to 82ea8b9 Compare February 4, 2026 13:54
@knet-jenkins
Copy link

knet-jenkins bot commented Feb 4, 2026

Can one of the project admins check and authorise this run please: https://ci.kronosnet.org/job/pacemaker/job/pacemaker-pipeline/job/PR-4044/2/input

@clumens clumens merged commit fa06288 into ClusterLabs:main Feb 5, 2026
1 check passed
@clumens
Copy link
Contributor

clumens commented Feb 5, 2026

There's one more spot that could use g_clear_pointer - in pcmk__xml_output_finish. I'll just submit another PR real quick to take care of that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants