]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
vmspawn: reject --bind-volume= duplicates at parse time 41961/head
authorChristian Brauner <brauner@kernel.org>
Wed, 6 May 2026 10:40:26 +0000 (12:40 +0200)
committerChristian Brauner <brauner@kernel.org>
Wed, 6 May 2026 12:30:37 +0000 (14:30 +0200)
bind_volume_parse() does not look at peers, so passing the same
PROVIDER:VOLUME twice on the command line silently produces two parsed
entries in arg_bind_volumes. vmspawn_bind_volume_acquire() then builds
two DriveInfo with identical d->id ("<provider>:<volume>"). At boot,
bridge_register_drive() puts d->id into the b->block_devices hashmap;
the second insert returns -EEXIST and the user sees a bare "File
exists" with no context for which volume is responsible.

Reject the collision at the parse site with a linear scan over the
existing array — n_items is small (one entry per --bind-volume on the
command line), and a clear error message naming the offending volume
is much more useful than the late EEXIST from the QMP setup loop.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
src/vmspawn/vmspawn.c

index ee8ae518f03306d38e89fd181e9ad64709f52c52..57b7697079ee4d8ce1e39ab46c464ff2fd6b9d23 100644 (file)
@@ -787,6 +787,12 @@ static int parse_argv(int argc, char *argv[]) {
                                                        bv->config, valid);
                         }
 
+                        FOREACH_ARRAY(it, arg_bind_volumes.items, arg_bind_volumes.n_items)
+                                if (streq((*it)->provider, bv->provider) && streq((*it)->volume, bv->volume))
+                                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                                               "Volume '%s:%s' specified more than once for --bind-volume=.",
+                                                               bv->provider, bv->volume);
+
                         if (!GREEDY_REALLOC(arg_bind_volumes.items, arg_bind_volumes.n_items + 1))
                                 return log_oom();
                         arg_bind_volumes.items[arg_bind_volumes.n_items++] = TAKE_PTR(bv);