]> xenbits.xensource.com Git - libvirt.git/commitdiff
conf: add idmap element to filesystem
authorJán Tomko <jtomko@redhat.com>
Wed, 16 Aug 2023 12:44:01 +0000 (14:44 +0200)
committerJán Tomko <jtomko@redhat.com>
Thu, 14 Dec 2023 16:10:22 +0000 (17:10 +0100)
Allow the user to manually tweak the ID mapping that will allow
virtiofsd to run unprivileged.

Signed-off-by: Ján Tomko <jtomko@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
docs/formatdomain.rst
src/conf/domain_conf.c
src/conf/domain_conf.h
src/conf/schemas/domaincommon.rng
tests/qemuxml2argvdata/vhost-user-fs-fd-memory.xml

index 310d2bc4275b76b86e0ce26b66daf6a7f946af94..96e03a3807cca83adbc9da42689950740db455b8 100644 (file)
@@ -3548,6 +3548,10 @@ A directory on the host that can be accessed directly from the guest.
          </binary>
          <source dir='/path'/>
          <target dir='mount_tag'/>
+         <idmap>
+             <uid start='0' target='100000' count='65535'/>
+             <gid start='0' target='100000' count='65535'/>
+         </idmap>
      </filesystem>
      <filesystem type='mount'>
          <driver type='virtiofs' queue='1024'/>
@@ -3697,6 +3701,10 @@ A directory on the host that can be accessed directly from the guest.
    Where the ``source`` can be accessed in the guest. For most drivers this is
    an automatic mount point, but for QEMU/KVM this is merely an arbitrary string
    tag that is exported to the guest as a hint for where to mount.
+``idmap``
+   For ``virtiofs``, an ``idmap`` element can be specified to map IDs in the user
+   namespace. See the `Container boot`_ section for the syntax of the element.
+   :since:`Since 10.0.0`
 ``readonly``
    Enables exporting filesystem as a readonly mount for guest, by default
    read-write access is given (currently only works for QEMU/KVM driver; not
index a70a1f29f2a904174e517cc684b5b75f7d5ce1ab..58a985fc5dbafc765abcc0fa004906749f8e86c3 100644 (file)
@@ -2588,6 +2588,8 @@ void virDomainFSDefFree(virDomainFSDef *def)
     virObjectUnref(def->privateData);
     g_free(def->binary);
     g_free(def->sock);
+    g_free(def->idmap.uidmap);
+    g_free(def->idmap.gidmap);
 
     g_free(def);
 }
@@ -8771,6 +8773,9 @@ virDomainFSDefParseXML(virDomainXMLOption *xmlopt,
         xmlNodePtr binary_lock_node = virXPathNode("./binary/lock", ctxt);
         xmlNodePtr binary_cache_node = virXPathNode("./binary/cache", ctxt);
         xmlNodePtr binary_sandbox_node = virXPathNode("./binary/sandbox", ctxt);
+        ssize_t n;
+        g_autofree xmlNodePtr *uid_nodes = NULL;
+        g_autofree xmlNodePtr *gid_nodes = NULL;
 
         if (queue_size && virStrToLong_ull(queue_size, NULL, 10, &def->queue_size) < 0) {
             virReportError(VIR_ERR_XML_ERROR,
@@ -8816,6 +8821,28 @@ virDomainFSDefParseXML(virDomainXMLOption *xmlopt,
                            VIR_XML_PROP_NONZERO,
                            &def->sandbox) < 0)
             goto error;
+
+        if ((n = virXPathNodeSet("./idmap/uid", ctxt, &uid_nodes)) < 0)
+            return NULL;
+
+        if (n) {
+            def->idmap.uidmap = virDomainIdmapDefParseXML(ctxt, uid_nodes, n);
+            if (!def->idmap.uidmap)
+                return NULL;
+
+            def->idmap.nuidmap = n;
+        }
+
+        if ((n = virXPathNodeSet("./idmap/gid", ctxt, &gid_nodes)) < 0)
+            return NULL;
+
+        if (n) {
+            def->idmap.gidmap = virDomainIdmapDefParseXML(ctxt, gid_nodes, n);
+            if (!def->idmap.gidmap)
+                return NULL;
+
+            def->idmap.ngidmap = n;
+        }
     }
 
     if (source == NULL && def->type != VIR_DOMAIN_FS_TYPE_RAM
@@ -23233,6 +23260,29 @@ virDomainFSDefFormat(virBuffer *buf,
     virXMLFormatElement(buf, "driver", &driverAttrBuf, &driverBuf);
     virXMLFormatElement(buf, "binary", &binaryAttrBuf, &binaryBuf);
 
+    if (def->idmap.uidmap) {
+        size_t i;
+
+        virBufferAddLit(buf, "<idmap>\n");
+        virBufferAdjustIndent(buf, 2);
+        for (i = 0; i < def->idmap.nuidmap; i++) {
+            virBufferAsprintf(buf,
+                              "<uid start='%u' target='%u' count='%u'/>\n",
+                              def->idmap.uidmap[i].start,
+                              def->idmap.uidmap[i].target,
+                              def->idmap.uidmap[i].count);
+        }
+        for (i = 0; i < def->idmap.ngidmap; i++) {
+            virBufferAsprintf(buf,
+                              "<gid start='%u' target='%u' count='%u'/>\n",
+                              def->idmap.gidmap[i].start,
+                              def->idmap.gidmap[i].target,
+                              def->idmap.gidmap[i].count);
+        }
+        virBufferAdjustIndent(buf, -2);
+        virBufferAddLit(buf, "</idmap>\n");
+    }
+
     switch (def->type) {
     case VIR_DOMAIN_FS_TYPE_MOUNT:
     case VIR_DOMAIN_FS_TYPE_BIND:
index 5a93ee0aee107f4812fb540f9f5c9f2a04e2917e..0c5e2636e1c35272fcdc12a097eb700fc2824415 100644 (file)
@@ -888,6 +888,7 @@ struct _virDomainFSDef {
     virTristateSwitch flock;
     virDomainFSSandboxMode sandbox;
     int thread_pool_size;
+    virDomainIdMapDef idmap;
     virDomainVirtioOptions *virtio;
     virObject *privateData;
 };
index b98a2ae60230a5860447d8bc94e271c51b6730df..f318c067976aa1501c528c0c816c7ecd129bf399 100644 (file)
               </choice>
               <empty/>
             </element>
+            <optional>
+              <ref name="idmap"/>
+            </optional>
             <ref name="filesystemCommon"/>
           </interleave>
         </group>
index 81de8c0dd7e98b228294fc9d94d2aea650abb8df..1d0bc26c46244d5a2cf3a30c0182c266b663908d 100644 (file)
         <lock posix='off' flock='off'/>
         <thread_pool size='16'/>
       </binary>
+      <idmap>
+        <uid start='0' target='100000' count='65535'/>
+        <gid start='0' target='100000' count='65535'/>
+      </idmap>
       <source dir='/path'/>
       <target dir='mount_tag'/>
       <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>