LXC domains with long file-backed filesystem path fail to start when
the backing image path is longer than LO_NAME_SIZE (64 bytes, 63 characters 
plus NUL).
When long file path is passed, virFileLoopDeviceAssociate() -> virStrcpy() fails
and user gets missleading error and domain fails to start.

Example:

    <filesystem type='file' accessmode='passthrough'>
      <driver type='loop' format='raw'/>
      <source 
file='/root/demoaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.raw'/>
      <target dir='/'/>
    </filesystem>

To match losetup behavior we copy the path with virStrcpy() and allow truncation
of lo_file_name only if needed, while still calling open() on the unchanged 
path.
Finally log VIR_WARN when the path is expected to be truncated. But still report
VIR_ERR_INTERNAL_ERROR for all other virStrcpy() failures.

Fixes: https://gitlab.com/libvirt/libvirt/-/work_items/63

Signed-off-by: Radoslaw Smigielski <[email protected]>
---
 src/util/virfile.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/src/util/virfile.c b/src/util/virfile.c
index a0c6cb804862..ae33deb8d223 100644
--- a/src/util/virfile.c
+++ b/src/util/virfile.c
@@ -995,11 +995,18 @@ int virFileLoopDeviceAssociate(const char *file,
 
     lo.lo_flags = LO_FLAGS_AUTOCLEAR;
 
-    /* Set backing file name for LOOP_GET_STATUS64 queries */
+    /* lo_file_name is loop device name, max length is LO_NAME_SIZE bytes.
+     * Truncate loop device name if file path is longer than LO_NAME_SIZE,
+     * and still use the full path to open backing file. */
     if (virStrcpy((char *) lo.lo_file_name, file, LO_NAME_SIZE) < 0) {
-        virReportSystemError(errno,
-                             _("Unable to set backing file %1$s"), file);
-        goto cleanup;
+        if (strlen(file) >= LO_NAME_SIZE) {
+            VIR_WARN("Loop backing device name %s truncated to %d bytes.",
+                     file, LO_NAME_SIZE);
+        } else {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("Unable to set loop lo_file_name for %1$s"), 
file);
+            goto cleanup;
+        }
     }
 
     if ((fsfd = open(file, O_RDWR)) < 0) {
-- 
2.54.0

Reply via email to