]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libmount: disable libblkid probing for non-root users
authorKarel Zak <kzak@redhat.com>
Tue, 2 Jun 2026 10:27:15 +0000 (12:27 +0200)
committerKarel Zak <kzak@redhat.com>
Tue, 9 Jun 2026 08:40:39 +0000 (10:40 +0200)
Add noprobe flag to struct libmnt_cache that disables low-level
device probing via libblkid. When the mount context is restricted
(non-root user), the flag is set automatically on cache creation
and on externally provided caches.

With noprobe enabled:
 - read_from_blkid() is skipped (device I/O blocked)
 - mnt_resolve_tag() uses blkid_evaluate_tag2() with
   BLKID_EVALUATE_NOPROBE, so tags are resolved only via
   udev /dev/disk/by-* symlinks without device scanning

This minimizes the libblkid attack surface for suid mount/umount
binaries.

Signed-off-by: Karel Zak <kzak@redhat.com>
libmount/src/cache.c
libmount/src/context.c
libmount/src/mountP.h

index 28af83740b1cc1f4ec7f2f8fa4144cdf969be6b4..e02c653f51758480ebb09436b23048b5f4ea3351 100644 (file)
@@ -63,6 +63,7 @@ struct libmnt_cache {
        size_t                  nallocs;
        int                     refcount;
        int                     probe_sb_extra; /* extra BLKID_SUBLKS_* flags */
+       bool                    noprobe;        /* disable libblkid device probing */
 
        /* blkid_evaluate_tag() works in two ways:
         *
@@ -214,6 +215,12 @@ int mnt_cache_set_sbprobe(struct libmnt_cache *cache, int flags)
        return 0;
 }
 
+void mnt_cache_enable_noprobe(struct libmnt_cache *cache, int enable)
+{
+       if (cache)
+               cache->noprobe = !!enable;
+}
+
 /* note that the @key could be the same pointer as @value */
 static int cache_add_entry(struct libmnt_cache *cache, char *key,
                                        char *value, int flag)
@@ -379,6 +386,11 @@ static int read_from_blkid(struct libmnt_cache *cache, const char *devname)
        assert(cache);
        assert(devname);
 
+       if (cache->noprobe) {
+               DBG_OBJ(CACHE, cache, ul_debug("%s: skip blkid probe (noprobe)", devname));
+               return 1;
+       }
+
        DBG_OBJ(CACHE, cache, ul_debug("%s: reading from blkid", devname));
 
        pr =  blkid_new_probe_from_filename(devname);
@@ -801,9 +813,6 @@ char *mnt_resolve_tag(const char *token, const char *value,
 {
        char *p = NULL;
 
-       /*DBG_OBJ(CACHE, cache, ul_debug("resolving tag token=%s value=%s",
-                               token, value));*/
-
        if (!token || !value)
                return NULL;
 
@@ -811,14 +820,20 @@ char *mnt_resolve_tag(const char *token, const char *value,
                p = (char *) cache_find_tag(cache, token, value);
 
        if (!p) {
+               DBG_OBJ(CACHE, cache, ul_debug("evaluating (by blkid) tag %s=%s", token, value));
+
                /* returns newly allocated string */
-               p = blkid_evaluate_tag(token, value, cache ? &cache->bc : NULL);
+               p = blkid_evaluate_tag2(token, value,
+                               cache ? &cache->bc : NULL,
+                               cache && cache->noprobe ? BLKID_EVALUATE_NOPROBE : 0);
 
                if (p && cache &&
                    cache_add_tag(cache, token, value, p, 0))
                                goto error;
        }
 
+       DBG_OBJ(CACHE, cache, ul_debug("resolve tag %s=%s -> %s",
+                               token, value, p ? p : "NOT FOUND"));
        return p;
 error:
        free(p);
index f4b012847a7381f5bb09a5645637e421e3a08d67..dccf8bdd5056693348d97c3039dbaee50f01fbb9 100644 (file)
@@ -1670,6 +1670,9 @@ int mnt_context_set_cache(struct libmnt_context *cxt, struct libmnt_cache *cache
        mnt_ref_cache(cache);                   /* new */
        mnt_unref_cache(cxt->cache);            /* old */
 
+       if (cache && mnt_context_is_restricted(cxt))
+               mnt_cache_enable_noprobe(cache, 1);
+
        cxt->cache = cache;
 
        if (cxt->mountinfo)
index 2c5512c807a4cb6419aba8d2e10063c0b568a253..094c9a928804d15422e22f5f6da005b57b63ec37 100644 (file)
@@ -696,6 +696,8 @@ extern int mnt_context_prepare_update(struct libmnt_context *cxt);
 extern int mnt_context_merge_mflags(struct libmnt_context *cxt);
 extern int mnt_context_update_tabs(struct libmnt_context *cxt);
 
+extern void mnt_cache_enable_noprobe(struct libmnt_cache *cache, int enable);
+
 extern int mnt_context_umount_setopt(struct libmnt_context *cxt, int c, char *arg);
 extern int mnt_context_mount_setopt(struct libmnt_context *cxt, int c, char *arg);