[Pkg-utopia-maintainers] Bug#1042001: libblockdev3 leaks empty directories in bd_fs_get_free_space on btrfs partition

Andre Naujoks nautsch2 at gmail.com
Tue Jul 25 15:16:42 BST 2023


Package: libblockdev3
Version: 3.0.2-1
Severity: normal
Tags: upstream

Dear Maintainer,

libblockdev seems to leak empty temporary directories, when the function bd_fs_get_free_space is called (even unsuccessfully) on a btrfs partition as it calls fs_mount internally, which then either fails and exhibits the behavior OR succeeds and btrfs_get_info leaks the directory.
I am relatively sure that this is not limited to btrfs, but that is what I have here.
I noticed this while steam was running and my /tmp directory was suddenly overflowing with hundreds of blockdev.XXXXXX directories. I don't know what steam does there or if it is in fact steam itself, proton or something else, but libblockdev should not leak the directories.

This little piece of code demonstrates the problem. It does not matter, if the device exists or not. It just cannot be mounted already.
Run it and an empty blockdev.XXXXXX dir remains in /tmp

#include <blockdev/blockdev.h>
#include <blockdev/fs/generic.h>
#include <stdio.h>

int main()
{
         GError *err = NULL;
         BDPluginSpec fs_plugin = {BD_PLUGIN_FS, NULL};
         BDPluginSpec *plugins[] = {&fs_plugin, NULL};
         if (!bd_init(plugins, NULL, &err)) {
                 fprintf(stdout, "failed to init lib: %s\n", err->message);
         }
         err = NULL;
         guint64 space = bd_fs_get_free_space("/dev/sda1", "btrfs", &err);
         if (space == 0) {
                 fprintf(stdout, "failed to get fs size: %s\n", err->message);
         } else {
         	fprintf(stdout, "%d\n", space);
	}

         return 0;
}

As far as I can see, the following patch should remedy at least the unsuccessul path, where the device cannot be mounted. However, I have not tested this!!

diff --git a/src/plugins/fs/generic.c b/src/plugins/fs/generic.c
index 21032b8a..843de8b1 100644
--- a/src/plugins/fs/generic.c
+++ b/src/plugins/fs/generic.c
@@ -650,6 +650,7 @@ static gchar* fs_mount (const gchar *device, gchar *fstype, gboolean read_only,
              if (!ret) {
                  g_propagate_prefixed_error (error, l_error, "Failed to mount '%s': ", device);
                  g_free (mountpoint);
+                g_rmdir (tempdir);
                  return NULL;
              } else
                  *unmount = TRUE;

I am not sure how to handle the successful calls to fs_mount from the other functions in that file. Do we really need to delete the dir downstream in all the calling functions? Seems strange to me, but I don't see a different solution right now.

Ps:
fs_mount() might also leak a little memory in case it creates the tmp mount, but I am not certain enough about the behavior of glib2 here (i.e. valgrind does not immediately see this as a definite leak). reassigning 'mountpoint' with the result of g_mkdtemp() looks as if the original memory, returned by g_build_path() is lost? The glib documentation at least suggests a leak here.

from line 642ff:
             mountpoint = g_build_path (G_DIR_SEPARATOR_S, g_get_tmp_dir (), "blockdev.XXXXXX", NULL);
             mountpoint = g_mkdtemp (mountpoint);

Regards
   Andre


-- System Information:
Debian Release: trixie/sid
   APT prefers unstable-debug
   APT policy: (500, 'unstable-debug'), (500, 'unstable')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 6.3.0-2-amd64 (SMP w/12 CPU threads; PREEMPT)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8), LANGUAGE=en_US
Shell: /bin/sh linked to /usr/bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled

Versions of packages libblockdev3 depends on:
ii  libblockdev-utils3  3.0.2-1
ii  libc6               2.37-6
ii  libglib2.0-0        2.76.4-3

libblockdev3 recommends no packages.

libblockdev3 suggests no packages.

-- no debconf information



More information about the Pkg-utopia-maintainers mailing list