[PATCH 3/3] qemu_namespace: Don't leak mknod items that are being skipped over
Laine Stump
laine at redhat.com
Fri Sep 4 15:29:54 UTC 2020
On 9/4/20 4:24 AM, Michal Privoznik wrote:
> When building and populating domain NS a couple of functions is
> called
s/is/are/
> that append paths to a string list. This string list is
> then inspected, one item at the time by
> qemuNamespacePrepareOneItem() which gathers all the info for
> given path (stat buffer, possible link target, ACLs, SELinux
> label) using qemuNamespaceMknodItemInit(). If the path needs to
> be created in the domain's private /dev then it's added onto this
> qemuNamespaceMknodData list which is freed later in the process.
> But, if the path does not need to be created in the domain's
> private /dev, then the memory allocated by
> qemuNamespaceMknodItemInit() is not freed anywhere leading to a
> leak.
>
> Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
> ---
>
> Honestly, I think this patch looks ugly. Ideas are welcome.
>
> src/qemu/qemu_namespace.c | 42 +++++++++++++++++++++++++++++----------
> 1 file changed, 31 insertions(+), 11 deletions(-)
>
> diff --git a/src/qemu/qemu_namespace.c b/src/qemu/qemu_namespace.c
> index 87f4fd8d58..917e140f6a 100644
> --- a/src/qemu/qemu_namespace.c
> +++ b/src/qemu/qemu_namespace.c
> @@ -1166,22 +1166,29 @@ qemuNamespacePrepareOneItem(qemuNamespaceMknodDataPtr data,
> size_t ndevMountsPath)
> {
> long ttl = sysconf(_SC_SYMLOOP_MAX);
> - const char *next = file;
> + g_autofree char *next = g_strdup(file);
> size_t i;
>
> while (1) {
> qemuNamespaceMknodItem item = { 0 };
> + bool added = false;
> + bool isLink;
> int rc;
>
> rc = qemuNamespaceMknodItemInit(&item, cfg, vm, next);
> - if (rc == -2) {
> - /* @file doesn't exist. We can break here. */
> - break;
> - } else if (rc < 0) {
> + if (rc < 0) {
> + qemuNamespaceMknodItemClear(&item);
> +
> + if (rc == -2) {
> + /* @file doesn't exist. We can break here. */
> + break;
> + }
> /* Some other (critical) error. */
> return -1;
> }
>
> + isLink = S_ISLNK(item.sb.st_mode);
> +
> if (STRPREFIX(next, QEMU_DEVPREFIX)) {
> for (i = 0; i < ndevMountsPath; i++) {
> if (STREQ(devMountsPath[i], "/dev"))
> @@ -1190,22 +1197,35 @@ qemuNamespacePrepareOneItem(qemuNamespaceMknodDataPtr data,
> break;
> }
>
> - if (i == ndevMountsPath &&
> - VIR_APPEND_ELEMENT_COPY(data->items, data->nitems, item) < 0)
> - return -1;
> + if (i == ndevMountsPath) {
> + if (VIR_APPEND_ELEMENT_COPY(data->items, data->nitems, item) < 0) {
> + qemuNamespaceMknodItemClear(&item);
> + return -1;
> + }
> + added = true;
> + }
> }
>
> - if (!S_ISLNK(item.sb.st_mode))
> + if (!isLink) {
> + if (!added)
> + qemuNamespaceMknodItemClear(&item);
> break;
> + }
>
> if (ttl-- == 0) {
> + if (!added)
> + qemuNamespaceMknodItemClear(&item);
> virReportSystemError(ELOOP,
> _("Too many levels of symbolic links: %s"),
> - next);
> + file);
> return -1;
> }
>
> - next = item.target;
> + g_free(next);
I recall once being reprimanded for calling g_free on a g_autofree()
pointer (by someone who said that *they* had been reprimanded for same).
I will say
Reviewed-by: Laine Stump <laine at redhat.com>
but don't want to later be fingered as "the person" who allowed this
into the code, so I guess maybe look for a way around that (or a signoff
from whoever it was that made the initial "it's bad to manually free a
g_autofree pointer" statement). (I don't think it's particularly ugly
BTW. Sure, it could probably be done in a cleaner manner somehow, but
sometimes things are just messy; you can move the mess, but you can't
eliminate it)
> + next = g_strdup(item.target);
> +
> + if (!added)
> + qemuNamespaceMknodItemClear(&item);
> }
>
> return 0;
More information about the libvir-list
mailing list